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 AT users.sourceforge.net> (2003-2006)
10 Bug Fixes - Raphael Neider <rneider AT web.de> (2004,2005)
11 Bug Fixes - Borut Razem <borut.razem AT siol.net> (2007)
13 This program is free software; you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by the
15 Free Software Foundation; either version 2, or (at your option) any
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 In other words, you are welcome to use, share and improve this program.
28 You are forbidden to forbid anyone else to use, share and improve
29 what you give them. Help stamp out software-hoarding!
32 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
33 Made everything static
34 -------------------------------------------------------------------------*/
40 #include "SDCCglobl.h"
44 #include "SDCCpeeph.h"
53 /* Set the following to 1 to enable the slower/bigger
54 * but more robust generic shifting routine (which also
55 * operates correctly with negative shift values). */
56 #define USE_GENERIC_SIGNED_SHIFT 1
58 /* Set the following to 1 to enable the new
59 * stripped down genCmp version.
60 * This version should be easier to understand,
61 * more reliable and (sigh) slighly slower. */
62 #define USE_SIMPLE_GENCMP 1
64 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
65 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
67 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
68 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
70 /* If you change these, you also have to update the library files
71 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
72 #define GPTR_TAG_DATA 0x80
73 #define GPTR_TAG_EEPROM 0x40
74 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
76 /* Wrapper to execute `code' at most once. */
77 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
79 void pic16_genMult8X8_n (operand *, operand *,operand *);
81 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
83 void pic16_genMult16X16_16(operand *, operand *, operand *);
84 void pic16_genMult32X32_32(operand *, operand *, operand *);
86 pCode *pic16_AssembleLine(char *line, int peeps);
87 extern void pic16_printpBlock(FILE *of, pBlock *pb);
88 static asmop *newAsmop (short type);
89 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
90 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
91 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
92 static pCodeOp *pic16_popRegFromIdx(int rIdx);
94 //static int aopIdx (asmop *aop, int offset);
96 int pic16_labelOffset=0;
97 extern int pic16_debug_verbose;
98 #if !(USE_GENERIC_SIGNED_SHIFT)
99 static int optimized_for_speed = 0;
108 /* max_key keeps track of the largest label number used in
109 a function. This is then used to adjust the label offset
110 for the next function.
112 static int max_key=0;
113 static int GpsuedoStkPtr=0;
115 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
117 const char *pic16_AopType(short type);
118 static iCode *ifxForOp ( operand *op, iCode *ic );
120 void pic16_pushpCodeOp(pCodeOp *pcop);
121 void pic16_poppCodeOp(pCodeOp *pcop);
123 static bool is_LitOp(operand *op);
124 static bool is_LitAOp(asmop *aop);
127 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
129 /* set the following macro to 1 to enable passing the
130 * first byte of functions parameters via WREG */
131 #define USE_WREG_IN_FUNC_PARAMS 0
134 /* this is the down and dirty file with all kinds of
135 kludgy & hacky stuff. This is what it is all about
136 CODE GENERATION for a specific MCU . some of the
137 routines may be reusable, will have to see */
139 static char *zero = "#0x00";
140 static char *one = "#0x01";
141 //static char *spname = "sp";
145 * Function return value policy (MSB-->LSB):
147 * 16 bits -> PRODL:WREG
148 * 24 bits -> PRODH:PRODL:WREG
149 * 32 bits -> FSR0L:PRODH:PRODL:WREG
150 * >32 bits -> on stack, and FSR0 points to the beginning
155 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
156 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
157 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
158 static char **fReturn = fReturnpic16;
160 static char *accUse[] = {"WREG"};
162 //static short rbank = -1;
176 bitVect *fregsUsed; /* registers used in function */
178 set *sregsAllocSet; /* registers used to store stack variables */
179 int stack_lat; /* stack offset latency */
181 int useWreg; /* flag when WREG is used to pass function parameter */
184 extern int pic16_ptrRegReq ;
185 extern int pic16_nRegs;
186 extern struct dbuf_s *codeOutBuf;
187 //static void saverbank (int, iCode *,bool);
189 static lineNode *lineHead = NULL;
190 static lineNode *lineCurr = NULL;
192 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
193 0xE0, 0xC0, 0x80, 0x00};
194 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
195 0x07, 0x03, 0x01, 0x00};
199 /*-----------------------------------------------------------------*/
200 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
201 /* exponent of 2 is returned, otherwise -1 is */
203 /* note that this is similar to the function `powof2' in SDCCsymt */
207 /*-----------------------------------------------------------------*/
208 int pic16_my_powof2 (unsigned long num)
211 if( (num & (num-1)) == 0) {
224 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
226 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
228 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
229 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
230 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
231 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
232 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
233 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
234 ((result) ? AOP_SIZE(result) : 0));
237 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
240 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
242 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
243 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
244 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
245 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
246 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
247 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
251 void pic16_emitpcomment (char *fmt, ...)
254 char lb[INITIAL_INLINEASM];
255 unsigned char *lbp = (unsigned char *)lb;
260 vsprintf(lb+1,fmt,ap);
262 while (isspace(*lbp)) lbp++;
265 lineCurr = (lineCurr ?
266 connectLine(lineCurr,newLineNode(lb)) :
267 (lineHead = newLineNode(lb)));
268 lineCurr->isInline = _G.inLine;
269 lineCurr->isDebug = _G.debugLine;
270 lineCurr->isComment = 1;
272 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
275 // fprintf(stderr, "%s\n", lb);
278 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
281 char lb[INITIAL_INLINEASM];
282 unsigned char *lbp = (unsigned char *)lb;
284 if(!pic16_debug_verbose)
291 sprintf(lb,"%s\t",inst);
293 sprintf(lb,"%s",inst);
294 vsprintf(lb+(strlen(lb)),fmt,ap);
298 while (isspace(*lbp)) lbp++;
301 lineCurr = (lineCurr ?
302 connectLine(lineCurr,newLineNode(lb)) :
303 (lineHead = newLineNode(lb)));
304 lineCurr->isInline = _G.inLine;
305 lineCurr->isDebug = _G.debugLine;
307 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
310 // fprintf(stderr, "%s\n", lb);
315 void pic16_emitpLabel(int key)
317 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
320 void pic16_emitpLabelFORCE(int key)
322 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
325 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
326 * NEVER call pic16_emitpcode_real directly, please... */
327 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
331 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
333 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
336 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
339 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
341 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
344 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
347 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
353 #define pic16_emitcode DEBUGpic16_emitcode
355 /*-----------------------------------------------------------------*/
356 /* pic16_emitcode - writes the code into a file : for now it is simple */
357 /*-----------------------------------------------------------------*/
358 void pic16_emitcode (char *inst,char *fmt, ...)
361 char lb[INITIAL_INLINEASM];
362 unsigned char *lbp = lb;
368 sprintf(lb,"%s\t",inst);
370 sprintf(lb,"%s",inst);
371 vsprintf(lb+(strlen(lb)),fmt,ap);
375 while (isspace(*lbp)) lbp++;
378 lineCurr = (lineCurr ?
379 connectLine(lineCurr,newLineNode(lb)) :
380 (lineHead = newLineNode(lb)));
381 lineCurr->isInline = _G.inLine;
382 lineCurr->isDebug = _G.debugLine;
383 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
384 lineCurr->isComment = (*lbp == ';');
386 // VR fprintf(stderr, "lb = <%s>\n", lbp);
388 // if(pic16_debug_verbose)
389 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
396 /*-----------------------------------------------------------------*/
397 /* pic16_emitDebuggerSymbol - associate the current code location */
398 /* with a debugger symbol */
399 /*-----------------------------------------------------------------*/
401 pic16_emitDebuggerSymbol (char * debugSym)
404 pic16_emitcode (";", "%s ==.", debugSym);
409 /*-----------------------------------------------------------------*/
410 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
411 /*-----------------------------------------------------------------*/
412 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
414 // bool r0iu = FALSE , r1iu = FALSE;
415 // bool r0ou = FALSE , r1ou = FALSE;
416 bool fsr0iu = FALSE, fsr0ou;
417 bool fsr2iu = FALSE, fsr2ou;
419 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
422 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
423 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
425 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
426 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
428 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
429 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
430 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
433 if(!fsr0iu && !fsr0ou) {
434 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
435 (*aopp)->type = AOP_FSR0;
437 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
439 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
443 /* no usage of FSR2 */
444 if(!fsr2iu && !fsr2ou) {
445 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
446 (*aopp)->type = AOP_FSR2;
448 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
452 /* now we know they both have usage */
453 /* if fsr0 not used in this instruction */
455 if (!_G.fsr0Pushed) {
456 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
457 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
461 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
462 (*aopp)->type = AOP_FSR0;
464 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
466 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
470 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
475 /* the logic: if r0 & r1 used in the instruction
476 then we are in trouble otherwise */
478 /* first check if r0 & r1 are used by this
479 instruction, in which case we are in trouble */
480 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
481 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
486 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
487 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
489 /* if no usage of r0 then return it */
490 if (!r0iu && !r0ou) {
491 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
492 (*aopp)->type = AOP_R0;
494 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
497 /* if no usage of r1 then return it */
498 if (!r1iu && !r1ou) {
499 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
500 (*aopp)->type = AOP_R1;
502 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
505 /* now we know they both have usage */
506 /* if r0 not used in this instruction */
508 /* push it if not already pushed */
510 //pic16_emitcode ("push","%s",
511 // pic16_regWithIdx(R0_IDX)->dname);
515 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
516 (*aopp)->type = AOP_R0;
518 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
521 /* if r1 not used then */
524 /* push it if not already pushed */
526 //pic16_emitcode ("push","%s",
527 // pic16_regWithIdx(R1_IDX)->dname);
531 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
532 (*aopp)->type = AOP_R1;
533 return pic16_regWithIdx(R1_IDX);
537 /* I said end of world but not quite end of world yet */
538 /* if this is a result then we can push it on the stack*/
540 (*aopp)->type = AOP_STK;
544 /* other wise this is true end of the world */
545 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
546 "getFreePtr should never reach here");
551 /*-----------------------------------------------------------------*/
552 /* newAsmop - creates a new asmOp */
553 /*-----------------------------------------------------------------*/
554 static asmop *newAsmop (short type)
558 aop = Safe_calloc(1,sizeof(asmop));
563 static void genSetDPTR(int n)
567 pic16_emitcode(";", "Select standard DPTR");
568 pic16_emitcode("mov", "dps, #0x00");
572 pic16_emitcode(";", "Select alternate DPTR");
573 pic16_emitcode("mov", "dps, #0x01");
577 /*-----------------------------------------------------------------*/
578 /* resolveIfx - converts an iCode ifx into a form more useful for */
579 /* generating code */
580 /*-----------------------------------------------------------------*/
581 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
585 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
591 resIfx->condition = 1; /* assume that the ifx is true */
592 resIfx->generated = 0; /* indicate that the ifx has not been used */
595 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
598 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
599 __FUNCTION__,__LINE__,resIfx->lbl->key);
604 resIfx->lbl = IC_TRUE(ifx);
606 resIfx->lbl = IC_FALSE(ifx);
607 resIfx->condition = 0;
612 DEBUGpic16_emitcode("; +++","ifx true is non-null");
614 DEBUGpic16_emitcode("; +++","ifx true is null");
616 DEBUGpic16_emitcode("; +++","ifx false is non-null");
618 DEBUGpic16_emitcode("; +++","ifx false is null");
622 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
626 /*-----------------------------------------------------------------*/
627 /* pointerCode - returns the code for a pointer type */
628 /*-----------------------------------------------------------------*/
629 static int pointerCode (sym_link *etype)
632 return PTR_TYPE(SPEC_OCLS(etype));
637 /*-----------------------------------------------------------------*/
638 /* aopForSym - for a true symbol */
639 /*-----------------------------------------------------------------*/
640 static asmop *aopForSym (iCode *ic, operand *op, bool result)
642 symbol *sym=OP_SYMBOL(op);
644 memmap *space= SPEC_OCLS(sym->etype);
648 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
650 // sym = OP_SYMBOL(op);
652 /* if already has one */
654 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
659 /* if symbol was initially placed onStack then we must re-place it
660 * to direct memory, since pic16 does not have a specific stack */
662 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
670 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
672 sym->aop = aop = newAsmop (AOP_PAGED);
673 aop->aopu.aop_dir = sym->rname ;
674 aop->size = getSize(sym->type);
675 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
676 pic16_allocDirReg( IC_LEFT(ic) );
684 /* assign depending on the storage class */
685 /* if it is on the stack or indirectly addressable */
686 /* space we need to assign either r0 or r1 to it */
687 if (sym->onStack) // || sym->iaccess)
692 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
693 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
695 /* acquire a temporary register -- it is saved in function */
697 sym->aop = aop = newAsmop(AOP_STA);
698 aop->aopu.stk.stk = sym->stack;
699 aop->size = getSize(sym->type);
702 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
703 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
704 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
705 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
707 for(i=0;i<aop->size;i++)
708 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
709 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
711 if(1 && ic->op == SEND) {
713 /* if SEND do the send here */
716 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
717 for(i=0;i<aop->size;i++) {
718 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
719 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
724 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
727 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
729 // we do not need to load the value if it is to be defined...
730 if (result) return aop;
733 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
736 for(i=0;i<aop->size;i++) {
738 /* initialise for stack access via frame pointer */
739 // operands on stack are accessible via "{FRAME POINTER} + index" with index
740 // starting at 2 for arguments and growing from 0 downwards for
741 // local variables (index == 0 is not assigned so we add one here)
743 int soffs = sym->stack;
749 if(1 && ic->op == SEND) {
750 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
751 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
752 pic16_popCopyReg( pic16_frame_plusw ),
753 pic16_popCopyReg(pic16_stack_postdec )));
755 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
756 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
757 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
763 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
770 /* now assign the address of the variable to
771 the pointer register */
772 if (aop->type != AOP_STK) {
776 pic16_emitcode("push","acc");
778 pic16_emitcode("mov","a,_bp");
779 pic16_emitcode("add","a,#0x%02x",
781 ((char)(sym->stack - _G.nRegsSaved )) :
782 ((char)sym->stack)) & 0xff);
783 pic16_emitcode("mov","%s,a",
784 aop->aopu.aop_ptr->name);
787 pic16_emitcode("pop","acc");
789 pic16_emitcode("mov","%s,#%s",
790 aop->aopu.aop_ptr->name,
792 aop->paged = space->paged;
794 aop->aopu.aop_stk = sym->stack;
802 if (sym->onStack && options.stack10bit)
804 /* It's on the 10 bit stack, which is located in
808 //DEBUGpic16_emitcode(";","%d",__LINE__);
811 pic16_emitcode("push","acc");
813 pic16_emitcode("mov","a,_bp");
814 pic16_emitcode("add","a,#0x%02x",
816 ((char)(sym->stack - _G.nRegsSaved )) :
817 ((char)sym->stack)) & 0xff);
820 pic16_emitcode ("mov","dpx1,#0x40");
821 pic16_emitcode ("mov","dph1,#0x00");
822 pic16_emitcode ("mov","dpl1, a");
826 pic16_emitcode("pop","acc");
828 sym->aop = aop = newAsmop(AOP_DPTR2);
829 aop->size = getSize(sym->type);
835 /* special case for a function */
836 if (IS_FUNC(sym->type)) {
837 sym->aop = aop = newAsmop(AOP_PCODE);
838 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
839 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
840 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
841 PCOI(aop->aopu.pcop)->index = 0;
842 aop->size = FPTRSIZE;
843 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
850 //DEBUGpic16_emitcode(";","%d",__LINE__);
851 /* if in bit space */
852 if (IN_BITSPACE(space)) {
853 sym->aop = aop = newAsmop (AOP_CRY);
854 aop->aopu.aop_dir = sym->rname ;
855 aop->size = getSize(sym->type);
856 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
859 /* if it is in direct space */
860 if (IN_DIRSPACE(space)) {
861 if(!strcmp(sym->rname, "_WREG")) {
862 sym->aop = aop = newAsmop (AOP_ACC);
863 aop->size = getSize(sym->type); /* should always be 1 */
864 assert(aop->size == 1);
865 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
868 sym->aop = aop = newAsmop (AOP_DIR);
869 aop->aopu.aop_dir = sym->rname ;
870 aop->size = getSize(sym->type);
871 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
872 pic16_allocDirReg( IC_LEFT(ic) );
877 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
878 sym->aop = aop = newAsmop (AOP_DIR);
879 aop->aopu.aop_dir = sym->rname ;
880 aop->size = getSize(sym->type);
881 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
882 pic16_allocDirReg( IC_LEFT(ic) );
887 /* only remaining is far space */
888 sym->aop = aop = newAsmop(AOP_PCODE);
890 /* change the next if to 1 to revert to good old immediate code */
891 if(IN_CODESPACE(space)) {
892 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
893 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
894 PCOI(aop->aopu.pcop)->index = 0;
896 /* try to allocate via direct register */
897 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
898 // aop->size = getSize( sym->type );
901 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
902 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
905 if(!pic16_allocDirReg (IC_LEFT(ic)))
909 if(IN_DIRSPACE( space ))
911 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
912 aop->size = FPTRSIZE;
913 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
914 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
915 else if(sym->onStack) {
918 if(SPEC_SCLS(sym->etype) == S_PDATA) {
919 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
920 aop->size = FPTRSIZE;
925 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
927 /* if it is in code space */
928 if (IN_CODESPACE(space))
934 /*-----------------------------------------------------------------*/
935 /* aopForRemat - rematerialzes an object */
936 /*-----------------------------------------------------------------*/
937 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
939 symbol *sym = OP_SYMBOL(op);
941 iCode *ic = NULL, *oldic;
942 asmop *aop = newAsmop(AOP_PCODE);
949 ic = sym->rematiCode;
951 if(IS_OP_POINTER(op)) {
952 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
955 // if(!result) /* fixme-vr */
959 // chat *iLine = printILine(ic);
960 // pic16_emitpcomment("ic: %s\n", iLine);
964 val += (int) operandLitValue(IC_RIGHT(ic));
965 } else if (ic->op == '-') {
966 val -= (int) operandLitValue(IC_RIGHT(ic));
970 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
973 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
976 if(!op->isaddr)viaimmd++; else viaimmd=0;
978 /* set the following if to 1 to revert to good old immediate code */
979 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
982 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
984 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
987 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
989 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
992 PCOI(aop->aopu.pcop)->index = val;
994 aop->size = getSize( sym->type );
996 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
998 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
999 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
1001 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
1005 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1006 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1008 val, IS_PTR_CONST(operandType(op)));
1010 val, IS_CODEPTR(operandType(op)));
1013 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1015 pic16_allocDirReg (IC_LEFT(ic));
1017 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1024 static int aopIdx (asmop *aop, int offset)
1029 if(aop->type != AOP_REG)
1032 return aop->aopu.aop_reg[offset]->rIdx;
1037 /*-----------------------------------------------------------------*/
1038 /* regsInCommon - two operands have some registers in common */
1039 /*-----------------------------------------------------------------*/
1040 static bool regsInCommon (operand *op1, operand *op2)
1042 symbol *sym1, *sym2;
1045 /* if they have registers in common */
1046 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1049 sym1 = OP_SYMBOL(op1);
1050 sym2 = OP_SYMBOL(op2);
1052 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1055 for (i = 0 ; i < sym1->nRegs ; i++) {
1060 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1064 if (sym2->regs[j] == sym1->regs[i])
1072 /*-----------------------------------------------------------------*/
1073 /* operandsEqu - equivalent */
1074 /*-----------------------------------------------------------------*/
1075 static bool operandsEqu ( operand *op1, operand *op2)
1077 symbol *sym1, *sym2;
1079 /* if they not symbols */
1080 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1083 sym1 = OP_SYMBOL(op1);
1084 sym2 = OP_SYMBOL(op2);
1086 /* if both are itemps & one is spilt
1087 and the other is not then false */
1088 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1089 sym1->isspilt != sym2->isspilt )
1092 /* if they are the same */
1096 if (sym1->rname[0] && sym2->rname[0]
1097 && strcmp (sym1->rname, sym2->rname) == 0)
1101 /* if left is a tmp & right is not */
1102 if (IS_ITEMP(op1) &&
1105 (sym1->usl.spillLoc == sym2))
1108 if (IS_ITEMP(op2) &&
1112 (sym2->usl.spillLoc == sym1))
1118 /*-----------------------------------------------------------------*/
1119 /* pic16_sameRegs - two asmops have the same registers */
1120 /*-----------------------------------------------------------------*/
1121 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1128 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1129 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1131 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1133 if (aop1->type != AOP_REG ||
1134 aop2->type != AOP_REG )
1137 /* This is a bit too restrictive if one is a subset of the other...
1138 if (aop1->size != aop2->size )
1142 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1143 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1145 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1146 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1153 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1155 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1156 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1158 if(aop1 == aop2)return TRUE;
1159 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1161 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1167 /*-----------------------------------------------------------------*/
1168 /* pic16_aopOp - allocates an asmop for an operand : */
1169 /*-----------------------------------------------------------------*/
1170 void pic16_aopOp (operand *op, iCode *ic, bool result)
1179 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1181 /* if this a literal */
1182 if (IS_OP_LITERAL(op)) {
1183 op->aop = aop = newAsmop(AOP_LIT);
1184 aop->aopu.aop_lit = op->operand.valOperand;
1185 aop->size = getSize(operandType(op));
1190 sym_link *type = operandType(op);
1192 if(IS_PTR_CONST(type))
1194 if(IS_CODEPTR(type))
1196 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1199 /* if already has a asmop then continue */
1203 /* if the underlying symbol has a aop */
1204 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1205 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1206 op->aop = OP_SYMBOL(op)->aop;
1210 /* if this is a true symbol */
1211 if (IS_TRUE_SYMOP(op)) {
1212 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1213 op->aop = aopForSym(ic, op, result);
1217 /* this is a temporary : this has
1223 e) can be a return use only */
1225 sym = OP_SYMBOL(op);
1227 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1228 /* if the type is a conditional */
1229 if (sym->regType == REG_CND) {
1230 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1235 /* if it is spilt then two situations
1237 b) has a spill location */
1238 if (sym->isspilt || sym->nRegs == 0) {
1240 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1241 DEBUGpic16_emitcode(";","%d",__LINE__);
1242 /* rematerialize it NOW */
1245 sym->aop = op->aop = aop = aopForRemat (op, result);
1246 // aop->size = getSize(sym->type);
1247 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1254 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1255 aop->size = getSize(sym->type);
1256 for ( i = 0 ; i < 1 ; i++ ) {
1257 aop->aopu.aop_str[i] = accUse[i];
1258 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1260 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1261 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1269 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1270 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1271 //pic16_allocDirReg (IC_LEFT(ic));
1272 aop->size = getSize(sym->type);
1277 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1278 aop->size = getSize(sym->type);
1279 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1280 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1282 DEBUGpic16_emitcode(";","%d",__LINE__);
1286 /* else spill location */
1287 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1288 /* force a new aop if sizes differ */
1289 sym->usl.spillLoc->aop = NULL;
1293 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1294 __FUNCTION__,__LINE__,
1295 sym->usl.spillLoc->rname,
1296 sym->rname, sym->usl.spillLoc->offset);
1299 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1300 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1301 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1304 sym->usl.spillLoc->offset, op);
1305 } else if (getSize(sym->type) <= 1) {
1306 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1307 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1308 assert (getSize(sym->type) <= 1);
1309 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1310 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1312 /* We need some kind of dummy area for getSize(sym->type) byte,
1313 * use WREG for all storage locations.
1314 * XXX: This only works if we are implementing a `dummy read',
1315 * the stored value will not be retrievable...
1316 * See #1503234 for a case requiring this. */
1317 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1318 aop->size = getSize(sym->type);
1319 for ( i = 0 ; i < aop->size ;i++)
1320 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1322 aop->size = getSize(sym->type);
1328 sym_link *type = operandType(op);
1330 if(IS_PTR_CONST(type))
1332 if(IS_CODEPTR(type))
1334 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1337 /* must be in a register */
1338 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1339 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1340 aop->size = sym->nRegs;
1341 for ( i = 0 ; i < sym->nRegs ;i++)
1342 aop->aopu.aop_reg[i] = sym->regs[i];
1345 /*-----------------------------------------------------------------*/
1346 /* pic16_freeAsmop - free up the asmop given to an operand */
1347 /*----------------------------------------------------------------*/
1348 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1365 /* depending on the asmop type only three cases need work AOP_RO
1366 , AOP_R1 && AOP_STK */
1368 switch (aop->type) {
1370 if (_G.fsr0Pushed ) {
1372 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1373 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1374 // pic16_emitcode ("pop","ar0");
1378 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1382 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1388 pic16_emitcode ("pop","ar0");
1392 bitVectUnSetBit(ic->rUsed,R0_IDX);
1398 pic16_emitcode ("pop","ar1");
1402 bitVectUnSetBit(ic->rUsed,R1_IDX);
1409 /* we must store the result on stack */
1410 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1411 // operands on stack are accessible via "FSR2 + index" with index
1412 // starting at 2 for arguments and growing from 0 downwards for
1413 // local variables (index == 0 is not assigned so we add one here)
1414 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1419 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1420 for(i=0;i<aop->size;i++) {
1421 /* initialise for stack access via frame pointer */
1422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1423 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1424 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1427 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1431 for(i=0;i<aop->size;i++) {
1432 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1434 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1435 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1436 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1443 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1444 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1445 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1446 deleteSetItem( &_G.sregsAllocSet, sr );
1457 int stk = aop->aopu.aop_stk + aop->size;
1458 bitVectUnSetBit(ic->rUsed,R0_IDX);
1459 bitVectUnSetBit(ic->rUsed,R1_IDX);
1461 getFreePtr(ic,&aop,FALSE);
1463 if (options.stack10bit)
1465 /* I'm not sure what to do here yet... */
1468 "*** Warning: probably generating bad code for "
1469 "10 bit stack mode.\n");
1473 pic16_emitcode ("mov","a,_bp");
1474 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1475 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1477 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1481 pic16_emitcode("pop","acc");
1482 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1484 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1487 pic16_freeAsmop(op,NULL,ic,TRUE);
1489 pic16_emitcode("pop","ar0");
1494 pic16_emitcode("pop","ar1");
1504 /* all other cases just dealloc */
1508 OP_SYMBOL(op)->aop = NULL;
1509 /* if the symbol has a spill */
1511 SPIL_LOC(op)->aop = NULL;
1516 /*-----------------------------------------------------------------*/
1517 /* pic16_aopGet - for fetching value of the aop */
1518 /*-----------------------------------------------------------------*/
1519 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1524 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1526 /* offset is greater than size then zero */
1527 if (offset > (aop->size - 1) &&
1528 aop->type != AOP_LIT)
1531 /* depending on type */
1532 switch (aop->type) {
1536 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1537 rs = Safe_calloc(1, strlen(s)+1);
1542 /* if we need to increment it */
1543 while (offset > aop->coff)
1545 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1549 while (offset < aop->coff)
1551 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1557 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1558 return (dname ? "acc" : "a");
1560 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1561 rs = Safe_calloc (1, strlen (s) + 1);
1569 sprintf (s,"%s",aop->aopu.aop_immd);
1572 sprintf(s,"(%s >> %d)",
1577 aop->aopu.aop_immd);
1578 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1579 rs = Safe_calloc(1,strlen(s)+1);
1585 sprintf(s,"(%s + %d)",
1588 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1590 sprintf(s,"%s",aop->aopu.aop_dir);
1591 rs = Safe_calloc(1,strlen(s)+1);
1596 return aop->aopu.aop_reg[offset]->name;
1599 return aop->aopu.aop_dir;
1602 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1603 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1605 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1606 rs = Safe_strdup("WREG");
1610 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1611 rs = Safe_calloc(1,strlen(s)+1);
1616 aop->coff = offset ;
1618 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1621 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1622 aop->type = AOP_ACC;
1623 return Safe_strdup("_WREG");
1625 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1627 return aop->aopu.aop_str[offset];
1631 pCodeOp *pcop = aop->aopu.pcop;
1632 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1634 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1635 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1637 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1639 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1642 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1645 rs = Safe_calloc(1,strlen(s)+1);
1651 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1653 sprintf(s,"(%s + %d)",
1657 sprintf(s,"%s",aop->aopu.aop_dir);
1658 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1659 rs = Safe_calloc(1,strlen(s)+1);
1665 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1669 // pCodeOp *pcop = aop->aop
1674 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1675 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1676 "aopget got unsupported aop->type");
1682 /* lock has the following meaning: When allocating temporary registers
1683 * for stack variables storage, the value of the temporary register is
1684 * saved on stack. Its value is restored at the end. This procedure is
1685 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1686 * a possibility that before a call to pic16_aopOp, a temporary register
1687 * is allocated for a while and it is freed after some time, this will
1688 * mess the stack and values will not be restored properly. So use lock=1
1689 * to allocate temporary registers used internally by the programmer, and
1690 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1691 * to inform the compiler developer about a possible bug. This is an internal
1692 * feature for developing the compiler -- VR */
1694 int _TempReg_lock = 0;
1695 /*-----------------------------------------------------------------*/
1696 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1697 /*-----------------------------------------------------------------*/
1698 pCodeOp *pic16_popGetTempReg(int lock)
1703 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1705 // werror(W_POSSBUG2, __FILE__, __LINE__);
1708 _TempReg_lock += lock;
1718 /* this code might seem better but it does the *same* job with
1719 * the old code, it all depends on ralloc.c to get a free/unused
1723 while(i < pic16_nRegs) {
1724 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1725 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1726 if((!rr || (rr && rr->isFree))
1727 && !bitVectBitValue(cfunc->regsUsed, i)) {
1728 pcop = pic16_newpCodeOpReg( i );
1729 PCOR(pcop)->r->wasUsed = 1;
1730 PCOR(pcop)->r->isFree = 0;
1737 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1742 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1743 PCOR(pcop)->r->wasUsed=1;
1744 PCOR(pcop)->r->isFree=0;
1746 /* push value on stack */
1747 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1758 /* is not part of f, but don't save if */
1760 /*-----------------------------------------------------------------*/
1761 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1767 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1770 // werror(W_POSSBUG2, __FILE__, __LINE__);
1773 _TempReg_lock += lock;
1778 i = bitVectFirstBit(f);
1781 /* bypass registers that are used by function */
1782 if(!bitVectBitValue(f, i)) {
1784 /* bypass registers that are already allocated for stack access */
1785 if(!bitVectBitValue(v, i)) {
1787 // debugf("getting register rIdx = %d\n", i);
1788 /* ok, get the operand */
1789 pcop = pic16_newpCodeOpReg( i );
1791 /* should never by NULL */
1792 assert( pcop != NULL );
1796 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1799 PCOR(pcop)->r->wasUsed=1;
1800 PCOR(pcop)->r->isFree=0;
1806 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1808 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1809 /* already used in previous steps, break */
1816 /* caller takes care of the following */
1817 // bitVectSetBit(v, i);
1820 /* push value on stack */
1821 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1822 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1840 /*-----------------------------------------------------------------*/
1841 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1845 _TempReg_lock -= lock;
1847 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1848 PCOR(pcop)->r->isFree = 1;
1850 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1853 /*-----------------------------------------------------------------*/
1854 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1855 /*-----------------------------------------------------------------*/
1856 pCodeOp *pic16_popGetLabel(int key)
1859 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1864 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1867 /*-----------------------------------------------------------------*/
1868 /* pic16_popCopyReg - copy a pcode operator */
1869 /*-----------------------------------------------------------------*/
1870 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1874 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1875 memcpy (pcor, pc, sizeof (pCodeOpReg));
1876 pcor->r->wasUsed = 1;
1878 //pcor->pcop.type = pc->pcop.type;
1880 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1881 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1883 pcor->pcop.name = NULL;
1886 //pcor->rIdx = pc->rIdx;
1887 //pcor->r->wasUsed=1;
1888 //pcor->instance = pc->instance;
1890 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1895 /*-----------------------------------------------------------------*/
1896 /* pic16_popGetLit - asm operator to pcode operator conversion */
1897 /*-----------------------------------------------------------------*/
1898 pCodeOp *pic16_popGetLit(int lit)
1900 return pic16_newpCodeOpLit(lit);
1903 /* Allow for 12 bit literals (LFSR x, <here!>). */
1904 pCodeOp *pic16_popGetLit12(int lit)
1906 return pic16_newpCodeOpLit12(lit);
1909 /*-----------------------------------------------------------------*/
1910 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1911 /*-----------------------------------------------------------------*/
1912 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1914 return pic16_newpCodeOpLit2(lit, arg2);
1918 /*-----------------------------------------------------------------*/
1919 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1920 /*-----------------------------------------------------------------*/
1921 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1923 return pic16_newpCodeOpImmd(name, offset,index, 0);
1927 /*-----------------------------------------------------------------*/
1928 /* pic16_popGet - asm operator to pcode operator conversion */
1929 /*-----------------------------------------------------------------*/
1930 pCodeOp *pic16_popGetWithString(char *str)
1936 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1940 pcop = pic16_newpCodeOp(str,PO_STR);
1945 /*-----------------------------------------------------------------*/
1946 /* pic16_popRegFromString - */
1947 /*-----------------------------------------------------------------*/
1948 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1951 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1952 pcop->type = PO_DIR;
1954 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1955 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1960 pcop->name = Safe_calloc(1,strlen(str)+1);
1961 strcpy(pcop->name,str);
1963 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1965 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1966 // PCOR(pcop)->r->wasUsed = 1;
1968 /* make sure that register doesn't exist,
1969 * and operand isn't NULL
1970 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1971 if((PCOR(pcop)->r == NULL)
1973 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1974 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1975 // __FUNCTION__, __LINE__, str, size, offset);
1977 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1978 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1981 PCOR(pcop)->instance = offset;
1986 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1990 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1991 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1993 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1994 PCOR(pcop)->rIdx = rIdx;
1995 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1997 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1999 PCOR(pcop)->r->isFree = 0;
2000 PCOR(pcop)->r->wasUsed = 1;
2002 pcop->type = PCOR(pcop)->r->pc_type;
2007 /*---------------------------------------------------------------------------------*/
2008 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2010 /*---------------------------------------------------------------------------------*/
2011 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2013 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2014 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2020 /*--------------------------------------------------------------------------------.-*/
2021 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2022 /* VR 030601 , adapted by Hans Dorn */
2023 /*--------------------------------------------------------------------------------.-*/
2024 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2027 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2031 /*---------------------------------------------------------------------------------*/
2032 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2033 /* movff instruction */
2034 /*---------------------------------------------------------------------------------*/
2035 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2037 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2038 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2044 /*-----------------------------------------------------------------*/
2045 /* pic16_popGet - asm operator to pcode operator conversion */
2046 /*-----------------------------------------------------------------*/
2047 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2049 // char *s = buffer ;
2055 /* offset is greater than size then zero */
2057 // if (offset > (aop->size - 1) &&
2058 // aop->type != AOP_LIT)
2059 // return NULL; //zero;
2061 /* depending on type */
2062 switch (aop->type) {
2067 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2068 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2074 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2075 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2076 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2077 PCOR(pcop)->r->wasUsed = 1;
2078 PCOR(pcop)->r->isFree = 0;
2080 PCOR(pcop)->instance = offset;
2081 pcop->type = PCOR(pcop)->r->pc_type;
2085 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2086 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2089 /* pCodeOp is already allocated from aopForSym */
2090 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2091 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2096 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2098 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2100 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2102 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2103 PCOR(pcop)->rIdx = rIdx;
2104 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2105 PCOR(pcop)->r->wasUsed=1;
2106 PCOR(pcop)->r->isFree=0;
2108 PCOR(pcop)->instance = offset;
2109 pcop->type = PCOR(pcop)->r->pc_type;
2110 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2114 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2115 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2121 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2122 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2126 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2127 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2134 // debugf2("aop = %p\toffset = %d\n", aop, offset);
2135 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
2136 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2138 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2140 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2141 // pcop->type = PO_GPR_REGISTER;
2142 PCOR(pcop)->rIdx = rIdx;
2143 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2144 PCOR(pcop)->r->wasUsed=1;
2145 PCOR(pcop)->r->isFree=0;
2147 PCOR(pcop)->instance = offset;
2148 pcop->type = PCOR(pcop)->r->pc_type;
2150 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2151 // rs = aop->aopu.aop_reg[offset]->name;
2152 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2157 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2159 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2160 PCOR(pcop)->instance = offset;
2161 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2162 //if(PCOR(pcop)->r == NULL)
2163 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2167 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2168 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2171 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2172 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2175 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2176 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2177 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2178 pcop->type = PCOR(pcop)->r->pc_type;
2179 pcop->name = PCOR(pcop)->r->name;
2185 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2187 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2188 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2189 switch( aop->aopu.pcop->type ) {
2190 case PO_DIR: PCOR(pcop)->instance += offset; break;
2191 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2196 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2197 assert( 0 ); /* should never reach here */;
2202 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2203 "pic16_popGet got unsupported aop->type");
2206 /*-----------------------------------------------------------------*/
2207 /* pic16_aopPut - puts a string for a aop */
2208 /*-----------------------------------------------------------------*/
2209 void pic16_aopPut (asmop *aop, char *s, int offset)
2216 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2218 if (aop->size && offset > ( aop->size - 1)) {
2219 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2220 "pic16_aopPut got offset > aop->size");
2224 /* will assign value to value */
2225 /* depending on where it is ofcourse */
2226 switch (aop->type) {
2229 sprintf(d,"(%s + %d)",
2230 aop->aopu.aop_dir,offset);
2231 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2234 sprintf(d,"%s",aop->aopu.aop_dir);
2237 DEBUGpic16_emitcode(";","%d",__LINE__);
2239 pic16_emitcode("movf","%s,w",s);
2240 pic16_emitcode("movwf","%s",d);
2243 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2244 if(offset >= aop->size) {
2245 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2248 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2251 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2258 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2259 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2262 strcmp(s,"r0") == 0 ||
2263 strcmp(s,"r1") == 0 ||
2264 strcmp(s,"r2") == 0 ||
2265 strcmp(s,"r3") == 0 ||
2266 strcmp(s,"r4") == 0 ||
2267 strcmp(s,"r5") == 0 ||
2268 strcmp(s,"r6") == 0 ||
2269 strcmp(s,"r7") == 0 )
2270 pic16_emitcode("mov","%s,%s ; %d",
2271 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2275 if(strcmp(s,"W")==0 )
2276 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2278 pic16_emitcode("movwf","%s",
2279 aop->aopu.aop_reg[offset]->name);
2281 if(strcmp(s,zero)==0) {
2282 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2284 } else if(strcmp(s,"W")==0) {
2285 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2286 pcop->type = PO_GPR_REGISTER;
2288 PCOR(pcop)->rIdx = -1;
2289 PCOR(pcop)->r = NULL;
2291 DEBUGpic16_emitcode(";","%d",__LINE__);
2292 pcop->name = Safe_strdup(s);
2293 pic16_emitpcode(POC_MOVFW,pcop);
2294 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2295 } else if(strcmp(s,one)==0) {
2296 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2297 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2299 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2307 if (aop->type == AOP_DPTR2)
2313 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2314 "pic16_aopPut writting to code space");
2318 while (offset > aop->coff) {
2320 pic16_emitcode ("inc","dptr");
2323 while (offset < aop->coff) {
2325 pic16_emitcode("lcall","__decdptr");
2330 /* if not in accumulater */
2333 pic16_emitcode ("movx","@dptr,a");
2335 if (aop->type == AOP_DPTR2)
2343 while (offset > aop->coff) {
2345 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2347 while (offset < aop->coff) {
2349 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2355 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2360 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2362 if (strcmp(s,"r0") == 0 ||
2363 strcmp(s,"r1") == 0 ||
2364 strcmp(s,"r2") == 0 ||
2365 strcmp(s,"r3") == 0 ||
2366 strcmp(s,"r4") == 0 ||
2367 strcmp(s,"r5") == 0 ||
2368 strcmp(s,"r6") == 0 ||
2369 strcmp(s,"r7") == 0 ) {
2371 sprintf(buffer,"a%s",s);
2372 pic16_emitcode("mov","@%s,%s",
2373 aop->aopu.aop_ptr->name,buffer);
2375 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2380 if (strcmp(s,"a") == 0)
2381 pic16_emitcode("push","acc");
2383 pic16_emitcode("push","%s",s);
2388 /* if bit variable */
2389 if (!aop->aopu.aop_dir) {
2390 pic16_emitcode("clr","a");
2391 pic16_emitcode("rlc","a");
2394 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2397 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2400 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2402 lbl = newiTempLabel(NULL);
2404 if (strcmp(s,"a")) {
2407 pic16_emitcode("clr","c");
2408 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2409 pic16_emitcode("cpl","c");
2410 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2411 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2418 if (strcmp(aop->aopu.aop_str[offset],s))
2419 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2424 if (!offset && (strcmp(s,"acc") == 0))
2427 if (strcmp(aop->aopu.aop_str[offset],s))
2428 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2432 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2433 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2434 // "pic16_aopPut got unsupported aop->type");
2440 /*-----------------------------------------------------------------*/
2441 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2442 /*-----------------------------------------------------------------*/
2443 void pic16_mov2w (asmop *aop, int offset)
2445 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2448 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2450 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2453 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2455 if(is_LitAOp(src)) {
2456 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2457 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2459 if(pic16_sameRegsOfs(src, dst, offset))return;
2460 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2461 pic16_popGet(dst, offset)));
2465 static void pic16_movLit2f(pCodeOp *pc, int lit)
2467 if (0 == (lit & 0x00ff))
2469 pic16_emitpcode (POC_CLRF, pc);
2470 } else if (0xff == (lit & 0x00ff))
2472 pic16_emitpcode (POC_SETF, pc);
2474 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2475 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2479 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2481 if(is_LitAOp(src)) {
2482 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2483 pic16_emitpcode(POC_MOVWF, dst);
2485 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2489 void pic16_testStackOverflow(void)
2491 #define GSTACK_TEST_NAME "_gstack_test"
2493 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2498 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2499 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2500 // strcpy(sym->rname, GSTACK_TEST_NAME);
2501 checkAddSym(&externs, sym);
2506 /* push pcop into stack */
2507 void pic16_pushpCodeOp(pCodeOp *pcop)
2509 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2510 if (pcop->type == PO_LITERAL) {
2511 pic16_emitpcode(POC_MOVLW, pcop);
2512 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2514 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2516 if(pic16_options.gstack)
2517 pic16_testStackOverflow();
2521 /* pop pcop from stack */
2522 void pic16_poppCodeOp(pCodeOp *pcop)
2524 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2525 if(pic16_options.gstack)
2526 pic16_testStackOverflow();
2530 /*-----------------------------------------------------------------*/
2531 /* pushw - pushes wreg to stack */
2532 /*-----------------------------------------------------------------*/
2535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2536 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2537 if(pic16_options.gstack)
2538 pic16_testStackOverflow();
2542 /*-----------------------------------------------------------------*/
2543 /* pushaop - pushes aop to stack */
2544 /*-----------------------------------------------------------------*/
2545 void pushaop(asmop *aop, int offset)
2547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2549 if(_G.resDirect)return;
2551 if(is_LitAOp(aop)) {
2552 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2553 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2555 pic16_emitpcode(POC_MOVFF,
2556 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2559 if(pic16_options.gstack)
2560 pic16_testStackOverflow();
2563 /*-----------------------------------------------------------------*/
2564 /* popaop - pops aop from stack */
2565 /*-----------------------------------------------------------------*/
2566 void popaop(asmop *aop, int offset)
2568 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2569 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2570 if(pic16_options.gstack)
2571 pic16_testStackOverflow();
2574 void popaopidx(asmop *aop, int offset, int index)
2578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2580 if(STACK_MODEL_LARGE)ofs++;
2582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2583 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2584 if(pic16_options.gstack)
2585 pic16_testStackOverflow();
2588 #if !(USE_GENERIC_SIGNED_SHIFT)
2589 /*-----------------------------------------------------------------*/
2590 /* reAdjustPreg - points a register back to where it should */
2591 /*-----------------------------------------------------------------*/
2592 static void reAdjustPreg (asmop *aop)
2596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2598 if ((size = aop->size) <= 1)
2601 switch (aop->type) {
2605 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2609 if (aop->type == AOP_DPTR2)
2615 pic16_emitcode("lcall","__decdptr");
2618 if (aop->type == AOP_DPTR2)
2630 /*-----------------------------------------------------------------*/
2631 /* opIsGptr: returns non-zero if the passed operand is */
2632 /* a generic pointer type. */
2633 /*-----------------------------------------------------------------*/
2634 static int opIsGptr(operand *op)
2636 sym_link *type = operandType(op);
2638 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2639 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2647 /*-----------------------------------------------------------------*/
2648 /* pic16_getDataSize - get the operand data size */
2649 /*-----------------------------------------------------------------*/
2650 int pic16_getDataSize(operand *op)
2652 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2655 return AOP_SIZE(op);
2657 // tsd- in the pic port, the genptr size is 1, so this code here
2658 // fails. ( in the 8051 port, the size was 4).
2661 size = AOP_SIZE(op);
2662 if (size == GPTRSIZE)
2664 sym_link *type = operandType(op);
2665 if (IS_GENPTR(type))
2667 /* generic pointer; arithmetic operations
2668 * should ignore the high byte (pointer type).
2671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outAcc - output Acc */
2680 /*-----------------------------------------------------------------*/
2681 void pic16_outAcc(operand *result)
2684 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2685 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2688 size = pic16_getDataSize(result);
2690 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2693 /* unsigned or positive */
2695 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2700 /*-----------------------------------------------------------------*/
2701 /* pic16_outBitC - output a bit C */
2702 /* Move to result the value of Carry flag -- VR */
2703 /*-----------------------------------------------------------------*/
2704 void pic16_outBitC(operand *result)
2708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2710 /* if the result is bit */
2711 if (AOP_TYPE(result) == AOP_CRY) {
2712 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2713 pic16_aopPut(AOP(result),"c",0);
2716 i = AOP_SIZE(result);
2718 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2720 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2724 /*-----------------------------------------------------------------*/
2725 /* pic16_outBitOp - output a bit from Op */
2726 /* Move to result the value of set/clr op -- VR */
2727 /*-----------------------------------------------------------------*/
2728 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2734 /* if the result is bit */
2735 if (AOP_TYPE(result) == AOP_CRY) {
2736 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2737 pic16_aopPut(AOP(result),"c",0);
2740 i = AOP_SIZE(result);
2742 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2744 pic16_emitpcode(POC_RRCF, pcop);
2745 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2749 /*-----------------------------------------------------------------*/
2750 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2751 /*-----------------------------------------------------------------*/
2752 void pic16_toBoolean(operand *oper)
2754 int size = AOP_SIZE(oper) - 1;
2757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2759 if ( AOP_TYPE(oper) != AOP_ACC) {
2760 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2763 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2767 /*-----------------------------------------------------------------*/
2768 /* genUminusFloat - unary minus for floating points */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminusFloat(operand *op,operand *result)
2772 int size ,offset =0 ;
2775 /* for this we just need to flip the
2776 first it then copy the rest in place */
2777 size = AOP_SIZE(op);
2778 assert( size == AOP_SIZE(result) );
2781 pic16_mov2f(AOP(result), AOP(op), offset);
2785 /* toggle the MSB's highest bit */
2786 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2789 /*-----------------------------------------------------------------*/
2790 /* genUminus - unary minus code generation */
2791 /*-----------------------------------------------------------------*/
2792 static void genUminus (iCode *ic)
2795 sym_link *optype, *rtype;
2802 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2803 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2805 /* if both in bit space then special case */
2806 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2807 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2809 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2810 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2811 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2815 optype = operandType(IC_LEFT(ic));
2816 rtype = operandType(IC_RESULT(ic));
2819 /* if float then do float stuff */
2820 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2821 if(IS_FIXED(optype))
2822 debugf("implement fixed16x16 type\n", 0);
2824 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2828 /* otherwise subtract from zero by taking the 2's complement */
2829 size = AOP_SIZE(IC_LEFT(ic));
2830 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2831 label = newiTempLabel ( NULL );
2833 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2834 for (i=size-1; i > 0; i--) {
2835 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2837 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2838 for (i=1; i < size; i++) {
2839 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2840 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2843 for (i=size-1; i >= 0; i--) {
2844 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2848 for (i=0; i < size-2; i++) {
2849 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2850 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2852 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2854 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2857 pic16_emitpLabel (label->key);
2860 /* release the aops */
2861 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2862 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2866 /*-----------------------------------------------------------------*/
2867 /* saveRegisters - will look for a call and save the registers */
2868 /*-----------------------------------------------------------------*/
2869 static void saveRegisters(iCode *lic)
2876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2878 for (ic = lic ; ic ; ic = ic->next)
2879 if (ic->op == CALL || ic->op == PCALL)
2883 fprintf(stderr,"found parameter push with no function call\n");
2887 /* if the registers have been saved already then
2889 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2892 /* find the registers in use at this time
2893 and push them away to safety */
2894 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2898 if (options.useXstack) {
2899 if (bitVectBitValue(rsave,R0_IDX))
2900 pic16_emitcode("mov","b,r0");
2901 pic16_emitcode("mov","r0,%s",spname);
2902 for (i = 0 ; i < pic16_nRegs ; i++) {
2903 if (bitVectBitValue(rsave,i)) {
2905 pic16_emitcode("mov","a,b");
2907 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2908 pic16_emitcode("movx","@r0,a");
2909 pic16_emitcode("inc","r0");
2912 pic16_emitcode("mov","%s,r0",spname);
2913 if (bitVectBitValue(rsave,R0_IDX))
2914 pic16_emitcode("mov","r0,b");
2916 //for (i = 0 ; i < pic16_nRegs ; i++) {
2917 // if (bitVectBitValue(rsave,i))
2918 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2921 dtype = operandType(IC_LEFT(ic));
2922 if (currFunc && dtype &&
2923 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2924 IFFUNC_ISISR(currFunc->type) &&
2927 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2930 /*-----------------------------------------------------------------*/
2931 /* unsaveRegisters - pop the pushed registers */
2932 /*-----------------------------------------------------------------*/
2933 static void unsaveRegisters (iCode *ic)
2938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2939 /* find the registers in use at this time
2940 and push them away to safety */
2941 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2944 if (options.useXstack) {
2945 pic16_emitcode("mov","r0,%s",spname);
2946 for (i = pic16_nRegs ; i >= 0 ; i--) {
2947 if (bitVectBitValue(rsave,i)) {
2948 pic16_emitcode("dec","r0");
2949 pic16_emitcode("movx","a,@r0");
2951 pic16_emitcode("mov","b,a");
2953 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2957 pic16_emitcode("mov","%s,r0",spname);
2958 if (bitVectBitValue(rsave,R0_IDX))
2959 pic16_emitcode("mov","r0,b");
2961 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2962 // if (bitVectBitValue(rsave,i))
2963 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2970 /*-----------------------------------------------------------------*/
2972 /*-----------------------------------------------------------------*/
2973 static void pushSide(operand * oper, int size)
2976 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2978 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2979 if (AOP_TYPE(oper) != AOP_REG &&
2980 AOP_TYPE(oper) != AOP_DIR &&
2982 pic16_emitcode("mov","a,%s",l);
2983 pic16_emitcode("push","acc");
2985 pic16_emitcode("push","%s",l);
2990 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2992 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2993 pic16_emitpcode(POC_MOVFW, src);
2994 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2996 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2997 src, pic16_popGet(AOP(op), offset)));
3002 /*-----------------------------------------------------------------*/
3003 /* assignResultValue - assign results to oper, rescall==1 is */
3004 /* called from genCall() or genPcall() */
3005 /*-----------------------------------------------------------------*/
3006 static void assignResultValue(operand * oper, int res_size, int rescall)
3008 int size = AOP_SIZE(oper);
3012 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3013 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3016 /* assign result from a call/pcall function() */
3018 /* function results are stored in a special order,
3019 * see top of file with Function return policy, or manual */
3022 /* 8-bits, result in WREG */
3023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3025 if(size > 1 && res_size > 1) {
3026 /* 16-bits, result in PRODL:WREG */
3027 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3030 if(size > 2 && res_size > 2) {
3031 /* 24-bits, result in PRODH:PRODL:WREG */
3032 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3035 if(size > 3 && res_size > 3) {
3036 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3037 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3040 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3043 /* >32-bits, result on stack, and FSR0 points to beginning.
3044 * Fix stack when done */
3046 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3048 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3049 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3051 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3056 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3057 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3058 if(STACK_MODEL_LARGE) {
3060 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3064 int areg = 0; /* matching argument register */
3066 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3067 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3070 /* its called from genReceive (probably) -- VR */
3071 /* I hope this code will not be called from somewhere else in the future!
3072 * We manually set the pseudo stack pointer in genReceive. - dw
3074 if(!GpsuedoStkPtr && _G.useWreg) {
3075 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3077 /* The last byte in the assignment is in W */
3078 if(areg <= GpsuedoStkPtr) {
3080 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3082 // debugf("receive from WREG\n", 0);
3084 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3087 _G.stack_lat = AOP_SIZE(oper)-1;
3092 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3093 // debugf("receive from STACK\n", 0);
3100 /*-----------------------------------------------------------------*/
3101 /* genIpush - generate code for pushing this gets a little complex */
3102 /*-----------------------------------------------------------------*/
3103 static void genIpush (iCode *ic)
3105 // int size, offset=0;
3108 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3111 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3113 /* send to stack as normal */
3114 addSet(&_G.sendSet,ic);
3115 // addSetHead(&_G.sendSet,ic);
3116 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3121 int size, offset = 0 ;
3125 /* if this is not a parm push : ie. it is spill push
3126 and spill push is always done on the local stack */
3127 if (!ic->parmPush) {
3129 /* and the item is spilt then do nothing */
3130 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3133 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3134 size = AOP_SIZE(IC_LEFT(ic));
3135 /* push it on the stack */
3137 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3142 pic16_emitcode("push","%s",l);
3147 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3151 /*-----------------------------------------------------------------*/
3152 /* genIpop - recover the registers: can happen only for spilling */
3153 /*-----------------------------------------------------------------*/
3154 static void genIpop (iCode *ic)
3157 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3162 /* if the temp was not pushed then */
3163 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3166 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3167 size = AOP_SIZE(IC_LEFT(ic));
3170 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3173 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3178 /*-----------------------------------------------------------------*/
3179 /* unsaverbank - restores the resgister bank from stack */
3180 /*-----------------------------------------------------------------*/
3181 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3183 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3191 if (options.useXstack) {
3193 r = getFreePtr(ic,&aop,FALSE);
3196 pic16_emitcode("mov","%s,_spx",r->name);
3197 pic16_emitcode("movx","a,@%s",r->name);
3198 pic16_emitcode("mov","psw,a");
3199 pic16_emitcode("dec","%s",r->name);
3202 pic16_emitcode ("pop","psw");
3205 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3206 if (options.useXstack) {
3207 pic16_emitcode("movx","a,@%s",r->name);
3208 //pic16_emitcode("mov","(%s+%d),a",
3209 // regspic16[i].base,8*bank+regspic16[i].offset);
3210 pic16_emitcode("dec","%s",r->name);
3213 pic16_emitcode("pop",""); //"(%s+%d)",
3214 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3217 if (options.useXstack) {
3219 pic16_emitcode("mov","_spx,%s",r->name);
3220 pic16_freeAsmop(NULL,aop,ic,TRUE);
3226 /*-----------------------------------------------------------------*/
3227 /* saverbank - saves an entire register bank on the stack */
3228 /*-----------------------------------------------------------------*/
3229 static void saverbank (int bank, iCode *ic, bool pushPsw)
3231 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3238 if (options.useXstack) {
3241 r = getFreePtr(ic,&aop,FALSE);
3242 pic16_emitcode("mov","%s,_spx",r->name);
3246 for (i = 0 ; i < pic16_nRegs ;i++) {
3247 if (options.useXstack) {
3248 pic16_emitcode("inc","%s",r->name);
3249 //pic16_emitcode("mov","a,(%s+%d)",
3250 // regspic16[i].base,8*bank+regspic16[i].offset);
3251 pic16_emitcode("movx","@%s,a",r->name);
3253 pic16_emitcode("push","");// "(%s+%d)",
3254 //regspic16[i].base,8*bank+regspic16[i].offset);
3258 if (options.useXstack) {
3259 pic16_emitcode("mov","a,psw");
3260 pic16_emitcode("movx","@%s,a",r->name);
3261 pic16_emitcode("inc","%s",r->name);
3262 pic16_emitcode("mov","_spx,%s",r->name);
3263 pic16_freeAsmop (NULL,aop,ic,TRUE);
3266 pic16_emitcode("push","psw");
3268 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3276 static int wparamCmp(void *p1, void *p2)
3278 return (!strcmp((char *)p1, (char *)p2));
3281 int inWparamList(char *s)
3283 return isinSetWith(wparamList, s, wparamCmp);
3287 /*-----------------------------------------------------------------*/
3288 /* genCall - generates a call statement */
3289 /*-----------------------------------------------------------------*/
3290 static void genCall (iCode *ic)
3300 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3301 /* if caller saves & we have not saved then */
3302 // if (!ic->regsSaved)
3303 // saveRegisters(ic);
3305 /* initialise stackParms for IPUSH pushes */
3306 // stackParms = psuedoStkPtr;
3307 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3308 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3309 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3312 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3315 /* if send set is not empty the assign */
3318 int psuedoStkPtr=-1;
3319 int firstTimeThruLoop = 1;
3322 /* reverse sendSet if function is not reentrant */
3323 if(!IFFUNC_ISREENT(ftype))
3324 _G.sendSet = reverseSet(_G.sendSet);
3326 /* First figure how many parameters are getting passed */
3330 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3334 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3335 size = AOP_SIZE(IC_LEFT(sic));
3339 /* pass the last byte through WREG */
3343 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3344 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3345 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3347 if(!firstTimeThruLoop) {
3348 /* If this is not the first time we've been through the loop
3349 * then we need to save the parameter in a temporary
3350 * register. The last byte of the last parameter is
3354 // --psuedoStkPtr; // sanity check
3358 firstTimeThruLoop=0;
3360 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3365 /* all arguments are passed via stack */
3369 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3370 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3371 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3373 // pushaop(AOP(IC_LEFT(sic)), size);
3374 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3381 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3385 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3386 pushw(); /* save last parameter to stack if functions has varargs */
3390 } else use_wreg = 0;
3392 _G.stackRegSet = _G.sendSet;
3397 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3401 /* if we need to assign a result value */
3402 if ((IS_ITEMP(IC_RESULT(ic))
3403 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3404 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3405 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3408 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3411 /* Must not assign an 8-bit result to a 16-bit variable;
3412 * this would use (used...) the uninitialized PRODL! */
3413 /* FIXME: Need a proper way to obtain size of function result type,
3414 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3415 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3417 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3418 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3420 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3423 if(!stackParms && ic->parmBytes) {
3424 stackParms = ic->parmBytes;
3427 stackParms -= use_wreg;
3430 if(stackParms == 1) {
3431 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3433 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3434 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3436 if(STACK_MODEL_LARGE) {
3438 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3443 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3446 /* adjust the stack for parameters if required */
3447 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3450 /* if register bank was saved then pop them */
3452 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3454 /* if we hade saved some registers then unsave them */
3455 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3456 unsaveRegisters (ic);
3462 /*-----------------------------------------------------------------*/
3463 /* genPcall - generates a call by pointer statement */
3464 /* new version, created from genCall - HJD */
3465 /*-----------------------------------------------------------------*/
3466 static void genPcall (iCode *ic)
3470 symbol *retlbl = newiTempLabel(NULL);
3471 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3475 fntype = operandType( IC_LEFT(ic) )->next;
3477 /* if send set is not empty the assign */
3480 int psuedoStkPtr=-1;
3482 /* reverse sendSet if function is not reentrant */
3483 if(!IFFUNC_ISREENT(fntype))
3484 _G.sendSet = reverseSet(_G.sendSet);
3488 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3491 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3492 size = AOP_SIZE(IC_LEFT(sic));
3495 /* all parameters are passed via stack, since WREG is clobbered
3496 * by the calling sequence */
3498 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3500 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3502 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3506 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3509 _G.stackRegSet = _G.sendSet;
3513 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3515 // push return address
3516 // push $ on return stack, then replace with retlbl
3518 /* Thanks to Thorsten Klose for pointing out that the following
3519 * snippet should be interrupt safe */
3520 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3521 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3523 pic16_emitpcodeNULLop(POC_PUSH);
3525 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3526 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3527 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3528 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3529 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3533 /* restore interrupt control register */
3534 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3537 /* make the call by writing the pointer into pc */
3538 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3539 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3541 // note: MOVFF to PCL not allowed
3542 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3543 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3546 /* return address is here: (X) */
3547 pic16_emitpLabelFORCE(retlbl->key);
3549 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3552 /* if we need assign a result value */
3553 if ((IS_ITEMP(IC_RESULT(ic))
3554 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3555 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3556 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3559 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3562 /* FIXME: Need proper way to obtain the function result's type.
3563 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3564 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3566 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3567 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3569 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3572 // stackParms -= use_wreg;
3575 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3576 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3577 if(STACK_MODEL_LARGE) {
3579 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3584 /*-----------------------------------------------------------------*/
3585 /* resultRemat - result is rematerializable */
3586 /*-----------------------------------------------------------------*/
3587 static int resultRemat (iCode *ic)
3589 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3590 if (SKIP_IC(ic) || ic->op == IFX)
3593 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3594 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3595 if (sym->remat && !POINTER_SET(ic))
3603 /*-----------------------------------------------------------------*/
3604 /* inExcludeList - return 1 if the string is in exclude Reg list */
3605 /*-----------------------------------------------------------------*/
3606 static bool inExcludeList(char *s)
3608 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3611 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3612 if (options.excludeRegs[i] &&
3613 STRCASECMP(options.excludeRegs[i],"none") == 0)
3616 for ( i = 0 ; options.excludeRegs[i]; i++) {
3617 if (options.excludeRegs[i] &&
3618 STRCASECMP(s,options.excludeRegs[i]) == 0)
3625 /*-----------------------------------------------------------------*/
3626 /* genFunction - generated code for function entry */
3627 /*-----------------------------------------------------------------*/
3628 static void genFunction (iCode *ic)
3634 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3636 pic16_labelOffset += (max_key+4);
3641 ftype = operandType(IC_LEFT(ic));
3642 sym = OP_SYMBOL(IC_LEFT(ic));
3644 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3645 /* create an absolute section at the interrupt vector:
3646 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3651 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3653 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3654 sprintf(asymname, "ivec_%s", sym->name);
3656 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3658 /* when an interrupt is declared as naked, do not emit the special
3659 * wrapper segment at vector address. The user should take care for
3660 * this instead. -- VR */
3662 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3663 asym = newSymbol(asymname, 0);
3664 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3665 pic16_addpBlock( apb );
3667 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3668 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3669 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3670 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3671 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3673 /* mark the end of this tiny function */
3674 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3676 sprintf(asymname, "%s", sym->rname);
3682 abSym = Safe_calloc(1, sizeof(absSym));
3683 strcpy(abSym->name, asymname);
3685 switch( FUNC_INTNO(sym->type) ) {
3686 case 0: abSym->address = 0x000000; break;
3687 case 1: abSym->address = 0x000008; break;
3688 case 2: abSym->address = 0x000018; break;
3691 // fprintf(stderr, "no interrupt number is given\n");
3692 abSym->address = -1; break;
3695 /* relocate interrupt vectors if needed */
3696 if(abSym->address != -1)
3697 abSym->address += pic16_options.ivt_loc;
3699 addSet(&absSymSet, abSym);
3703 /* create the function header */
3704 pic16_emitcode(";","-----------------------------------------");
3705 pic16_emitcode(";"," function %s",sym->name);
3706 pic16_emitcode(";","-----------------------------------------");
3708 /* prevent this symbol from being emitted as 'extern' */
3709 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3711 pic16_emitcode("","%s:",sym->rname);
3712 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3717 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3718 if(!strcmp(ab->name, sym->rname)) {
3719 pic16_pBlockConvert2Absolute(pb);
3725 if(IFFUNC_ISNAKED(ftype)) {
3726 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3730 /* if critical function then turn interrupts off */
3731 if (IFFUNC_ISCRITICAL(ftype)) {
3732 //pic16_emitcode("clr","ea");
3735 currFunc = sym; /* update the currFunc symbol */
3736 _G.fregsUsed = sym->regsUsed;
3737 _G.sregsAlloc = newBitVect(128);
3740 /* if this is an interrupt service routine then
3741 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3742 if (IFFUNC_ISISR(sym->type)) {
3743 _G.usefastretfie = 1; /* use shadow registers by default */
3745 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3746 if(!FUNC_ISSHADOWREGS(sym->type)) {
3747 /* do not save WREG,STATUS,BSR for high priority interrupts
3748 * because they are stored in the hardware shadow registers already */
3749 _G.usefastretfie = 0;
3750 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3751 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3752 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3755 /* these should really be optimized somehow, because not all
3756 * interrupt handlers modify them */
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3758 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3759 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3764 // pic16_pBlockConvert2ISR(pb);
3767 /* emit code to setup stack frame if user enabled,
3768 * and function is not main() */
3770 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3771 if(strcmp(sym->name, "main")) {
3773 || !options.ommitFramePtr
3775 || IFFUNC_ARGS(sym->type)
3776 || FUNC_HASSTACKPARM(sym->etype)
3778 /* setup the stack frame */
3779 if(STACK_MODEL_LARGE)
3780 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3781 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3783 if(STACK_MODEL_LARGE)
3784 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3785 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3789 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3792 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3794 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3795 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3797 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3800 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3801 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3808 /* if callee-save to be used for this function
3809 * then save the registers being used in this function */
3810 // if (IFFUNC_CALLEESAVES(sym->type))
3811 if(strcmp(sym->name, "main")) {
3814 /* if any registers used */
3815 if (sym->regsUsed) {
3816 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3819 /* save the registers used */
3820 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3821 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3822 if (bitVectBitValue(sym->regsUsed,i)) {
3824 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3826 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3829 if(!pic16_regWithIdx(i)->wasUsed) {
3830 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3831 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3832 pic16_regWithIdx(i)->wasUsed = 1;
3839 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3840 for(i=0;i<sym->regsUsed->size;i++) {
3841 if(bitVectBitValue(sym->regsUsed, i)) {
3846 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3849 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3854 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3855 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3858 /*-----------------------------------------------------------------*/
3859 /* genEndFunction - generates epilogue for functions */
3860 /*-----------------------------------------------------------------*/
3861 static void genEndFunction (iCode *ic)
3863 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3867 if(IFFUNC_ISNAKED(sym->type)) {
3868 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3874 /* add code for ISCRITICAL */
3875 if(IFFUNC_ISCRITICAL(sym->type)) {
3876 /* if critical function, turn on interrupts */
3878 /* TODO: add code here -- VR */
3881 // sym->regsUsed = _G.fregsUsed;
3883 /* now we need to restore the registers */
3884 /* if any registers used */
3886 /* first restore registers that might be used for stack access */
3887 if(_G.sregsAllocSet) {
3890 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3891 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3892 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3896 if (strcmp(sym->name, "main") && sym->regsUsed) {
3899 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3900 /* restore registers used */
3901 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3902 for ( i = sym->regsUsed->size; i >= 0; i--) {
3903 if (bitVectBitValue(sym->regsUsed,i)) {
3904 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3908 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3913 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3915 if (sym->stack == 1) {
3916 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3917 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3919 // we have to add more than one...
3920 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3921 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3922 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3924 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3925 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3926 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3930 if(strcmp(sym->name, "main")) {
3932 || !options.ommitFramePtr
3934 || IFFUNC_ARGS(sym->type)
3935 || FUNC_HASSTACKPARM(sym->etype)
3937 /* restore stack frame */
3938 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3939 if(STACK_MODEL_LARGE)
3940 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3946 if (IFFUNC_ISISR(sym->type)) {
3947 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3948 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3949 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3950 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3951 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3952 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3954 if(!FUNC_ISSHADOWREGS(sym->type)) {
3955 /* do not restore interrupt vector for WREG,STATUS,BSR
3956 * for high priority interrupt, see genFunction */
3957 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3958 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3959 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3961 // _G.interruptvector = 0; /* sanity check */
3964 /* if debug then send end of function */
3965 /* if (options.debug && currFunc) */
3967 debugFile->writeEndFunction (currFunc, ic, 1);
3970 if(_G.usefastretfie)
3971 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3973 pic16_emitpcodeNULLop(POC_RETFIE);
3975 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3977 _G.usefastretfie = 0;
3981 if (IFFUNC_ISCRITICAL(sym->type)) {
3982 pic16_emitcode("setb","ea");
3985 /* if debug then send end of function */
3987 debugFile->writeEndFunction (currFunc, ic, 1);
3990 /* insert code to restore stack frame, if user enabled it
3991 * and function is not main() */
3994 pic16_emitpcodeNULLop(POC_RETURN);
3996 /* Mark the end of a function */
3997 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4001 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4003 unsigned long lit=1;
4008 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4009 if(AOP_TYPE(op) == AOP_LIT) {
4010 if(!IS_FLOAT(operandType( op ))) {
4011 lit = ulFromVal (AOP(op)->aopu.aop_lit);
4014 unsigned long lit_int;
4018 /* take care if literal is a float */
4019 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4024 if (AOP_TYPE(op) == AOP_LIT) {
4025 /* FIXME: broken for
4026 * char __at(0x456) foo;
4028 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4029 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4030 } else if (AOP_TYPE(op) == AOP_PCODE
4031 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4032 /* char *s= "aaa"; return s; */
4033 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4034 * that the generic pointer is interpreted correctly
4035 * as referring to __code space, but this is fragile! */
4036 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4037 /* XXX: should check that dest != WREG */
4038 pic16_emitpcode(POC_MOVWF, dest);
4040 if(dest->type == PO_WREG && (offset == 0)) {
4041 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4048 /*-----------------------------------------------------------------*/
4049 /* genRet - generate code for return statement */
4050 /*-----------------------------------------------------------------*/
4051 static void genRet (iCode *ic)
4057 /* if we have no return value then
4058 * just generate the "ret" */
4063 /* we have something to return then
4064 * move the return value into place */
4065 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4066 size = AOP_SIZE(IC_LEFT(ic));
4070 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4073 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4076 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4078 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4081 /* >32-bits, setup stack and FSR0 */
4083 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4084 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4086 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4088 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4093 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4094 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4096 if(STACK_MODEL_LARGE) {
4097 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4098 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4100 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4105 /* old code, left here for reference -- VR */
4109 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4111 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4112 pic16_emitpcomment("push %s",l);
4115 DEBUGpic16_emitcode(";", "%d", __LINE__);
4116 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4117 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4119 if (strcmp(fReturn[offset],l)) {
4120 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4121 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4122 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4124 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4128 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4138 if (strcmp(fReturn[pushed],"a"))
4139 pic16_emitcode("pop",fReturn[pushed]);
4141 pic16_emitcode("pop","acc");
4147 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4150 /* generate a jump to the return label
4151 * if the next is not the return statement */
4152 if (!(ic->next && ic->next->op == LABEL
4153 && IC_LABEL(ic->next) == returnLabel)) {
4155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4156 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4160 /*-----------------------------------------------------------------*/
4161 /* genLabel - generates a label */
4162 /*-----------------------------------------------------------------*/
4163 static void genLabel (iCode *ic)
4167 /* special case never generate */
4168 if (IC_LABEL(ic) == entryLabel)
4171 pic16_emitpLabel(IC_LABEL(ic)->key);
4172 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4175 /*-----------------------------------------------------------------*/
4176 /* genGoto - generates a goto */
4177 /*-----------------------------------------------------------------*/
4179 static void genGoto (iCode *ic)
4182 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4183 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4187 /*-----------------------------------------------------------------*/
4188 /* genMultbits :- multiplication of bits */
4189 /*-----------------------------------------------------------------*/
4190 static void genMultbits (operand *left,
4196 if(!pic16_sameRegs(AOP(result),AOP(right)))
4197 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4199 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4200 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4201 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4206 /*-----------------------------------------------------------------*/
4207 /* genMultOneByte : 8 bit multiplication & division */
4208 /*-----------------------------------------------------------------*/
4209 static void genMultOneByte (operand *left,
4215 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4218 /* (if two literals, the value is computed before) */
4219 /* if one literal, literal on the right */
4220 if (AOP_TYPE(left) == AOP_LIT){
4226 /* size is already checked in genMult == 1 */
4227 // size = AOP_SIZE(result);
4229 if (AOP_TYPE(right) == AOP_LIT){
4230 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4231 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4232 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4233 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4235 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4236 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4237 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4238 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4241 pic16_genMult8X8_n (left, right,result);
4245 /*-----------------------------------------------------------------*/
4246 /* genMultOneWord : 16 bit multiplication */
4247 /*-----------------------------------------------------------------*/
4248 static void genMultOneWord (operand *left,
4253 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4254 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4256 /* (if two literals, the value is computed before)
4257 * if one literal, literal on the right */
4258 if (AOP_TYPE(left) == AOP_LIT){
4264 /* size is checked already == 2 */
4265 // size = AOP_SIZE(result);
4267 if (AOP_TYPE(right) == AOP_LIT) {
4268 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4269 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4270 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4271 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4273 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4274 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4275 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4276 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4279 pic16_genMult16X16_16(left, right,result);
4284 /*-----------------------------------------------------------------*/
4285 /* genMultOneLong : 32 bit multiplication */
4286 /*-----------------------------------------------------------------*/
4287 static void genMultOneLong (operand *left,
4292 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4293 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4295 /* (if two literals, the value is computed before)
4296 * if one literal, literal on the right */
4297 if (AOP_TYPE(left) == AOP_LIT){
4303 /* size is checked already == 4 */
4304 // size = AOP_SIZE(result);
4306 if (AOP_TYPE(right) == AOP_LIT) {
4307 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4308 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4309 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4310 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4312 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4313 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4314 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4315 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4318 pic16_genMult32X32_32(left, right,result);
4324 /*-----------------------------------------------------------------*/
4325 /* genMult - generates code for multiplication */
4326 /*-----------------------------------------------------------------*/
4327 static void genMult (iCode *ic)
4329 operand *left = IC_LEFT(ic);
4330 operand *right = IC_RIGHT(ic);
4331 operand *result= IC_RESULT(ic);
4334 /* assign the amsops */
4335 pic16_aopOp (left,ic,FALSE);
4336 pic16_aopOp (right,ic,FALSE);
4337 pic16_aopOp (result,ic,TRUE);
4339 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4341 /* special cases first *
4343 if (AOP_TYPE(left) == AOP_CRY
4344 && AOP_TYPE(right)== AOP_CRY) {
4345 genMultbits(left,right,result);
4349 /* if both are of size == 1 */
4350 if(AOP_SIZE(left) == 1
4351 && AOP_SIZE(right) == 1) {
4352 genMultOneByte(left,right,result);
4357 /* if both are of size == 2 */
4358 if(AOP_SIZE(left) == 2
4359 && AOP_SIZE(right) == 2) {
4360 genMultOneWord(left, right, result);
4364 /* if both are of size == 4 */
4365 if(AOP_SIZE(left) == 4
4366 && AOP_SIZE(right) == 4) {
4367 genMultOneLong(left, right, result);
4372 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4373 assert( !"Multiplication should have been transformed into function call!" );
4375 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4378 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4379 /* should have been converted to function call */
4383 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4385 pic16_freeAsmop(result,NULL,ic,TRUE);
4389 /*-----------------------------------------------------------------*/
4390 /* genDivbits :- division of bits */
4391 /*-----------------------------------------------------------------*/
4392 static void genDivbits (operand *left,
4399 /* the result must be bit */
4400 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4401 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4405 pic16_emitcode("div","ab");
4406 pic16_emitcode("rrc","a");
4407 pic16_aopPut(AOP(result),"c",0);
4410 /*-----------------------------------------------------------------*/
4411 /* genDivOneByte : 8 bit division */
4412 /*-----------------------------------------------------------------*/
4413 static void genDivOneByte (operand *left,
4417 sym_link *opetype = operandType(result);
4422 /* result = divident / divisor
4423 * - divident may be a register or a literal,
4424 * - divisor may be a register or a literal,
4425 * so there are 3 cases (literal / literal is optimized
4426 * by the front-end) to handle.
4427 * In addition we must handle signed and unsigned, which
4428 * result in 6 final different cases -- VR */
4432 size = AOP_SIZE(result) - 1;
4434 /* signed or unsigned */
4435 if (SPEC_USIGN(opetype)) {
4436 pCodeOp *pct1, /* count */
4439 symbol *label1, *label2, *label3;;
4442 /* unsigned is easy */
4444 pct1 = pic16_popGetTempReg(1);
4445 pct2 = pic16_popGetTempReg(1);
4446 pct3 = pic16_popGetTempReg(1);
4448 label1 = newiTempLabel(NULL);
4449 label2 = newiTempLabel(NULL);
4450 label3 = newiTempLabel(NULL);
4452 /* the following algorithm is extracted from divuint.c */
4454 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4455 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4457 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4459 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4461 pic16_emitpLabel(label1->key);
4464 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4468 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4472 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4474 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4477 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4478 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4479 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4481 pic16_emitpLabel( label3->key );
4482 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4483 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4487 pic16_emitpLabel(label2->key);
4488 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4489 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4490 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4492 /* result is in wreg */
4493 if(AOP_TYPE(result) != AOP_ACC)
4494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4496 pic16_popReleaseTempReg( pct3, 1);
4497 pic16_popReleaseTempReg( pct2, 1);
4498 pic16_popReleaseTempReg( pct1, 1);
4503 /* signed is a little bit more difficult */
4505 /* save the signs of the operands */
4506 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4508 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4509 pic16_emitcode("push","acc"); /* save it on the stack */
4511 /* now sign adjust for both left & right */
4512 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4514 lbl = newiTempLabel(NULL);
4515 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4516 pic16_emitcode("cpl","a");
4517 pic16_emitcode("inc","a");
4518 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4519 pic16_emitcode("mov","b,a");
4521 /* sign adjust left side */
4522 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4525 lbl = newiTempLabel(NULL);
4526 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4527 pic16_emitcode("cpl","a");
4528 pic16_emitcode("inc","a");
4529 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4531 /* now the division */
4532 pic16_emitcode("div","ab");
4533 /* we are interested in the lower order
4535 pic16_emitcode("mov","b,a");
4536 lbl = newiTempLabel(NULL);
4537 pic16_emitcode("pop","acc");
4538 /* if there was an over flow we don't
4539 adjust the sign of the result */
4540 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4541 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4543 pic16_emitcode("clr","a");
4544 pic16_emitcode("subb","a,b");
4545 pic16_emitcode("mov","b,a");
4546 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4548 /* now we are done */
4549 pic16_aopPut(AOP(result),"b",0);
4551 pic16_emitcode("mov","c,b.7");
4552 pic16_emitcode("subb","a,acc");
4555 pic16_aopPut(AOP(result),"a",offset++);
4560 /*-----------------------------------------------------------------*/
4561 /* genDiv - generates code for division */
4562 /*-----------------------------------------------------------------*/
4563 static void genDiv (iCode *ic)
4565 operand *left = IC_LEFT(ic);
4566 operand *right = IC_RIGHT(ic);
4567 operand *result= IC_RESULT(ic);
4569 int leftVal = 0, rightVal = 0;
4571 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4574 /* Division is a very lengthy algorithm, so it is better
4575 * to call support routines than inlining algorithm.
4576 * Division functions written here just in case someone
4577 * wants to inline and not use the support libraries -- VR */
4581 /* assign the amsops */
4582 pic16_aopOp (left,ic,FALSE);
4583 pic16_aopOp (right,ic,FALSE);
4584 pic16_aopOp (result,ic,TRUE);
4588 else if (ic->op == '%')
4591 assert( !"invalid operation requested in genDivMod" );
4593 /* get literal values */
4594 if (IS_VALOP(left)) {
4595 leftVal = (int) ulFromVal ( OP_VALUE(left) );
4596 assert( leftVal >= -128 && leftVal < 256 );
4597 if (leftVal < 0) { signedLits++; }
4599 if (IS_VALOP(right)) {
4600 rightVal = (int) ulFromVal ( OP_VALUE(right) );
4601 assert( rightVal >= -128 && rightVal < 256 );
4602 if (rightVal < 0) { signedLits++; }
4605 /* We should only come here to convert all
4606 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4607 * with exactly one operand being s8_t into
4608 * u8_t x u8_t -> u8_t. All other cases should have been
4609 * turned into calls to support routines beforehand... */
4610 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4611 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4613 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4614 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4616 /* Both operands are signed or negative, use _divschar
4617 * instead of _divuchar */
4618 pushaop(AOP(right), 0);
4619 pushaop(AOP(left), 0);
4621 /* call _divschar */
4622 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4626 sym = newSymbol( functions[op][0], 0 );
4628 strcpy(sym->rname, functions[op][0]);
4629 checkAddSym(&externs, sym);
4633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4634 if (AOP_SIZE(result) > 1)
4636 pic16_emitpcode(POC_MOVFF,
4637 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4638 pic16_popGet(AOP(result), 1)));
4640 pic16_addSign(result, 2, 1);
4643 /* clean up stack */
4644 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4645 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4650 /* push right operand */
4651 if (IS_VALOP(right)) {
4653 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4656 pushaop(AOP(right), 0);
4658 } else if (!IS_UNSIGNED(operandType(right))) {
4659 pic16_mov2w(AOP(right), 0);
4660 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4661 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4662 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4665 pushaop(AOP(right), 0);
4668 /* push left operand */
4669 if (IS_VALOP(left)) {
4671 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4674 pushaop(AOP(left), 0);
4676 } else if (!IS_UNSIGNED(operandType(left))) {
4677 pic16_mov2w(AOP(left),0);
4678 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4679 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4680 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4683 pushaop(AOP(left), 0);
4686 /* call _divuchar */
4687 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4691 sym = newSymbol( functions[op][1], 0 );
4693 strcpy(sym->rname, functions[op][1]);
4694 checkAddSym(&externs, sym);
4697 /* Revert negation(s) from above.
4698 * This is inefficient: if both operands are negative, this
4699 * should not touch WREG. However, determining that exactly
4700 * one operand was negated costs at least 3 instructions,
4701 * so there is nothing to be gained here, is there?
4703 * I negate WREG because either operand might share registers with
4704 * result, so assigning first might destroy an operand. */
4706 /* For the modulus operator, (a/b)*b == a shall hold.
4707 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4708 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4709 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4710 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4711 * Only invert the result if the left operand is negative (sigh).
4713 if (AOP_SIZE(result) <= 1 || !negated)
4717 if (IS_VALOP(right)) {
4719 /* we negated this operand above */
4720 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4722 } else if (!IS_UNSIGNED(operandType(right))) {
4723 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4724 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4728 if (IS_VALOP(left)) {
4730 /* we negated this operand above */
4731 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4733 } else if (!IS_UNSIGNED(operandType(left))) {
4734 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4735 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4738 /* Move result to destination. */
4739 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4741 /* Zero-extend: no operand was signed (or result is just a byte). */
4742 pic16_addSign(result, 1, 0);
4744 assert( AOP_SIZE(result) > 1 );
4745 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4748 if (IS_VALOP(right)) {
4750 /* we negated this operand above */
4751 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4753 } else if (!IS_UNSIGNED(operandType(right))) {
4754 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4755 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4759 if (IS_VALOP(left)) {
4761 /* we negated this operand above */
4762 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4764 } else if (!IS_UNSIGNED(operandType(left))) {
4765 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4766 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4769 /* Move result to destination. */
4770 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4772 /* Negate result if required. */
4773 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4774 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4777 pic16_addSign(result, 2, 1);
4780 /* clean up stack */
4781 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4782 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4787 /* special cases first */
4789 if (AOP_TYPE(left) == AOP_CRY &&
4790 AOP_TYPE(right)== AOP_CRY) {
4791 genDivbits(left,right,result);
4795 /* if both are of size == 1 */
4796 if (AOP_SIZE(left) == 1 &&
4797 AOP_SIZE(right) == 1 ) {
4798 genDivOneByte(left,right,result);
4803 /* should have been converted to function call */
4806 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4808 pic16_freeAsmop(result,NULL,ic,TRUE);
4812 /*-----------------------------------------------------------------*/
4813 /* genModbits :- modulus of bits */
4814 /*-----------------------------------------------------------------*/
4815 static void genModbits (operand *left,
4823 werror(W_POSSBUG2, __FILE__, __LINE__);
4824 /* the result must be bit */
4825 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4826 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4830 pic16_emitcode("div","ab");
4831 pic16_emitcode("mov","a,b");
4832 pic16_emitcode("rrc","a");
4833 pic16_aopPut(AOP(result),"c",0);
4836 /*-----------------------------------------------------------------*/
4837 /* genModOneByte : 8 bit modulus */
4838 /*-----------------------------------------------------------------*/
4839 static void genModOneByte (operand *left,
4843 sym_link *opetype = operandType(result);
4848 werror(W_POSSBUG2, __FILE__, __LINE__);
4850 /* signed or unsigned */
4851 if (SPEC_USIGN(opetype)) {
4852 /* unsigned is easy */
4853 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4854 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4856 pic16_emitcode("div","ab");
4857 pic16_aopPut(AOP(result),"b",0);
4861 /* signed is a little bit more difficult */
4863 /* save the signs of the operands */
4864 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4867 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4868 pic16_emitcode("push","acc"); /* save it on the stack */
4870 /* now sign adjust for both left & right */
4871 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4874 lbl = newiTempLabel(NULL);
4875 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4876 pic16_emitcode("cpl","a");
4877 pic16_emitcode("inc","a");
4878 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4879 pic16_emitcode("mov","b,a");
4881 /* sign adjust left side */
4882 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4885 lbl = newiTempLabel(NULL);
4886 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4887 pic16_emitcode("cpl","a");
4888 pic16_emitcode("inc","a");
4889 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4891 /* now the multiplication */
4892 pic16_emitcode("div","ab");
4893 /* we are interested in the lower order
4895 lbl = newiTempLabel(NULL);
4896 pic16_emitcode("pop","acc");
4897 /* if there was an over flow we don't
4898 adjust the sign of the result */
4899 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4900 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4902 pic16_emitcode("clr","a");
4903 pic16_emitcode("subb","a,b");
4904 pic16_emitcode("mov","b,a");
4905 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4907 /* now we are done */
4908 pic16_aopPut(AOP(result),"b",0);
4913 /*-----------------------------------------------------------------*/
4914 /* genMod - generates code for division */
4915 /*-----------------------------------------------------------------*/
4916 static void genMod (iCode *ic)
4918 /* Task deferred to genDiv */
4921 operand *left = IC_LEFT(ic);
4922 operand *right = IC_RIGHT(ic);
4923 operand *result= IC_RESULT(ic);
4927 /* assign the amsops */
4928 pic16_aopOp (left,ic,FALSE);
4929 pic16_aopOp (right,ic,FALSE);
4930 pic16_aopOp (result,ic,TRUE);
4932 /* special cases first */
4934 if (AOP_TYPE(left) == AOP_CRY &&
4935 AOP_TYPE(right)== AOP_CRY) {
4936 genModbits(left,right,result);
4940 /* if both are of size == 1 */
4941 if (AOP_SIZE(left) == 1 &&
4942 AOP_SIZE(right) == 1 ) {
4943 genModOneByte(left,right,result);
4947 /* should have been converted to function call */
4951 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4953 pic16_freeAsmop(result,NULL,ic,TRUE);
4957 /*-----------------------------------------------------------------*/
4958 /* genIfxJump :- will create a jump depending on the ifx */
4959 /*-----------------------------------------------------------------*/
4961 note: May need to add parameter to indicate when a variable is in bit space.
4963 static void genIfxJump (iCode *ic, char *jval)
4967 /* if true label then we jump if condition
4969 if ( IC_TRUE(ic) ) {
4971 if(strcmp(jval,"a") == 0)
4973 else if (strcmp(jval,"c") == 0)
4976 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4977 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4981 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4985 /* false label is present */
4986 if(strcmp(jval,"a") == 0)
4988 else if (strcmp(jval,"c") == 0)
4991 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4992 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4995 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4996 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5001 /* mark the icode as generated */
5005 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5009 /* if true label then we jump if condition
5011 if ( IC_TRUE(ic) ) {
5012 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5013 pic16_emitpcode(POC_BTFSC, jop);
5015 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5016 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5019 /* false label is present */
5020 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5021 pic16_emitpcode(POC_BTFSS, jop);
5023 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5024 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5028 /* mark the icode as generated */
5035 /*-----------------------------------------------------------------*/
5037 /*-----------------------------------------------------------------*/
5038 static void genSkip(iCode *ifx,int status_bit)
5040 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5044 if ( IC_TRUE(ifx) ) {
5045 switch(status_bit) {
5060 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5061 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5065 switch(status_bit) {
5079 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5080 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5087 /*-----------------------------------------------------------------*/
5089 /*-----------------------------------------------------------------*/
5090 static void genSkipc(resolvedIfx *rifx)
5092 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5102 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5103 rifx->generated = 1;
5106 #if !(USE_SIMPLE_GENCMP)
5107 /*-----------------------------------------------------------------*/
5109 /*-----------------------------------------------------------------*/
5110 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5112 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5117 if( (rifx->condition ^ invert_condition) & 1)
5122 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5123 rifx->generated = 1;
5128 /*-----------------------------------------------------------------*/
5130 /*-----------------------------------------------------------------*/
5131 static void genSkipz(iCode *ifx, int condition)
5142 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5144 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5147 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5149 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5154 #if !(USE_SIMPLE_GENCMP)
5155 /*-----------------------------------------------------------------*/
5157 /*-----------------------------------------------------------------*/
5158 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5164 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5166 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5169 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5170 rifx->generated = 1;
5175 /*-----------------------------------------------------------------*/
5176 /* genChkZeroes :- greater or less than comparison */
5177 /* For each byte in a literal that is zero, inclusive or the */
5178 /* the corresponding byte in the operand with W */
5179 /* returns true if any of the bytes are zero */
5180 /*-----------------------------------------------------------------*/
5181 static int genChkZeroes(operand *op, int lit, int size)
5188 i = (lit >> (size*8)) & 0xff;
5192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5194 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5204 /*-----------------------------------------------------------------*/
5205 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5206 /* aop (if it's NOT a literal) or from lit (if */
5207 /* aop is a literal) */
5208 /*-----------------------------------------------------------------*/
5209 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5210 if (aop->type == AOP_LIT) {
5211 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5213 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5217 /*-----------------------------------------------------------------*/
5218 /* genCmp :- greater or less than comparison */
5219 /*-----------------------------------------------------------------*/
5221 #if USE_SIMPLE_GENCMP /* { */
5223 /* genCmp performs a left < right comparison, stores
5224 * the outcome in result (if != NULL) and generates
5225 * control flow code for the ifx (if != NULL).
5227 * This version leaves in sequences like
5228 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5229 * which should be optmized by the peephole
5230 * optimizer - RN 2005-01-01 */
5231 static void genCmp (operand *left,operand *right,
5232 operand *result, iCode *ifx, int sign)
5245 assert (left && right);
5246 assert (AOP_SIZE(left) == AOP_SIZE(right));
5248 size = AOP_SIZE(right) - 1;
5249 mask = (0x100UL << (size*8)) - 1;
5250 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5255 resolveIfx (&rIfx, ifx);
5257 /* handle for special cases */
5258 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5261 /**********************************************************************
5262 * handle bits - bit compares are promoted to int compares seemingly! *
5263 **********************************************************************/
5265 // THIS IS COMPLETELY UNTESTED!
5266 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5267 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5268 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5269 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5272 // 1 < {0,1} is false --> clear C by skipping the next instruction
5273 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5274 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5275 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5276 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5277 emitCLRC; // only skipped for left=0 && right=1
5279 goto correct_result_in_carry;
5283 /*************************************************
5284 * make sure that left is register (or the like) *
5285 *************************************************/
5286 if (!isAOP_REGlike(left)) {
5287 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5288 assert (isAOP_LIT(left));
5289 assert (isAOP_REGlike(right));
5290 // swap left and right
5291 // left < right <==> right > left <==> (right >= left + 1)
5292 lit = ulFromVal (AOP(left)->aopu.aop_lit);
5294 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5295 // MAXVALUE < right? always false
5296 if (performedLt) emitCLRC; else emitSETC;
5297 goto correct_result_in_carry;
5300 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5301 // that's why we handled it above.
5308 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5309 } else if (isAOP_LIT(right)) {
5310 lit = ulFromVal (AOP(right)->aopu.aop_lit);
5313 assert (isAOP_REGlike(left)); // left must be register or the like
5314 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5316 /*************************************************
5317 * special cases go here *
5318 *************************************************/
5320 if (isAOP_LIT(right)) {
5322 // unsigned comparison to a literal
5323 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5325 // unsigned left < 0? always false
5326 if (performedLt) emitCLRC; else emitSETC;
5327 goto correct_result_in_carry;
5330 // signed comparison to a literal
5331 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5332 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5333 // signed left < 0x80000000? always false
5334 if (performedLt) emitCLRC; else emitSETC;
5335 goto correct_result_in_carry;
5336 } else if (lit == 0) {
5337 // compare left < 0; set CARRY if SIGNBIT(left) is set
5338 if (performedLt) emitSETC; else emitCLRC;
5339 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5340 if (performedLt) emitCLRC; else emitSETC;
5341 goto correct_result_in_carry;
5344 } // right is literal
5346 /*************************************************
5347 * perform a general case comparison *
5348 * make sure we get CARRY==1 <==> left >= right *
5349 *************************************************/
5350 // compare most significant bytes
5351 //DEBUGpc ("comparing bytes at offset %d", size);
5353 // unsigned comparison
5354 mov2w_regOrLit (AOP(right), lit, size);
5355 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5357 // signed comparison
5358 // (add 2^n to both operands then perform an unsigned comparison)
5359 if (isAOP_LIT(right)) {
5360 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5361 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5363 if (litbyte == 0x80) {
5364 // left >= 0x80 -- always true, but more bytes to come
5365 pic16_mov2w (AOP(left), size);
5366 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5369 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5370 pic16_mov2w (AOP(left), size);
5371 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5372 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5375 /* using PRODL as a temporary register here */
5376 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5377 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5378 pic16_mov2w (AOP(left), size);
5379 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5380 pic16_emitpcode (POC_MOVWF, pctemp);
5381 pic16_mov2w (AOP(right), size);
5382 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5383 pic16_emitpcode (POC_SUBFW, pctemp);
5384 //pic16_popReleaseTempReg(pctemp, 1);
5388 // compare remaining bytes (treat as unsigned case from above)
5389 templbl = newiTempLabel ( NULL );
5392 //DEBUGpc ("comparing bytes at offset %d", offs);
5393 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5394 mov2w_regOrLit (AOP(right), lit, offs);
5395 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5397 pic16_emitpLabel (templbl->key);
5398 goto result_in_carry;
5402 /****************************************************
5403 * now CARRY contains the result of the comparison: *
5404 * SUBWF sets CARRY iff *
5405 * F-W >= 0 <==> F >= W <==> !(F < W) *
5406 * (F=left, W=right) *
5407 ****************************************************/
5410 if (result && AOP_TYPE(result) != AOP_CRY) {
5411 // value will be stored
5414 // value wil only be used in the following genSkipc()
5415 rIfx.condition ^= 1;
5419 correct_result_in_carry:
5421 // assign result to variable (if neccessary)
5422 if (result && AOP_TYPE(result) != AOP_CRY) {
5423 //DEBUGpc ("assign result");
5424 size = AOP_SIZE(result);
5426 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5428 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5431 // perform conditional jump
5433 //DEBUGpc ("generate control flow");
5442 static void genCmp (operand *left,operand *right,
5443 operand *result, iCode *ifx, int sign)
5445 int size; //, offset = 0 ;
5446 unsigned long lit = 0L,i = 0;
5447 resolvedIfx rFalseIfx;
5448 // resolvedIfx rTrueIfx;
5450 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5453 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5454 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5460 resolveIfx(&rFalseIfx,ifx);
5461 truelbl = newiTempLabel(NULL);
5462 size = max(AOP_SIZE(left),AOP_SIZE(right));
5464 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5468 /* if literal is on the right then swap with left */
5469 if ((AOP_TYPE(right) == AOP_LIT)) {
5470 operand *tmp = right ;
5471 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5472 lit = ulFromVal (AOP(right)->aopu.aop_lit);
5475 lit = (lit - 1) & mask;
5478 rFalseIfx.condition ^= 1;
5481 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5482 lit = ulFromVal (AOP(left)->aopu.aop_lit);
5486 //if(IC_TRUE(ifx) == NULL)
5487 /* if left & right are bit variables */
5488 if (AOP_TYPE(left) == AOP_CRY &&
5489 AOP_TYPE(right) == AOP_CRY ) {
5490 assert (0 && "bit variables used in genCmp");
5491 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5492 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5494 /* subtract right from left if at the
5495 end the carry flag is set then we know that
5496 left is greater than right */
5498 symbol *lbl = newiTempLabel(NULL);
5501 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5502 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5506 if(AOP_TYPE(right) == AOP_LIT) {
5508 //lit = ulFromVal (AOP(right)->aopu.aop_lit);
5510 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5517 genSkipCond(&rFalseIfx,left,size-1,7);
5519 /* no need to compare to 0...*/
5520 /* NOTE: this is a de-generate compare that most certainly
5521 * creates some dead code. */
5522 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5524 if(ifx) ifx->generated = 1;
5531 //i = (lit >> (size*8)) & 0xff;
5532 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5534 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5536 i = ((0-lit) & 0xff);
5539 /* lit is 0x7f, all signed chars are less than
5540 * this except for 0x7f itself */
5541 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5542 genSkipz2(&rFalseIfx,0);
5544 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5545 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5546 genSkipc(&rFalseIfx);
5551 genSkipz2(&rFalseIfx,1);
5553 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5554 genSkipc(&rFalseIfx);
5558 if(ifx) ifx->generated = 1;
5562 /* chars are out of the way. now do ints and longs */
5565 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5572 genSkipCond(&rFalseIfx,left,size,7);
5573 if(ifx) ifx->generated = 1;
5578 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5580 //rFalseIfx.condition ^= 1;
5581 //genSkipCond(&rFalseIfx,left,size,7);
5582 //rFalseIfx.condition ^= 1;
5584 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5585 if(rFalseIfx.condition)
5586 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5588 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5590 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5591 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5592 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5595 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5597 if(rFalseIfx.condition) {
5599 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5605 genSkipc(&rFalseIfx);
5606 pic16_emitpLabel(truelbl->key);
5607 if(ifx) ifx->generated = 1;
5614 if( (lit & 0xff) == 0) {
5615 /* lower byte is zero */
5616 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5617 i = ((lit >> 8) & 0xff) ^0x80;
5618 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5619 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5620 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5621 genSkipc(&rFalseIfx);
5624 if(ifx) ifx->generated = 1;
5629 /* Special cases for signed longs */
5630 if( (lit & 0xffffff) == 0) {
5631 /* lower byte is zero */
5632 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5633 i = ((lit >> 8*3) & 0xff) ^0x80;
5634 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5635 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5636 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5637 genSkipc(&rFalseIfx);
5640 if(ifx) ifx->generated = 1;
5648 if(lit & (0x80 << (size*8))) {
5649 /* lit is negative */
5650 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5652 //genSkipCond(&rFalseIfx,left,size,7);
5654 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5656 if(rFalseIfx.condition)
5657 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5659 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5663 /* lit is positive */
5664 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5665 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5666 if(rFalseIfx.condition)
5667 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5669 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5674 This works, but is only good for ints.
5675 It also requires a "known zero" register.
5676 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5677 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5678 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5679 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5680 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5681 genSkipc(&rFalseIfx);
5683 pic16_emitpLabel(truelbl->key);
5684 if(ifx) ifx->generated = 1;
5688 /* There are no more special cases, so perform a general compare */
5690 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5691 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5695 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5697 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5699 //rFalseIfx.condition ^= 1;
5700 genSkipc(&rFalseIfx);
5702 pic16_emitpLabel(truelbl->key);
5704 if(ifx) ifx->generated = 1;
5711 /* sign is out of the way. So now do an unsigned compare */
5712 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5715 /* General case - compare to an unsigned literal on the right.*/
5717 i = (lit >> (size*8)) & 0xff;
5718 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5719 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5721 i = (lit >> (size*8)) & 0xff;
5724 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5726 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5728 /* this byte of the lit is zero,
5729 *if it's not the last then OR in the variable */
5731 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5736 pic16_emitpLabel(lbl->key);
5737 // pic16_emitpLabel(truelbl->key);
5738 //if(emitFinalCheck)
5739 genSkipc(&rFalseIfx);
5741 pic16_emitpLabel(truelbl->key);
5743 if(ifx) ifx->generated = 1;
5750 if(AOP_TYPE(left) == AOP_LIT) {
5751 //symbol *lbl = newiTempLabel(NULL);
5753 //EXPERIMENTAL lit = ulFromVal (AOP(left)->aopu.aop_lit);
5756 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5759 if((lit == 0) && (sign == 0)){
5762 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5764 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5766 genSkipz2(&rFalseIfx,0);
5767 if(ifx) ifx->generated = 1;
5774 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5775 /* degenerate compare can never be true */
5776 if(rFalseIfx.condition == 0)
5777 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5779 if(ifx) ifx->generated = 1;
5784 /* signed comparisons to a literal byte */
5786 int lp1 = (lit+1) & 0xff;
5788 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5791 rFalseIfx.condition ^= 1;
5792 genSkipCond(&rFalseIfx,right,0,7);
5795 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5796 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5797 genSkipz2(&rFalseIfx,1);
5800 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5801 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5802 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5803 rFalseIfx.condition ^= 1;
5804 genSkipc(&rFalseIfx);
5808 /* unsigned comparisons to a literal byte */
5810 switch(lit & 0xff ) {
5812 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5813 genSkipz2(&rFalseIfx,0);
5816 rFalseIfx.condition ^= 1;
5817 genSkipCond(&rFalseIfx,right,0,7);
5821 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5822 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5824 rFalseIfx.condition ^= 1;
5825 if (AOP_TYPE(result) == AOP_CRY)
5826 genSkipc(&rFalseIfx);
5828 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5829 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5835 if(ifx) ifx->generated = 1;
5836 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5842 /* Size is greater than 1 */
5850 /* this means lit = 0xffffffff, or -1 */
5853 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5854 rFalseIfx.condition ^= 1;
5855 genSkipCond(&rFalseIfx,right,size,7);
5856 if(ifx) ifx->generated = 1;
5858 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5867 if(rFalseIfx.condition) {
5868 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5869 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5872 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5874 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5878 if(rFalseIfx.condition) {
5879 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5880 pic16_emitpLabel(truelbl->key);
5882 rFalseIfx.condition ^= 1;
5883 genSkipCond(&rFalseIfx,right,s,7);
5886 if(ifx) ifx->generated = 1;
5888 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5894 if((size == 1) && (0 == (lp1&0xff))) {
5895 /* lower byte of signed word is zero */
5896 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5897 i = ((lp1 >> 8) & 0xff) ^0x80;
5898 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5899 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5900 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5902 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5904 if(ifx) ifx->generated = 1;
5907 rFalseIfx.condition ^= 1;
5908 genSkipc(&rFalseIfx);
5909 if(ifx) ifx->generated = 1;
5915 if(lit & (0x80 << (size*8))) {
5916 /* Lit is less than zero */
5917 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5918 //rFalseIfx.condition ^= 1;
5919 //genSkipCond(&rFalseIfx,left,size,7);
5920 //rFalseIfx.condition ^= 1;
5921 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5922 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5924 if(rFalseIfx.condition)
5925 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5927 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5931 /* Lit is greater than or equal to zero */
5932 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5933 //rFalseIfx.condition ^= 1;
5934 //genSkipCond(&rFalseIfx,right,size,7);
5935 //rFalseIfx.condition ^= 1;
5937 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5938 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5940 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5941 if(rFalseIfx.condition)
5942 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5948 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5949 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5955 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5957 rFalseIfx.condition ^= 1;
5958 //rFalseIfx.condition = 1;
5959 genSkipc(&rFalseIfx);
5961 pic16_emitpLabel(truelbl->key);
5963 if(ifx) ifx->generated = 1;
5966 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5973 /* compare word or long to an unsigned literal on the right.*/
5978 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5981 break; /* handled above */
5984 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5986 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5987 genSkipz2(&rFalseIfx,0);
5991 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5993 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5996 if(rFalseIfx.condition)
5997 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5999 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6002 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6003 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6005 rFalseIfx.condition ^= 1;
6006 genSkipc(&rFalseIfx);
6009 pic16_emitpLabel(truelbl->key);
6011 if(ifx) ifx->generated = 1;
6013 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6021 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6022 i = (lit >> (size*8)) & 0xff;
6024 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6025 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6028 i = (lit >> (size*8)) & 0xff;
6031 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6033 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6035 /* this byte of the lit is zero,
6036 * if it's not the last then OR in the variable */
6038 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6043 pic16_emitpLabel(lbl->key);
6045 rFalseIfx.condition ^= 1;
6047 genSkipc(&rFalseIfx);
6051 pic16_emitpLabel(truelbl->key);
6052 if(ifx) ifx->generated = 1;
6054 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6060 /* Compare two variables */
6062 DEBUGpic16_emitcode(";sign","%d",sign);
6066 /* Sigh. thus sucks... */
6070 pctemp = pic16_popGetTempReg(1);
6071 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6072 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6073 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6074 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6075 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6076 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6077 pic16_popReleaseTempReg(pctemp, 1);
6079 /* Signed char comparison */
6080 /* Special thanks to Nikolai Golovchenko for this snippet */
6081 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6082 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6083 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6084 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6085 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6086 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6088 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6089 genSkipc(&rFalseIfx);
6091 if(ifx) ifx->generated = 1;
6093 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6101 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6102 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6106 /* The rest of the bytes of a multi-byte compare */
6110 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6113 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6114 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6119 pic16_emitpLabel(lbl->key);
6121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6122 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6123 (AOP_TYPE(result) == AOP_REG)) {
6124 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6125 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6127 genSkipc(&rFalseIfx);
6129 //genSkipc(&rFalseIfx);
6130 if(ifx) ifx->generated = 1;
6133 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6141 if ((AOP_TYPE(result) != AOP_CRY)
6142 && AOP_SIZE(result)) {
6143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6145 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6147 pic16_outBitC(result);
6149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6150 /* if the result is used in the next
6151 ifx conditional branch then generate
6152 code a little differently */
6154 genIfxJump (ifx,"c");
6156 pic16_outBitC(result);
6157 /* leave the result in acc */
6162 #elif 0 /* VR version of genCmp() */ /* } else { */
6164 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6165 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6166 operand *result, int offset, int invert_op)
6170 /* check condition, > or < ?? */
6171 if(rIfx->condition != 0)invert_op ^= 1;
6173 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6175 if(!ifx)invert_op ^= 1;
6177 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6178 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6181 if(!invert_op)return POC_CPFSGT;
6182 else return POC_CPFSLT;
6185 static int compareAopfirstpass=1;
6187 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6188 operand *oper, int offset, operand *result,
6189 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6195 /* invert if there is a result to be loaded, in order to fit,
6196 * SETC/CLRC sequence */
6197 if(AOP_SIZE(result))invert_op ^= 1;
6199 // if(sign && !offset)invert_op ^= 1;
6201 // if(sign)invert_op ^= 1;
6203 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6205 if(AOP_SIZE(result) && compareAopfirstpass) {
6208 pic16_emitpcode(POC_SETF, pcop2);
6213 pic16_emitpcode(POC_CLRF, pcop2);
6219 compareAopfirstpass = 0;
6221 /* there is a bug when comparing operands with size > 1,
6222 * because higher bytes can be equal and test should be performed
6223 * to the next lower byte, current algorithm, considers operands
6224 * inequal in these cases! -- VR 20041107 */
6228 pic16_emitpcode(op, pcop);
6230 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6233 if((!sign || !offset) && AOP_SIZE(result)) {
6236 pic16_emitpcode(POC_CLRF, pcop2);
6241 pic16_emitpcode(POC_SETF, pcop2);
6246 /* don't emit final branch (offset == 0) */
6250 pic16_emitpcode(POC_RRCF, pcop2);
6252 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6255 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6256 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6257 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6259 truelbl = newiTempLabel( NULL );
6260 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6261 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6262 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6264 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6265 pic16_emitpLabel(truelbl->key);
6267 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6272 static void genCmp (operand *left, operand *right,
6273 operand *result, iCode *ifx, int sign)
6277 resolvedIfx rFalseIfx;
6278 symbol *falselbl, *tlbl;
6282 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6284 resolveIfx(&rFalseIfx, ifx);
6285 size = max(AOP_SIZE(left), AOP_SIZE(right));
6287 /* if left & right are bit variables */
6288 if(AOP_TYPE(left) == AOP_CRY
6289 && AOP_TYPE(right) == AOP_CRY ) {
6291 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6292 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6294 werror(W_POSSBUG2, __FILE__, __LINE__);
6298 /* if literal is on the right then swap with left */
6299 if((AOP_TYPE(right) == AOP_LIT)) {
6300 operand *tmp = right ;
6301 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6303 lit = ulFromVal (AOP(right)->aopu.aop_lit);
6305 // lit = (lit - 1) & mask;
6308 rFalseIfx.condition ^= 1; /* reverse compare */
6310 if ((AOP_TYPE(left) == AOP_LIT)) {
6311 /* float compares are handled by support functions */
6312 lit = ulFromVal(AOP(left)->aopu.aop_lit);
6315 /* actual comparing algorithm */
6316 // size = AOP_SIZE( right );
6318 falselbl = newiTempLabel( NULL );
6319 if(AOP_TYPE(left) == AOP_LIT) {
6320 /* compare to literal */
6321 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6324 pCodeOp *pct, *pct2;
6327 /* signed compare */
6328 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6330 /* using PRODL:PRODH as a temporary register here */
6331 pct = pic16_popCopyReg(&pic16_pc_prodl);
6332 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6333 tlbl = newiTempLabel( NULL );
6335 /* first compare signs:
6336 * a. if both are positive, compare just like unsigned
6337 * b. if both are negative, invert cmpop, compare just like unsigned
6338 * c. if different signs, determine the result directly */
6344 tlbl1 = newiTempLabel( NULL );
6345 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6349 /* literal is zero or positive:
6350 * a. if carry is zero, too, continue compare,
6351 * b. if carry is set, then continue depending on cmpop ^ condition:
6352 * 1. '<' return false (literal < variable),
6353 * 2. '>' return true (literal > variable) */
6354 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6355 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6358 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6359 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6363 /* literal is negative:
6364 * a. if carry is set, too, continue compare,
6365 * b. if carry is zero, then continue depending on cmpop ^ condition:
6366 * 1. '<' return true (literal < variable),
6367 * 2. '>' return false (literal > variable) */
6368 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6369 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6371 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6372 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6377 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6379 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6380 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6385 pic16_emitpLabel( tlbl1->key );
6388 compareAopfirstpass=1;
6389 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6390 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6391 // pic16_emitpcode(POC_MOVWF, pct);
6393 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6394 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6395 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6396 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6400 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6401 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6402 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6403 // pic16_emitpcode(POC_MOVWF, pct);
6405 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6406 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6407 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6408 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6409 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6412 if(ifx)ifx->generated = 1;
6414 if(AOP_SIZE(result)) {
6415 pic16_emitpLabel(tlbl->key);
6416 pic16_emitpLabel(falselbl->key);
6417 pic16_outBitOp( result, pct2 );
6419 pic16_emitpLabel(tlbl->key);
6423 /* unsigned compare */
6424 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6426 compareAopfirstpass=1;
6429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6430 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6433 if(ifx)ifx->generated = 1;
6435 if(AOP_SIZE(result)) {
6436 pic16_emitpLabel(falselbl->key);
6437 pic16_outBitC( result );
6442 /* compare registers */
6443 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6447 pCodeOp *pct, *pct2;
6449 /* signed compare */
6450 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6452 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6453 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6454 tlbl = newiTempLabel( NULL );
6456 compareAopfirstpass=1;
6459 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6460 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6461 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6462 pic16_emitpcode(POC_MOVWF, pct);
6464 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6465 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6468 /* WREG already holds left + 0x80 */
6469 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6472 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6473 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6474 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6475 pic16_emitpcode(POC_MOVWF, pct);
6477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6478 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6479 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6481 /* WREG already holds left + 0x80 */
6482 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6483 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6486 if(ifx)ifx->generated = 1;
6488 if(AOP_SIZE(result)) {
6489 pic16_emitpLabel(tlbl->key);
6490 pic16_emitpLabel(falselbl->key);
6491 pic16_outBitOp( result, pct2 );
6493 pic16_emitpLabel(tlbl->key);
6497 /* unsigned compare */
6498 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6500 compareAopfirstpass=1;
6503 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6504 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6508 if(ifx)ifx->generated = 1;
6509 if(AOP_SIZE(result)) {
6511 pic16_emitpLabel(falselbl->key);
6512 pic16_outBitC( result );
6523 /*-----------------------------------------------------------------*/
6524 /* genCmpGt :- greater than comparison */
6525 /*-----------------------------------------------------------------*/
6526 static void genCmpGt (iCode *ic, iCode *ifx)
6528 operand *left, *right, *result;
6529 sym_link *letype , *retype;
6535 right= IC_RIGHT(ic);
6536 result = IC_RESULT(ic);
6538 letype = getSpec(operandType(left));
6539 retype =getSpec(operandType(right));
6540 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6541 /* assign the amsops */
6542 pic16_aopOp (left,ic,FALSE);
6543 pic16_aopOp (right,ic,FALSE);
6544 pic16_aopOp (result,ic,TRUE);
6546 genCmp(right, left, result, ifx, sign);
6548 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6550 pic16_freeAsmop(result,NULL,ic,TRUE);
6553 /*-----------------------------------------------------------------*/
6554 /* genCmpLt - less than comparisons */
6555 /*-----------------------------------------------------------------*/
6556 static void genCmpLt (iCode *ic, iCode *ifx)
6558 operand *left, *right, *result;
6559 sym_link *letype , *retype;
6565 right= IC_RIGHT(ic);
6566 result = IC_RESULT(ic);
6568 letype = getSpec(operandType(left));
6569 retype =getSpec(operandType(right));
6570 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6572 /* assign the amsops */
6573 pic16_aopOp (left,ic,FALSE);
6574 pic16_aopOp (right,ic,FALSE);
6575 pic16_aopOp (result,ic,TRUE);
6577 genCmp(left, right, result, ifx, sign);
6579 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6581 pic16_freeAsmop(result,NULL,ic,TRUE);
6586 // FIXME reenable literal optimisation when the pic16 port is stable
6588 /*-----------------------------------------------------------------*/
6589 /* genc16bit2lit - compare a 16 bit value to a literal */
6590 /*-----------------------------------------------------------------*/
6591 static void genc16bit2lit(operand *op, int lit, int offset)
6595 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6596 if( (lit&0xff) == 0)
6601 switch( BYTEofLONG(lit,i)) {
6603 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6606 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6609 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6612 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6613 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6618 switch( BYTEofLONG(lit,i)) {
6620 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6624 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6628 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6631 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6633 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6642 /*-----------------------------------------------------------------*/
6643 /* gencjneshort - compare and jump if not equal */
6644 /*-----------------------------------------------------------------*/
6645 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6647 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6649 int res_offset = 0; /* the result may be a different size then left or right */
6650 int res_size = AOP_SIZE(result);
6652 symbol *lbl, *lbl_done;
6654 unsigned long lit = 0L;
6655 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6657 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6658 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6660 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6661 resolveIfx(&rIfx,ifx);
6662 lbl = newiTempLabel(NULL);
6663 lbl_done = newiTempLabel(NULL);
6666 /* if the left side is a literal or
6667 if the right is in a pointer register and left
6669 if ((AOP_TYPE(left) == AOP_LIT) ||
6670 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6675 if(AOP_TYPE(right) == AOP_LIT)
6676 lit = ulFromVal (AOP(right)->aopu.aop_lit);
6678 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6679 preserve_result = 1;
6681 if(result && !preserve_result)
6684 for(i = 0; i < AOP_SIZE(result); i++)
6685 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6689 /* if the right side is a literal then anything goes */
6690 if (AOP_TYPE(right) == AOP_LIT &&
6691 AOP_TYPE(left) != AOP_DIR ) {
6694 genc16bit2lit(left, lit, 0);
6696 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6702 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6703 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6705 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6709 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6711 if(res_offset < res_size-1)
6719 /* if the right side is in a register or in direct space or
6720 if the left is a pointer register & right is not */
6721 else if (AOP_TYPE(right) == AOP_REG ||
6722 AOP_TYPE(right) == AOP_DIR ||
6723 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6724 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6725 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6726 int lbl_key = lbl->key;
6729 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6730 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6732 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6733 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6734 __FUNCTION__,__LINE__);
6738 /* switch(size) { */
6740 /* genc16bit2lit(left, lit, 0); */
6742 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6747 if((AOP_TYPE(left) == AOP_DIR) &&
6748 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6750 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6751 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6753 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6755 switch (lit & 0xff) {
6757 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6760 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6761 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6766 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6767 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6768 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6769 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6773 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6774 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6779 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6782 if(AOP_TYPE(result) == AOP_CRY) {
6783 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6788 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6790 /* fix me. probably need to check result size too */
6791 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6796 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6797 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6804 if(res_offset < res_size-1)
6809 } else if(AOP_TYPE(right) == AOP_REG &&
6810 AOP_TYPE(left) != AOP_DIR){
6813 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6814 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6815 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6820 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6822 if(res_offset < res_size-1)
6827 /* right is a pointer reg need both a & b */
6829 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6831 pic16_emitcode("mov","b,%s",l);
6832 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6833 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6838 if(result && preserve_result)
6841 for(i = 0; i < AOP_SIZE(result); i++)
6842 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6845 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6847 if(result && preserve_result)
6848 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6851 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6853 pic16_emitpLabel(lbl->key);
6855 if(result && preserve_result)
6858 for(i = 0; i < AOP_SIZE(result); i++)
6859 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6861 pic16_emitpLabel(lbl_done->key);
6864 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6872 /*-----------------------------------------------------------------*/
6873 /* gencjne - compare and jump if not equal */
6874 /*-----------------------------------------------------------------*/
6875 static void gencjne(operand *left, operand *right, iCode *ifx)
6877 symbol *tlbl = newiTempLabel(NULL);
6879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6880 gencjneshort(left, right, lbl);
6882 pic16_emitcode("mov","a,%s",one);
6883 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6884 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6885 pic16_emitcode("clr","a");
6886 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6888 pic16_emitpLabel(lbl->key);
6889 pic16_emitpLabel(tlbl->key);
6895 /*-----------------------------------------------------------------*/
6896 /* is_LitOp - check if operand has to be treated as literal */
6897 /*-----------------------------------------------------------------*/
6898 static bool is_LitOp(operand *op)
6900 return ((AOP_TYPE(op) == AOP_LIT)
6901 || ( (AOP_TYPE(op) == AOP_PCODE)
6902 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6903 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6906 /*-----------------------------------------------------------------*/
6907 /* is_LitAOp - check if operand has to be treated as literal */
6908 /*-----------------------------------------------------------------*/
6909 static bool is_LitAOp(asmop *aop)
6911 return ((aop->type == AOP_LIT)
6912 || ( (aop->type == AOP_PCODE)
6913 && ( (aop->aopu.pcop->type == PO_LITERAL)
6914 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6919 /*-----------------------------------------------------------------*/
6920 /* genCmpEq - generates code for equal to */
6921 /*-----------------------------------------------------------------*/
6922 static void genCmpEq (iCode *ic, iCode *ifx)
6924 operand *left, *right, *result;
6925 symbol *falselbl = newiTempLabel(NULL);
6926 symbol *donelbl = newiTempLabel(NULL);
6928 int preserve_result = 0;
6929 int generate_result = 0;
6931 unsigned long lit = -1;
6935 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6936 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6937 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6939 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6941 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6943 werror(W_POSSBUG2, __FILE__, __LINE__);
6944 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6945 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6949 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6951 operand *tmp = right ;
6956 if (AOP_TYPE(right) == AOP_LIT) {
6957 lit = ulFromVal (AOP(right)->aopu.aop_lit);
6960 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6961 preserve_result = 1;
6963 if(result && AOP_SIZE(result))
6964 generate_result = 1;
6966 if(generate_result && !preserve_result)
6968 for(i = 0; i < AOP_SIZE(result); i++)
6969 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6972 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6973 for(i=0; i < AOP_SIZE(left); i++)
6975 if(AOP_TYPE(left) != AOP_ACC)
6978 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6980 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6982 if(is_LitOp(right)) {
6983 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6984 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6987 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6989 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6994 if(generate_result && preserve_result)
6996 for(i = 0; i < AOP_SIZE(result); i++)
6997 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7001 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7003 if(generate_result && preserve_result)
7004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7006 if(ifx && IC_TRUE(ifx))
7007 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7009 if(ifx && IC_FALSE(ifx))
7010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7012 pic16_emitpLabel(falselbl->key);
7016 if(ifx && IC_FALSE(ifx))
7017 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7019 if(generate_result && preserve_result)
7021 for(i = 0; i < AOP_SIZE(result); i++)
7022 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7025 pic16_emitpLabel(donelbl->key);
7031 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7033 pic16_freeAsmop(result,NULL,ic,TRUE);
7039 // old version kept for reference
7041 /*-----------------------------------------------------------------*/
7042 /* genCmpEq - generates code for equal to */
7043 /*-----------------------------------------------------------------*/
7044 static void genCmpEq (iCode *ic, iCode *ifx)
7046 operand *left, *right, *result;
7047 unsigned long lit = 0L;
7049 symbol *falselbl = newiTempLabel(NULL);
7052 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7055 DEBUGpic16_emitcode ("; ifx is non-null","");
7057 DEBUGpic16_emitcode ("; ifx is null","");
7059 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7060 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7061 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7063 size = max(AOP_SIZE(left),AOP_SIZE(right));
7065 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7067 /* if literal, literal on the right or
7068 if the right is in a pointer register and left
7070 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7071 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7072 operand *tmp = right ;
7078 if(ifx && !AOP_SIZE(result)){
7080 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7081 /* if they are both bit variables */
7082 if (AOP_TYPE(left) == AOP_CRY &&
7083 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7084 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7085 if(AOP_TYPE(right) == AOP_LIT){
7086 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
7088 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7089 pic16_emitcode("cpl","c");
7090 } else if(lit == 1L) {
7091 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7093 pic16_emitcode("clr","c");
7095 /* AOP_TYPE(right) == AOP_CRY */
7097 symbol *lbl = newiTempLabel(NULL);
7098 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7099 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7100 pic16_emitcode("cpl","c");
7101 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7103 /* if true label then we jump if condition
7105 tlbl = newiTempLabel(NULL);
7106 if ( IC_TRUE(ifx) ) {
7107 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7108 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7110 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7111 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7113 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7116 /* left and right are both bit variables, result is carry */
7119 resolveIfx(&rIfx,ifx);
7121 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7122 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7123 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7124 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7129 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7131 /* They're not both bit variables. Is the right a literal? */
7132 if(AOP_TYPE(right) == AOP_LIT) {
7133 lit = ulFromVal (AOP(right)->aopu.aop_lit);
7138 switch(lit & 0xff) {
7140 if ( IC_TRUE(ifx) ) {
7141 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7143 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7145 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7146 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7150 if ( IC_TRUE(ifx) ) {
7151 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7153 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7155 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7156 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7160 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7162 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7167 /* end of size == 1 */
7171 genc16bit2lit(left,lit,offset);
7174 /* end of size == 2 */
7179 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7180 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7181 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7182 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7185 /* search for patterns that can be optimized */
7187 genc16bit2lit(left,lit,0);
7191 emitSKPZ; // if hi word unequal
7193 emitSKPNZ; // if hi word equal
7195 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7196 genc16bit2lit(left,lit,2);
7199 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7200 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7204 pic16_emitpLabel(falselbl->key);
7213 } else if(AOP_TYPE(right) == AOP_CRY ) {
7214 /* we know the left is not a bit, but that the right is */
7215 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7216 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7217 pic16_popGet(AOP(right),offset));
7218 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7220 /* if the two are equal, then W will be 0 and the Z bit is set
7221 * we could test Z now, or go ahead and check the high order bytes if
7222 * the variable we're comparing is larger than a byte. */
7225 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7227 if ( IC_TRUE(ifx) ) {
7229 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7230 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7233 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7234 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7238 /* They're both variables that are larger than bits */
7241 tlbl = newiTempLabel(NULL);
7244 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7245 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7247 if ( IC_TRUE(ifx) ) {
7251 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7253 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7254 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7258 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7261 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7262 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7267 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7269 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7270 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7274 if(s>1 && IC_TRUE(ifx)) {
7275 pic16_emitpLabel(tlbl->key);
7276 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7280 /* mark the icode as generated */
7285 /* if they are both bit variables */
7286 if (AOP_TYPE(left) == AOP_CRY &&
7287 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7288 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7289 if(AOP_TYPE(right) == AOP_LIT){
7290 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
7292 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7293 pic16_emitcode("cpl","c");
7294 } else if(lit == 1L) {
7295 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7297 pic16_emitcode("clr","c");
7299 /* AOP_TYPE(right) == AOP_CRY */
7301 symbol *lbl = newiTempLabel(NULL);
7302 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7303 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7304 pic16_emitcode("cpl","c");
7305 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7308 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7309 pic16_outBitC(result);
7313 genIfxJump (ifx,"c");
7316 /* if the result is used in an arithmetic operation
7317 then put the result in place */
7318 pic16_outBitC(result);
7321 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7322 gencjne(left,right,result,ifx);
7325 gencjne(left,right,newiTempLabel(NULL));
7327 if(IC_TRUE(ifx)->key)
7328 gencjne(left,right,IC_TRUE(ifx)->key);
7330 gencjne(left,right,IC_FALSE(ifx)->key);
7334 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7335 pic16_aopPut(AOP(result),"a",0);
7340 genIfxJump (ifx,"a");
7344 /* if the result is used in an arithmetic operation
7345 then put the result in place */
7347 if (AOP_TYPE(result) != AOP_CRY)
7348 pic16_outAcc(result);
7350 /* leave the result in acc */
7354 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7356 pic16_freeAsmop(result,NULL,ic,TRUE);
7360 /*-----------------------------------------------------------------*/
7361 /* ifxForOp - returns the icode containing the ifx for operand */
7362 /*-----------------------------------------------------------------*/
7363 static iCode *ifxForOp ( operand *op, iCode *ic )
7367 /* if true symbol then needs to be assigned */
7368 if (IS_TRUE_SYMOP(op))
7371 /* if this has register type condition and
7372 the next instruction is ifx with the same operand
7373 and live to of the operand is upto the ifx only then */
7375 && ic->next->op == IFX
7376 && IC_COND(ic->next)->key == op->key
7377 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7379 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7385 ic->next->op == IFX &&
7386 IC_COND(ic->next)->key == op->key) {
7387 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7392 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7394 ic->next->op == IFX)
7395 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7398 ic->next->op == IFX &&
7399 IC_COND(ic->next)->key == op->key) {
7400 DEBUGpic16_emitcode ("; "," key is okay");
7401 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7402 OP_SYMBOL(op)->liveTo,
7407 /* the code below is completely untested
7408 * it just allows ulong2fs.c compile -- VR */
7411 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7412 __FILE__, __FUNCTION__, __LINE__);
7414 /* if this has register type condition and
7415 the next instruction is ifx with the same operand
7416 and live to of the operand is upto the ifx only then */
7418 ic->next->op == IFX &&
7419 IC_COND(ic->next)->key == op->key &&
7420 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7424 ic->next->op == IFX &&
7425 IC_COND(ic->next)->key == op->key) {
7426 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7430 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7431 __FILE__, __FUNCTION__, __LINE__);
7433 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7438 /*-----------------------------------------------------------------*/
7439 /* genAndOp - for && operation */
7440 /*-----------------------------------------------------------------*/
7441 static void genAndOp (iCode *ic)
7443 operand *left,*right, *result;
7448 /* note here that && operations that are in an
7449 if statement are taken away by backPatchLabels
7450 only those used in arthmetic operations remain */
7451 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7452 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7453 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7455 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7457 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7458 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7459 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7461 /* if both are bit variables */
7462 /* if (AOP_TYPE(left) == AOP_CRY && */
7463 /* AOP_TYPE(right) == AOP_CRY ) { */
7464 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7465 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7466 /* pic16_outBitC(result); */
7468 /* tlbl = newiTempLabel(NULL); */
7469 /* pic16_toBoolean(left); */
7470 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7471 /* pic16_toBoolean(right); */
7472 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7473 /* pic16_outBitAcc(result); */
7476 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7478 pic16_freeAsmop(result,NULL,ic,TRUE);
7482 /*-----------------------------------------------------------------*/
7483 /* genOrOp - for || operation */
7484 /*-----------------------------------------------------------------*/
7487 modified this code, but it doesn't appear to ever get called
7490 static void genOrOp (iCode *ic)
7492 operand *left,*right, *result;
7497 /* note here that || operations that are in an
7498 if statement are taken away by backPatchLabels
7499 only those used in arthmetic operations remain */
7500 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7501 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7502 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7504 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7506 /* if both are bit variables */
7507 if (AOP_TYPE(left) == AOP_CRY &&
7508 AOP_TYPE(right) == AOP_CRY ) {
7509 pic16_emitcode("clrc","");
7510 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7511 AOP(left)->aopu.aop_dir,
7512 AOP(left)->aopu.aop_dir);
7513 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7514 AOP(right)->aopu.aop_dir,
7515 AOP(right)->aopu.aop_dir);
7516 pic16_emitcode("setc","");
7519 tlbl = newiTempLabel(NULL);
7520 pic16_toBoolean(left);
7522 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7523 pic16_toBoolean(right);
7524 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7526 pic16_outBitAcc(result);
7529 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7531 pic16_freeAsmop(result,NULL,ic,TRUE);
7534 /*-----------------------------------------------------------------*/
7535 /* isLiteralBit - test if lit == 2^n */
7536 /*-----------------------------------------------------------------*/
7537 static int isLiteralBit(unsigned long lit)
7539 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7540 0x100L,0x200L,0x400L,0x800L,
7541 0x1000L,0x2000L,0x4000L,0x8000L,
7542 0x10000L,0x20000L,0x40000L,0x80000L,
7543 0x100000L,0x200000L,0x400000L,0x800000L,
7544 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7545 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7549 for(idx = 0; idx < 32; idx++)
7555 /*-----------------------------------------------------------------*/
7556 /* continueIfTrue - */
7557 /*-----------------------------------------------------------------*/
7558 static void continueIfTrue (iCode *ic)
7562 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7566 /*-----------------------------------------------------------------*/
7568 /*-----------------------------------------------------------------*/
7569 static void jumpIfTrue (iCode *ic)
7573 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7577 /*-----------------------------------------------------------------*/
7578 /* jmpTrueOrFalse - */
7579 /*-----------------------------------------------------------------*/
7580 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7582 // ugly but optimized by peephole
7585 symbol *nlbl = newiTempLabel(NULL);
7586 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7587 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7588 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7589 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7591 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7592 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7597 /*-----------------------------------------------------------------*/
7598 /* genAnd - code for and */
7599 /*-----------------------------------------------------------------*/
7600 static void genAnd (iCode *ic, iCode *ifx)
7602 operand *left, *right, *result;
7603 int size, offset = 0;
7604 unsigned long lit = 0L;
7609 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7610 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7611 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7613 resolveIfx (&rIfx, ifx);
7615 /* if left is a literal & right is not then exchange them */
7616 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7617 AOP_NEEDSACC (left))
7619 operand *tmp = right;
7624 /* if result = right then exchange them */
7625 if (pic16_sameRegs (AOP (result), AOP (right)))
7627 operand *tmp = right;
7632 /* if right is bit then exchange them */
7633 if (AOP_TYPE (right) == AOP_CRY &&
7634 AOP_TYPE (left) != AOP_CRY)
7636 operand *tmp = right;
7641 if (AOP_TYPE (right) == AOP_LIT)
7642 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7644 size = AOP_SIZE (result);
7646 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
7649 // result = bit & yy;
7650 if (AOP_TYPE(left) == AOP_CRY){
7651 // c = bit & literal;
7652 if(AOP_TYPE(right) == AOP_LIT){
7654 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7657 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7660 if(size && (AOP_TYPE(result) == AOP_CRY)){
7661 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7664 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7668 pic16_emitcode("clr","c");
7671 if (AOP_TYPE(right) == AOP_CRY){
7673 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7674 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7677 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7679 pic16_emitcode("rrc","a");
7680 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7686 pic16_outBitC(result);
7688 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7689 genIfxJump(ifx, "c");
7693 // if (val & 0xZZ) - size = 0, ifx != FALSE -
7694 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7695 if ((AOP_TYPE (right) == AOP_LIT) &&
7696 (AOP_TYPE (result) == AOP_CRY) &&
7697 (AOP_TYPE (left) != AOP_CRY))
7699 symbol *tlbl = newiTempLabel (NULL);
7700 int sizel = AOP_SIZE (left);
7707 /* get number of non null bytes in literal */
7710 if (lit & (0xff << (sizel * 8)))
7714 emitBra = nonnull || rIfx.condition;
7716 for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
7718 unsigned char bytelit = lit;
7726 /* patch provided by Aaron Colwell */
7727 if ((posbit = isLiteralBit (bytelit)) != 0)
7731 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
7732 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
7736 pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
7741 if (bytelit == 0xff)
7743 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7744 * a peephole could optimize it out -- VR */
7745 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
7749 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
7750 pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
7757 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
7761 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
7766 /* last non null byte */
7776 // bit = left & literal
7780 pic16_emitpLabel (tlbl->key);
7783 // if(left & literal)
7789 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
7792 pic16_emitpLabel (tlbl->key);
7795 pic16_outBitC (result);
7799 /* if left is same as result */
7800 if(pic16_sameRegs(AOP(result),AOP(left))){
7802 for(;size--; offset++,lit>>=8) {
7803 if(AOP_TYPE(right) == AOP_LIT){
7804 switch(lit & 0xff) {
7806 /* and'ing with 0 has clears the result */
7807 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7808 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7811 /* and'ing with 0xff is a nop when the result and left are the same */
7816 int p = pic16_my_powof2( (~lit) & 0xff );
7818 /* only one bit is set in the literal, so use a bcf instruction */
7819 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7820 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7823 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7824 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7825 if(know_W != (lit&0xff))
7826 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7828 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7833 if (AOP_TYPE(left) == AOP_ACC) {
7834 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7836 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7837 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7844 // left & result in different registers
7845 if(AOP_TYPE(result) == AOP_CRY){
7847 // if(size), result in bit
7848 // if(!size && ifx), conditional oper: if(left & right)
7849 symbol *tlbl = newiTempLabel(NULL);
7850 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7852 pic16_emitcode("setb","c");
7854 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7855 pic16_emitcode("anl","a,%s",
7856 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7857 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7862 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7863 pic16_outBitC(result);
7865 jmpTrueOrFalse(ifx, tlbl);
7867 for(;(size--);offset++) {
7869 // result = left & right
7870 if(AOP_TYPE(right) == AOP_LIT){
7871 int t = (lit >> (offset*8)) & 0x0FFL;
7874 pic16_emitcode("clrf","%s",
7875 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7876 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7879 pic16_emitcode("movf","%s,w",
7880 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7881 pic16_emitcode("movwf","%s",
7882 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7883 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7884 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7887 pic16_emitcode("movlw","0x%x",t);
7888 pic16_emitcode("andwf","%s,w",
7889 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890 pic16_emitcode("movwf","%s",
7891 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7893 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7894 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7895 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7900 if (AOP_TYPE(left) == AOP_ACC) {
7901 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7904 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7905 pic16_emitcode("andwf","%s,w",
7906 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7908 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7910 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7911 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7917 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7918 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7919 pic16_freeAsmop(result,NULL,ic,TRUE);
7922 /*-----------------------------------------------------------------*/
7923 /* genOr - code for or */
7924 /*-----------------------------------------------------------------*/
7925 static void genOr (iCode *ic, iCode *ifx)
7927 operand *left, *right, *result;
7928 int size, offset = 0;
7929 unsigned long lit = 0L;
7934 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7935 pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
7936 pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
7938 resolveIfx (&rIfx, ifx);
7940 /* if left is a literal & right is not then exchange them */
7941 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7942 AOP_NEEDSACC (left))
7944 operand *tmp = right;
7949 /* if result = right then exchange them */
7950 if (pic16_sameRegs (AOP (result), AOP (right)))
7952 operand *tmp = right;
7957 /* if right is bit then exchange them */
7958 if (AOP_TYPE (right) == AOP_CRY &&
7959 AOP_TYPE (left) != AOP_CRY)
7961 operand *tmp = right;
7966 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
7968 if (AOP_TYPE (right) == AOP_LIT)
7969 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7971 size = AOP_SIZE (result);
7975 if (AOP_TYPE(left) == AOP_CRY){
7976 if(AOP_TYPE(right) == AOP_LIT){
7977 // c = bit & literal;
7979 // lit != 0 => result = 1
7980 if(AOP_TYPE(result) == AOP_CRY){
7982 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7983 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7984 // AOP(result)->aopu.aop_dir,
7985 // AOP(result)->aopu.aop_dir);
7987 continueIfTrue(ifx);
7991 // lit == 0 => result = left
7992 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7994 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7997 if (AOP_TYPE(right) == AOP_CRY){
7998 if(pic16_sameRegs(AOP(result),AOP(left))){
8000 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8001 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8002 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8004 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8005 AOP(result)->aopu.aop_dir,
8006 AOP(result)->aopu.aop_dir);
8007 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8008 AOP(right)->aopu.aop_dir,
8009 AOP(right)->aopu.aop_dir);
8010 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8011 AOP(result)->aopu.aop_dir,
8012 AOP(result)->aopu.aop_dir);
8014 if( AOP_TYPE(result) == AOP_ACC) {
8015 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8016 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8017 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8018 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8022 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8023 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8024 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8025 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8027 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8028 AOP(result)->aopu.aop_dir,
8029 AOP(result)->aopu.aop_dir);
8030 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8031 AOP(right)->aopu.aop_dir,
8032 AOP(right)->aopu.aop_dir);
8033 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8034 AOP(left)->aopu.aop_dir,
8035 AOP(left)->aopu.aop_dir);
8036 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8037 AOP(result)->aopu.aop_dir,
8038 AOP(result)->aopu.aop_dir);
8043 symbol *tlbl = newiTempLabel(NULL);
8044 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8047 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8048 if( AOP_TYPE(right) == AOP_ACC) {
8049 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8051 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8052 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8057 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8058 pic16_emitcode(";XXX setb","c");
8059 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8060 AOP(left)->aopu.aop_dir,tlbl->key+100);
8061 pic16_toBoolean(right);
8062 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8063 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8064 jmpTrueOrFalse(ifx, tlbl);
8068 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8075 pic16_outBitC(result);
8077 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8078 genIfxJump(ifx, "c");
8082 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8083 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8084 if ((AOP_TYPE (right) == AOP_LIT) &&
8085 (AOP_TYPE (result) == AOP_CRY) &&
8086 (AOP_TYPE (left) != AOP_CRY))
8091 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
8100 /* if left is same as result */
8101 if(pic16_sameRegs(AOP(result),AOP(left))){
8103 for(;size--; offset++,lit>>=8) {
8104 if(AOP_TYPE(right) == AOP_LIT){
8105 if((lit & 0xff) == 0)
8106 /* or'ing with 0 has no effect */
8109 int p = pic16_my_powof2(lit & 0xff);
8111 /* only one bit is set in the literal, so use a bsf instruction */
8112 pic16_emitpcode(POC_BSF,
8113 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8115 if(know_W != (lit & 0xff))
8116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8117 know_W = lit & 0xff;
8118 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8123 if (AOP_TYPE(left) == AOP_ACC) {
8124 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8125 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8127 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8128 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8130 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8131 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8137 // left & result in different registers
8138 if(AOP_TYPE(result) == AOP_CRY){
8140 // if(size), result in bit
8141 // if(!size && ifx), conditional oper: if(left | right)
8142 symbol *tlbl = newiTempLabel(NULL);
8143 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8144 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8148 pic16_emitcode(";XXX setb","c");
8150 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 pic16_emitcode(";XXX orl","a,%s",
8152 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8158 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8159 pic16_outBitC(result);
8161 jmpTrueOrFalse(ifx, tlbl);
8162 } else for(;(size--);offset++){
8164 // result = left & right
8165 if(AOP_TYPE(right) == AOP_LIT){
8166 int t = (lit >> (offset*8)) & 0x0FFL;
8169 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8170 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8172 // pic16_emitcode("movf","%s,w",
8173 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174 // pic16_emitcode("movwf","%s",
8175 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8178 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8179 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8180 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8182 // pic16_emitcode("movlw","0x%x",t);
8183 // pic16_emitcode("iorwf","%s,w",
8184 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185 // pic16_emitcode("movwf","%s",
8186 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8192 // faster than result <- left, anl result,right
8193 // and better if result is SFR
8194 if (AOP_TYPE(left) == AOP_ACC) {
8195 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8196 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8198 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8199 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8201 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8202 // pic16_emitcode("iorwf","%s,w",
8203 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8205 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8206 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8211 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8212 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8213 pic16_freeAsmop(result,NULL,ic,TRUE);
8216 /*-----------------------------------------------------------------*/
8217 /* genXor - code for xclusive or */
8218 /*-----------------------------------------------------------------*/
8219 static void genXor (iCode *ic, iCode *ifx)
8221 operand *left, *right, *result;
8222 int size, offset = 0;
8223 unsigned long lit = 0L;
8228 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
8229 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
8230 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
8232 resolveIfx (&rIfx,ifx);
8234 /* if left is a literal & right is not ||
8235 if left needs acc & right does not */
8236 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
8237 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
8239 operand *tmp = right;
8244 /* if result = right then exchange them */
8245 if (pic16_sameRegs (AOP (result), AOP (right)))
8247 operand *tmp = right ;
8252 /* if right is bit then exchange them */
8253 if (AOP_TYPE (right) == AOP_CRY &&
8254 AOP_TYPE (left) != AOP_CRY)
8256 operand *tmp = right ;
8261 if (AOP_TYPE (right) == AOP_LIT)
8262 lit = ulFromVal (AOP (right)->aopu.aop_lit);
8264 size = AOP_SIZE (result);
8268 if (AOP_TYPE(left) == AOP_CRY)
8270 if (AOP_TYPE(right) == AOP_LIT)
8272 // c = bit & literal;
8275 // lit>>1 != 0 => result = 1
8276 if (AOP_TYPE(result) == AOP_CRY)
8280 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
8281 pic16_emitcode("setb", "%s", AOP(result)->aopu.aop_dir);
8284 continueIfTrue(ifx);
8287 pic16_emitcode("setb", "c");
8294 // lit == 0, result = left
8295 if (size && pic16_sameRegs(AOP(result), AOP(left)))
8297 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
8301 // lit == 1, result = not(left)
8302 if (size && pic16_sameRegs(AOP(result), AOP(left)))
8304 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
8305 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
8306 pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
8311 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
8312 pic16_emitcode("cpl", "c");
8320 symbol *tlbl = newiTempLabel(NULL);
8321 if (AOP_TYPE(right) == AOP_CRY)
8324 pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
8328 int sizer = AOP_SIZE(right);
8330 // if val>>1 != 0, result = 1
8331 pic16_emitcode("setb", "c");
8334 MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
8336 // test the msb of the lsb
8337 pic16_emitcode("anl", "a,#0xfe");
8338 pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
8342 pic16_emitcode("rrc", "a");
8344 pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
8345 pic16_emitcode("cpl", "c");
8346 pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
8351 pic16_outBitC(result);
8353 else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
8354 genIfxJump(ifx, "c");
8358 // if(val ^ 0xZZ) - size = 0, ifx != FALSE -
8359 // bit = val ^ 0xZZ - size = 1, ifx = FALSE -
8360 if ((AOP_TYPE (right) == AOP_LIT) &&
8361 (AOP_TYPE (result) == AOP_CRY) &&
8362 (AOP_TYPE (left) != AOP_CRY))
8364 symbol *tlbl = newiTempLabel (NULL);
8370 for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
8372 unsigned char bytelit = lit;
8377 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
8381 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
8385 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
8386 pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
8394 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
8398 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
8403 /* last non null byte */
8411 // bit = left ^ literal
8415 pic16_emitpLabel (tlbl->key);
8417 // if (left ^ literal)
8422 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
8425 pic16_emitpLabel (tlbl->key);
8429 pic16_outBitC (result);
8433 if (pic16_sameRegs(AOP(result), AOP(left)))
8435 /* if left is same as result */
8436 for (; size--; offset++)
8438 if (AOP_TYPE(right) == AOP_LIT)
8440 int t = (lit >> (offset * 8)) & 0x0FFL;
8444 if (IS_AOP_PREG(left))
8446 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8447 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(left), offset, FALSE, TRUE));
8448 pic16_aopPut(AOP(result), "a", offset);
8452 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8453 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
8454 pic16_emitcode("xrl", "%s,%s",
8455 pic16_aopGet(AOP(left), offset, FALSE, TRUE),
8456 pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8461 if (AOP_TYPE(left) == AOP_ACC)
8462 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8465 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
8466 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
8473 // left ^ result in different registers
8474 if (AOP_TYPE(result) == AOP_CRY)
8477 // if(size), result in bit
8478 // if(!size && ifx), conditional oper: if(left ^ right)
8479 symbol *tlbl = newiTempLabel(NULL);
8480 int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
8482 pic16_emitcode("setb", "c");
8485 if ((AOP_TYPE(right) == AOP_LIT) &&
8486 (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
8488 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8492 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8493 pic16_emitcode("xrl", "a,%s",
8494 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8496 pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
8502 pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
8503 pic16_outBitC(result);
8506 jmpTrueOrFalse(ifx, tlbl);
8510 for (; (size--); offset++)
8513 // result = left ^ right
8514 if (AOP_TYPE(right) == AOP_LIT)
8516 int t = (lit >> (offset * 8)) & 0x0FFL;
8520 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
8521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8522 pic16_emitcode("movf", "%s,w",
8523 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8524 pic16_emitcode("movwf", "%s",
8525 pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8529 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
8530 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8531 pic16_emitcode("comf", "%s,w",
8532 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8533 pic16_emitcode("movwf", "%s",
8534 pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8538 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8539 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
8540 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8541 pic16_emitcode("movlw", "0x%x", t);
8542 pic16_emitcode("xorwf", "%s,w",
8543 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8544 pic16_emitcode("movwf", "%s",
8545 pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8551 // faster than result <- left, anl result,right
8552 // and better if result is SFR
8553 if (AOP_TYPE(left) == AOP_ACC)
8555 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
8556 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8560 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
8561 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
8562 pic16_emitcode("movf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8563 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8565 if ( AOP_TYPE(result) != AOP_ACC)
8567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8568 pic16_emitcode("movwf", "%s", pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8575 pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
8576 pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
8577 pic16_freeAsmop(result, NULL, ic, TRUE);
8580 /*-----------------------------------------------------------------*/
8581 /* genInline - write the inline code out */
8582 /*-----------------------------------------------------------------*/
8583 static void genInline (iCode *ic)
8585 char *buffer, *bp, *bp1;
8586 bool inComment = FALSE;
8588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8590 _G.inLine += (!options.asmpeep);
8592 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
8594 while((bp1=strstr(bp, "\\n"))) {
8602 /* This is an experimental code for #pragma inline
8603 and is temporarily disabled for 2.5.0 release */
8611 cbuf = Safe_strdup(buffer);
8612 cblen = strlen(buffer)+1;
8613 memset(cbuf, 0, cblen);
8618 if(*bp != '%')*bp1++ = *bp++;
8624 if(i>elementsInSet(asmInlineMap))break;
8627 s = indexSet(asmInlineMap, i);
8628 DEBUGpc("searching symbol s = `%s'", s);
8629 sym = findSym(SymbolTab, NULL, s);
8632 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8634 strcat(bp1, sym->rname);
8640 if(strlen(bp1) > cblen - 16) {
8641 int i = strlen(cbuf);
8643 cbuf = realloc(cbuf, cblen);
8644 memset(cbuf+i, 0, 50);
8650 buffer = Safe_strdup( cbuf );
8657 /* emit each line as a code */
8671 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8676 /* Add \n for labels, not dirs such as c:\mydir */
8677 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8682 /* print label, use this special format with NULL directive
8683 * to denote that the argument should not be indented with tab */
8684 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8693 if ((bp1 != bp) && *bp1)
8694 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8698 _G.inLine -= (!options.asmpeep);
8701 /*-----------------------------------------------------------------*/
8702 /* genRRC - rotate right with carry */
8703 /*-----------------------------------------------------------------*/
8704 static void genRRC (iCode *ic)
8706 operand *left , *result ;
8707 int size, offset = 0, same;
8709 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8711 /* rotate right with carry */
8713 result=IC_RESULT(ic);
8714 pic16_aopOp (left,ic,FALSE);
8715 pic16_aopOp (result,ic,TRUE);
8717 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8719 same = pic16_sameRegs(AOP(result),AOP(left));
8721 size = AOP_SIZE(result);
8723 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8725 /* get the lsb and put it into the carry */
8726 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8733 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8735 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8736 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8742 pic16_freeAsmop(left,NULL,ic,TRUE);
8743 pic16_freeAsmop(result,NULL,ic,TRUE);
8746 /*-----------------------------------------------------------------*/
8747 /* genRLC - generate code for rotate left with carry */
8748 /*-----------------------------------------------------------------*/
8749 static void genRLC (iCode *ic)
8751 operand *left , *result ;
8752 int size, offset = 0;
8755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8756 /* rotate right with carry */
8758 result=IC_RESULT(ic);
8759 pic16_aopOp (left,ic,FALSE);
8760 pic16_aopOp (result,ic,TRUE);
8762 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8764 same = pic16_sameRegs(AOP(result),AOP(left));
8766 /* move it to the result */
8767 size = AOP_SIZE(result);
8769 /* get the msb and put it into the carry */
8770 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8777 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8779 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8787 pic16_freeAsmop(left,NULL,ic,TRUE);
8788 pic16_freeAsmop(result,NULL,ic,TRUE);
8792 /* gpasm can get the highest order bit with HIGH/UPPER
8793 * so the following probably is not needed -- VR */
8795 /*-----------------------------------------------------------------*/
8796 /* genGetHbit - generates code get highest order bit */
8797 /*-----------------------------------------------------------------*/
8798 static void genGetHbit (iCode *ic)
8800 operand *left, *result;
8802 result=IC_RESULT(ic);
8803 pic16_aopOp (left,ic,FALSE);
8804 pic16_aopOp (result,ic,FALSE);
8806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8807 /* get the highest order byte into a */
8808 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8809 if(AOP_TYPE(result) == AOP_CRY){
8810 pic16_emitcode("rlc","a");
8811 pic16_outBitC(result);
8814 pic16_emitcode("rl","a");
8815 pic16_emitcode("anl","a,#0x01");
8816 pic16_outAcc(result);
8820 pic16_freeAsmop(left,NULL,ic,TRUE);
8821 pic16_freeAsmop(result,NULL,ic,TRUE);
8825 /*-----------------------------------------------------------------*/
8826 /* AccRol - rotate left accumulator by known count */
8827 /*-----------------------------------------------------------------*/
8828 static void AccRol (int shCount)
8830 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8831 shCount &= 0x0007; // shCount : 0..7
8836 pic16_emitcode("rl","a");
8839 pic16_emitcode("rl","a");
8840 pic16_emitcode("rl","a");
8843 pic16_emitcode("swap","a");
8844 pic16_emitcode("rr","a");
8847 pic16_emitcode("swap","a");
8850 pic16_emitcode("swap","a");
8851 pic16_emitcode("rl","a");
8854 pic16_emitcode("rr","a");
8855 pic16_emitcode("rr","a");
8858 pic16_emitcode("rr","a");
8864 /*-----------------------------------------------------------------*/
8865 /* AccLsh - left shift accumulator by known count */
8866 /*-----------------------------------------------------------------*/
8867 static void AccLsh (int shCount, int doMask)
8869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8875 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8878 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8879 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8882 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8883 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8886 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8889 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8890 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8893 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8894 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8897 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8901 /* no masking is required in genPackBits */
8902 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8906 /*-----------------------------------------------------------------*/
8907 /* AccRsh - right shift accumulator by known count */
8908 /*-----------------------------------------------------------------*/
8909 static void AccRsh (int shCount, int andmask)
8911 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8916 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8919 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8920 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8923 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8924 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8927 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8930 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8931 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8934 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8935 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8938 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8943 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8945 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8949 /*-----------------------------------------------------------------*/
8950 /* AccSRsh - signed right shift accumulator by known count */
8951 /*-----------------------------------------------------------------*/
8952 static void AccSRsh (int shCount)
8955 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8958 pic16_emitcode("mov","c,acc.7");
8959 pic16_emitcode("rrc","a");
8960 } else if(shCount == 2){
8961 pic16_emitcode("mov","c,acc.7");
8962 pic16_emitcode("rrc","a");
8963 pic16_emitcode("mov","c,acc.7");
8964 pic16_emitcode("rrc","a");
8966 tlbl = newiTempLabel(NULL);
8967 /* rotate right accumulator */
8968 AccRol(8 - shCount);
8969 /* and kill the higher order bits */
8970 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8971 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8972 pic16_emitcode("orl","a,#0x%02x",
8973 (unsigned char)~SRMask[shCount]);
8974 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8980 /*-----------------------------------------------------------------*/
8981 /* shiftR1Left2Result - shift right one byte from left to result */
8982 /*-----------------------------------------------------------------*/
8983 static void shiftR1Left2ResultSigned (operand *left, int offl,
8984 operand *result, int offr,
8989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8991 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8995 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8997 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8999 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9008 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9027 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9030 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9031 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9038 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9039 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9040 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
9041 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9048 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9050 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9052 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9053 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9060 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9062 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9063 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9066 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9067 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9068 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
9069 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9070 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9076 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9077 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9078 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9082 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9083 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
9091 /*-----------------------------------------------------------------*/
9092 /* shiftR1Left2Result - shift right one byte from left to result */
9093 /*-----------------------------------------------------------------*/
9094 static void shiftR1Left2Result (operand *left, int offl,
9095 operand *result, int offr,
9096 int shCount, int sign)
9100 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9102 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9104 /* Copy the msb into the carry if signed. */
9106 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9116 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9119 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9128 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9136 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9138 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9139 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9142 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9143 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9149 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9150 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9151 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9156 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9164 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9165 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9166 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9167 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9168 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9173 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9174 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9175 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9184 /*-----------------------------------------------------------------*/
9185 /* shiftL1Left2Result - shift left one byte from left to result */
9186 /*-----------------------------------------------------------------*/
9187 static void shiftL1Left2Result (operand *left, int offl,
9188 operand *result, int offr, int shCount)
9193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9195 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9196 DEBUGpic16_emitcode ("; ***","same = %d",same);
9197 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9199 /* shift left accumulator */
9200 //AccLsh(shCount, 1); // don't comment out just yet...
9201 // pic16_aopPut(AOP(result),"a",offr);
9205 /* Shift left 1 bit position */
9206 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9208 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9210 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9211 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9216 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9217 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9218 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9221 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9222 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9223 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9224 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9225 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9228 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9229 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9230 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9234 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9235 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9236 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9239 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9240 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9241 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9242 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9243 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9246 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9247 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9248 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9252 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9257 /*-----------------------------------------------------------------*/
9258 /* movLeft2Result - move byte from left to result */
9259 /*-----------------------------------------------------------------*/
9260 static void movLeft2Result (operand *left, int offl,
9261 operand *result, int offr)
9264 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9265 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9266 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9268 if (*l == '@' && (IS_AOP_PREG(result))) {
9269 pic16_emitcode("mov","a,%s",l);
9270 pic16_aopPut(AOP(result),"a",offr);
9272 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9278 /*-----------------------------------------------------------------*/
9279 /* shiftL2Left2Result - shift left two bytes from left to result */
9280 /*-----------------------------------------------------------------*/
9281 static void shiftL2Left2Result (operand *left, int offl,
9282 operand *result, int offr, int shCount)
9284 int same = pic16_sameRegs(AOP(result), AOP(left));
9287 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9289 if (same && (offl != offr)) { // shift bytes
9292 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9293 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9295 } else { // just treat as different later on
9308 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9309 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9310 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9314 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9315 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9321 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9322 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9323 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9324 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9325 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9326 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9327 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9329 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9330 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9334 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9335 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9336 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9337 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9338 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9339 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9340 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9341 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9342 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9343 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9346 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9347 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9348 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9349 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9350 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9360 /* note, use a mov/add for the shift since the mov has a
9361 chance of getting optimized out */
9362 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9364 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9365 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9366 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9370 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9371 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9377 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9378 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9380 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9382 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9383 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9384 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9388 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9389 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9393 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9394 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9395 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9396 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9398 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9399 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9400 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9401 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9402 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9403 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9404 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9405 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9408 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9409 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9410 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9411 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9412 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9417 /*-----------------------------------------------------------------*/
9418 /* shiftR2Left2Result - shift right two bytes from left to result */
9419 /*-----------------------------------------------------------------*/
9420 static void shiftR2Left2Result (operand *left, int offl,
9421 operand *result, int offr,
9422 int shCount, int sign)
9424 int same = pic16_sameRegs(AOP(result), AOP(left));
9426 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9428 if (same && (offl != offr)) { // shift right bytes
9431 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9432 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9434 } else { // just treat as different later on
9445 /* obtain sign from left operand */
9447 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9452 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9453 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9455 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9456 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9457 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9458 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9463 /* now get sign from already assigned result (avoid BANKSEL) */
9464 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9467 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9468 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9476 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9477 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9479 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9480 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9481 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9482 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9484 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9485 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9486 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9488 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9489 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9490 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9491 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9492 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9496 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9497 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9501 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9502 pic16_emitpcode(POC_BTFSC,
9503 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9504 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9512 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9513 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9515 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9516 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9517 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9518 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9520 pic16_emitpcode(POC_BTFSC,
9521 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9522 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9524 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9525 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9526 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9527 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9529 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9530 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9531 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9532 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9533 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9534 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9535 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9536 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9538 pic16_emitpcode(POC_BTFSC,
9539 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9540 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9542 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9543 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9550 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9551 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9552 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9553 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9556 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9558 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9563 /*-----------------------------------------------------------------*/
9564 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9565 /*-----------------------------------------------------------------*/
9566 static void shiftLLeftOrResult (operand *left, int offl,
9567 operand *result, int offr, int shCount)
9569 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9571 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9572 /* shift left accumulator */
9574 /* or with result */
9575 /* back to result */
9576 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9579 /*-----------------------------------------------------------------*/
9580 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9581 /*-----------------------------------------------------------------*/
9582 static void shiftRLeftOrResult (operand *left, int offl,
9583 operand *result, int offr, int shCount)
9585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9587 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9588 /* shift right accumulator */
9590 /* or with result */
9591 /* back to result */
9592 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9595 /*-----------------------------------------------------------------*/
9596 /* genlshOne - left shift a one byte quantity by known count */
9597 /*-----------------------------------------------------------------*/
9598 static void genlshOne (operand *result, operand *left, int shCount)
9600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9601 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9604 /*-----------------------------------------------------------------*/
9605 /* genlshTwo - left shift two bytes by known amount != 0 */
9606 /*-----------------------------------------------------------------*/
9607 static void genlshTwo (operand *result,operand *left, int shCount)
9611 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9612 size = pic16_getDataSize(result);
9614 /* if shCount >= 8 */
9620 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9622 movLeft2Result(left, LSB, result, MSB16);
9624 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9627 /* 1 <= shCount <= 7 */
9630 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9632 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9636 /*-----------------------------------------------------------------*/
9637 /* shiftLLong - shift left one long from left to result */
9638 /* offr = LSB or MSB16 */
9639 /*-----------------------------------------------------------------*/
9640 static void shiftLLong (operand *left, operand *result, int offr )
9642 int size = AOP_SIZE(result);
9643 int same = pic16_sameRegs(AOP(left),AOP(result));
9646 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9648 if (same && (offr == MSB16)) { //shift one byte
9649 for(i=size-1;i>=MSB16;i--) {
9650 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9651 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9654 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9657 if (size > LSB+offr ){
9659 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9661 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9662 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9666 if(size > MSB16+offr){
9668 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9670 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9671 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9675 if(size > MSB24+offr){
9677 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9679 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9680 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9684 if(size > MSB32+offr){
9686 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9688 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9689 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9693 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9697 /*-----------------------------------------------------------------*/
9698 /* genlshFour - shift four byte by a known amount != 0 */
9699 /*-----------------------------------------------------------------*/
9700 static void genlshFour (operand *result, operand *left, int shCount)
9704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9705 size = AOP_SIZE(result);
9707 /* if shifting more that 3 bytes */
9708 if (shCount >= 24 ) {
9711 /* lowest order of left goes to the highest
9712 order of the destination */
9713 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9715 movLeft2Result(left, LSB, result, MSB32);
9717 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9718 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9719 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9724 /* more than two bytes */
9725 else if ( shCount >= 16 ) {
9726 /* lower order two bytes goes to higher order two bytes */
9728 /* if some more remaining */
9730 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9732 movLeft2Result(left, MSB16, result, MSB32);
9733 movLeft2Result(left, LSB, result, MSB24);
9735 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9736 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9740 /* if more than 1 byte */
9741 else if ( shCount >= 8 ) {
9742 /* lower order three bytes goes to higher order three bytes */
9746 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9748 movLeft2Result(left, LSB, result, MSB16);
9750 else{ /* size = 4 */
9752 movLeft2Result(left, MSB24, result, MSB32);
9753 movLeft2Result(left, MSB16, result, MSB24);
9754 movLeft2Result(left, LSB, result, MSB16);
9755 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9757 else if(shCount == 1)
9758 shiftLLong(left, result, MSB16);
9760 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9761 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9762 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9763 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9768 /* 1 <= shCount <= 7 */
9769 else if(shCount <= 3)
9771 shiftLLong(left, result, LSB);
9772 while(--shCount >= 1)
9773 shiftLLong(result, result, LSB);
9775 /* 3 <= shCount <= 7, optimize */
9777 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9778 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9779 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9783 /*-----------------------------------------------------------------*/
9784 /* genLeftShiftLiteral - left shifting by known count */
9785 /*-----------------------------------------------------------------*/
9786 void pic16_genLeftShiftLiteral (operand *left,
9791 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
9795 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9796 pic16_freeAsmop(right,NULL,ic,TRUE);
9798 pic16_aopOp(left,ic,FALSE);
9799 pic16_aopOp(result,ic,TRUE);
9801 size = getSize(operandType(result));
9804 pic16_emitcode("; shift left ","result %d, left %d",size,
9808 /* I suppose that the left size >= result size */
9811 movLeft2Result(left, size, result, size);
9815 else if(shCount >= (size * 8))
9817 pic16_aopPut(AOP(result),zero,size);
9821 genlshOne (result,left,shCount);
9826 genlshTwo (result,left,shCount);
9830 genlshFour (result,left,shCount);
9834 pic16_freeAsmop(left,NULL,ic,TRUE);
9835 pic16_freeAsmop(result,NULL,ic,TRUE);
9838 /*-----------------------------------------------------------------*
9839 * genMultiAsm - repeat assembly instruction for size of register.
9840 * if endian == 1, then the high byte (i.e base address + size of
9841 * register) is used first else the low byte is used first;
9842 *-----------------------------------------------------------------*/
9843 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9848 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9861 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9867 #if !(USE_GENERIC_SIGNED_SHIFT)
9868 /*-----------------------------------------------------------------*/
9869 /* genLeftShift - generates code for left shifting */
9870 /*-----------------------------------------------------------------*/
9871 static void genLeftShift (iCode *ic)
9873 operand *left,*right, *result;
9876 symbol *tlbl , *tlbl1;
9879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9881 right = IC_RIGHT(ic);
9883 result = IC_RESULT(ic);
9885 pic16_aopOp(right,ic,FALSE);
9887 /* if the shift count is known then do it
9888 as efficiently as possible */
9889 if (AOP_TYPE(right) == AOP_LIT) {
9890 pic16_genLeftShiftLiteral (left,right,result,ic);
9894 /* shift count is unknown then we have to form
9895 * a loop. Get the loop count in WREG : Note: we take
9896 * only the lower order byte since shifting
9897 * more than 32 bits make no sense anyway, ( the
9898 * largest size of an object can be only 32 bits ) */
9900 pic16_aopOp(left,ic,FALSE);
9901 pic16_aopOp(result,ic,FALSE);
9903 /* now move the left to the result if they are not the
9904 * same, and if size > 1,
9905 * and if right is not same to result (!!!) -- VR */
9906 if (!pic16_sameRegs(AOP(left),AOP(result))
9907 && (AOP_SIZE(result) > 1)) {
9909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9911 size = AOP_SIZE(result);
9916 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9917 if (*l == '@' && (IS_AOP_PREG(result))) {
9919 pic16_emitcode("mov","a,%s",l);
9920 pic16_aopPut(AOP(result),"a",offset);
9924 /* we don't know if left is a literal or a register, take care -- VR */
9925 pic16_mov2f(AOP(result), AOP(left), offset);
9931 size = AOP_SIZE(result);
9933 /* if it is only one byte then */
9935 if(optimized_for_speed) {
9936 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9937 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9938 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9939 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9940 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9941 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9942 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9943 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9944 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9945 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9946 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9947 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9952 tlbl = newiTempLabel(NULL);
9955 /* this is already done, why change it? */
9956 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9957 pic16_mov2f(AOP(result), AOP(left), 0);
9961 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9962 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9963 pic16_emitpLabel(tlbl->key);
9964 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9965 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9967 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9972 if (pic16_sameRegs(AOP(left),AOP(result))) {
9974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9976 tlbl = newiTempLabel(NULL);
9977 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9978 genMultiAsm(POC_RRCF, result, size,1);
9979 pic16_emitpLabel(tlbl->key);
9980 genMultiAsm(POC_RLCF, result, size,0);
9981 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9983 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9987 //tlbl = newiTempLabel(NULL);
9989 //tlbl1 = newiTempLabel(NULL);
9991 //reAdjustPreg(AOP(result));
9993 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9994 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9995 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9997 //pic16_emitcode("add","a,acc");
9998 //pic16_aopPut(AOP(result),"a",offset++);
10000 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10002 // pic16_emitcode("rlc","a");
10003 // pic16_aopPut(AOP(result),"a",offset++);
10005 //reAdjustPreg(AOP(result));
10007 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10008 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10011 tlbl = newiTempLabel(NULL);
10012 tlbl1= newiTempLabel(NULL);
10014 size = AOP_SIZE(result);
10017 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10019 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10021 /* offset should be 0, 1 or 3 */
10023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10025 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10027 pic16_emitpcode(POC_MOVWF, pctemp);
10030 pic16_emitpLabel(tlbl->key);
10033 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10035 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10037 pic16_emitpcode(POC_DECFSZ, pctemp);
10038 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10039 pic16_emitpLabel(tlbl1->key);
10041 pic16_popReleaseTempReg(pctemp,1);
10045 pic16_freeAsmop (right,NULL,ic,TRUE);
10046 pic16_freeAsmop(left,NULL,ic,TRUE);
10047 pic16_freeAsmop(result,NULL,ic,TRUE);
10053 #error old code (left here for reference)
10054 /*-----------------------------------------------------------------*/
10055 /* genLeftShift - generates code for left shifting */
10056 /*-----------------------------------------------------------------*/
10057 static void genLeftShift (iCode *ic)
10059 operand *left,*right, *result;
10062 symbol *tlbl , *tlbl1;
10065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10067 right = IC_RIGHT(ic);
10068 left = IC_LEFT(ic);
10069 result = IC_RESULT(ic);
10071 pic16_aopOp(right,ic,FALSE);
10073 /* if the shift count is known then do it
10074 as efficiently as possible */
10075 if (AOP_TYPE(right) == AOP_LIT) {
10076 pic16_genLeftShiftLiteral (left,right,result,ic);
10080 /* shift count is unknown then we have to form
10081 a loop get the loop count in B : Note: we take
10082 only the lower order byte since shifting
10083 more that 32 bits make no sense anyway, ( the
10084 largest size of an object can be only 32 bits ) */
10087 pic16_aopOp(left,ic,FALSE);
10088 pic16_aopOp(result,ic,FALSE);
10090 /* now move the left to the result if they are not the
10092 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10093 AOP_SIZE(result) > 1) {
10095 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10097 size = AOP_SIZE(result);
10100 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10101 if (*l == '@' && (IS_AOP_PREG(result))) {
10103 pic16_emitcode("mov","a,%s",l);
10104 pic16_aopPut(AOP(result),"a",offset);
10107 /* we don't know if left is a literal or a register, take care -- VR */
10108 pic16_mov2f(AOP(result), AOP(left), offset);
10114 size = AOP_SIZE(result);
10116 /* if it is only one byte then */
10118 if(optimized_for_speed) {
10119 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10121 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10122 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10123 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10124 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10125 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10126 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10127 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10128 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10129 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10130 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10135 tlbl = newiTempLabel(NULL);
10136 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10137 pic16_mov2f(AOP(result), AOP(left), 0);
10139 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10140 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10143 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10144 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10145 pic16_emitpLabel(tlbl->key);
10146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10147 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10149 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10154 if (pic16_sameRegs(AOP(left),AOP(result))) {
10156 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10158 tlbl = newiTempLabel(NULL);
10159 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10160 genMultiAsm(POC_RRCF, result, size,1);
10161 pic16_emitpLabel(tlbl->key);
10162 genMultiAsm(POC_RLCF, result, size,0);
10163 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10165 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10169 //tlbl = newiTempLabel(NULL);
10171 //tlbl1 = newiTempLabel(NULL);
10173 //reAdjustPreg(AOP(result));
10175 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10176 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10177 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10179 //pic16_emitcode("add","a,acc");
10180 //pic16_aopPut(AOP(result),"a",offset++);
10182 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10184 // pic16_emitcode("rlc","a");
10185 // pic16_aopPut(AOP(result),"a",offset++);
10187 //reAdjustPreg(AOP(result));
10189 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10190 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10193 tlbl = newiTempLabel(NULL);
10194 tlbl1= newiTempLabel(NULL);
10196 size = AOP_SIZE(result);
10199 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10201 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10203 /* offset should be 0, 1 or 3 */
10205 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10207 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10209 pic16_emitpcode(POC_MOVWF, pctemp);
10212 pic16_emitpLabel(tlbl->key);
10215 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10217 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10219 pic16_emitpcode(POC_DECFSZ, pctemp);
10220 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10221 pic16_emitpLabel(tlbl1->key);
10223 pic16_popReleaseTempReg(pctemp,1);
10227 pic16_freeAsmop (right,NULL,ic,TRUE);
10228 pic16_freeAsmop(left,NULL,ic,TRUE);
10229 pic16_freeAsmop(result,NULL,ic,TRUE);
10233 /*-----------------------------------------------------------------*/
10234 /* genrshOne - right shift a one byte quantity by known count */
10235 /*-----------------------------------------------------------------*/
10236 static void genrshOne (operand *result, operand *left,
10237 int shCount, int sign)
10239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10240 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10243 /*-----------------------------------------------------------------*/
10244 /* genrshTwo - right shift two bytes by known amount != 0 */
10245 /*-----------------------------------------------------------------*/
10246 static void genrshTwo (operand *result,operand *left,
10247 int shCount, int sign)
10249 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10250 /* if shCount >= 8 */
10251 if (shCount >= 8) {
10254 shiftR1Left2Result(left, MSB16, result, LSB,
10257 movLeft2Result(left, MSB16, result, LSB);
10259 pic16_addSign (result, 1, sign);
10262 /* 1 <= shCount <= 7 */
10264 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10267 /*-----------------------------------------------------------------*/
10268 /* shiftRLong - shift right one long from left to result */
10269 /* offl = LSB or MSB16 */
10270 /*-----------------------------------------------------------------*/
10271 static void shiftRLong (operand *left, int offl,
10272 operand *result, int sign)
10274 int size = AOP_SIZE(result);
10275 int same = pic16_sameRegs(AOP(left),AOP(result));
10277 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10279 if (same && (offl == MSB16)) { //shift one byte right
10280 for(i=MSB16;i<size;i++) {
10281 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10282 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10287 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10293 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10295 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10296 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10299 if(offl == MSB16) {
10300 /* add sign of "a" */
10301 pic16_addSign(result, MSB32, sign);
10305 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10307 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10308 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10312 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10314 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10315 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10319 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10322 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10328 /*-----------------------------------------------------------------*/
10329 /* genrshFour - shift four byte by a known amount != 0 */
10330 /*-----------------------------------------------------------------*/
10331 static void genrshFour (operand *result, operand *left,
10332 int shCount, int sign)
10334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10335 /* if shifting more that 3 bytes */
10336 if(shCount >= 24 ) {
10339 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10341 movLeft2Result(left, MSB32, result, LSB);
10343 pic16_addSign(result, MSB16, sign);
10345 else if(shCount >= 16){
10348 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10350 movLeft2Result(left, MSB24, result, LSB);
10351 movLeft2Result(left, MSB32, result, MSB16);
10353 pic16_addSign(result, MSB24, sign);
10355 else if(shCount >= 8){
10358 shiftRLong(left, MSB16, result, sign);
10359 else if(shCount == 0){
10360 movLeft2Result(left, MSB16, result, LSB);
10361 movLeft2Result(left, MSB24, result, MSB16);
10362 movLeft2Result(left, MSB32, result, MSB24);
10363 pic16_addSign(result, MSB32, sign);
10365 else{ //shcount >= 2
10366 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10367 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10368 /* the last shift is signed */
10369 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10370 pic16_addSign(result, MSB32, sign);
10373 else{ /* 1 <= shCount <= 7 */
10375 shiftRLong(left, LSB, result, sign);
10377 shiftRLong(result, LSB, result, sign);
10380 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10381 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10382 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10387 /*-----------------------------------------------------------------*/
10388 /* genRightShiftLiteral - right shifting by known count */
10389 /*-----------------------------------------------------------------*/
10390 static void genRightShiftLiteral (operand *left,
10396 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
10397 int lsize,res_size;
10399 pic16_freeAsmop(right,NULL,ic,TRUE);
10401 pic16_aopOp(left,ic,FALSE);
10402 pic16_aopOp(result,ic,TRUE);
10404 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10407 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10411 lsize = pic16_getDataSize(left);
10412 res_size = pic16_getDataSize(result);
10413 /* test the LEFT size !!! */
10415 /* I suppose that the left size >= result size */
10417 assert (res_size <= lsize);
10418 while (res_size--) {
10419 pic16_mov2f (AOP(result), AOP(left), res_size);
10423 else if(shCount >= (lsize * 8)){
10425 if(res_size == 1) {
10426 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10428 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10429 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10434 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10435 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10438 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10443 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10448 switch (res_size) {
10450 genrshOne (result,left,shCount,sign);
10454 genrshTwo (result,left,shCount,sign);
10458 genrshFour (result,left,shCount,sign);
10466 pic16_freeAsmop(left,NULL,ic,TRUE);
10467 pic16_freeAsmop(result,NULL,ic,TRUE);
10470 #if !(USE_GENERIC_SIGNED_SHIFT)
10471 /*-----------------------------------------------------------------*/
10472 /* genSignedRightShift - right shift of signed number */
10473 /*-----------------------------------------------------------------*/
10474 static void genSignedRightShift (iCode *ic)
10476 operand *right, *left, *result;
10479 symbol *tlbl, *tlbl1 ;
10482 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10484 /* we do it the hard way put the shift count in b
10485 and loop thru preserving the sign */
10486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10488 right = IC_RIGHT(ic);
10489 left = IC_LEFT(ic);
10490 result = IC_RESULT(ic);
10492 pic16_aopOp(right,ic,FALSE);
10493 pic16_aopOp(left,ic,FALSE);
10494 pic16_aopOp(result,ic,FALSE);
10497 if ( AOP_TYPE(right) == AOP_LIT) {
10498 genRightShiftLiteral (left,right,result,ic,1);
10501 /* shift count is unknown then we have to form
10502 a loop get the loop count in B : Note: we take
10503 only the lower order byte since shifting
10504 more that 32 bits make no sense anyway, ( the
10505 largest size of an object can be only 32 bits ) */
10507 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10508 //pic16_emitcode("inc","b");
10509 //pic16_freeAsmop (right,NULL,ic,TRUE);
10510 //pic16_aopOp(left,ic,FALSE);
10511 //pic16_aopOp(result,ic,FALSE);
10513 /* now move the left to the result if they are not the
10515 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10516 AOP_SIZE(result) > 1) {
10518 size = AOP_SIZE(result);
10522 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10523 if (*l == '@' && IS_AOP_PREG(result)) {
10525 pic16_emitcode("mov","a,%s",l);
10526 pic16_aopPut(AOP(result),"a",offset);
10528 pic16_aopPut(AOP(result),l,offset);
10530 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10531 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10537 /* mov the highest order bit to OVR */
10538 tlbl = newiTempLabel(NULL);
10539 tlbl1= newiTempLabel(NULL);
10541 size = AOP_SIZE(result);
10544 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10546 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10548 /* offset should be 0, 1 or 3 */
10549 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10551 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10553 pic16_emitpcode(POC_MOVWF, pctemp);
10556 pic16_emitpLabel(tlbl->key);
10558 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10559 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10562 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10565 pic16_emitpcode(POC_DECFSZ, pctemp);
10566 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10567 pic16_emitpLabel(tlbl1->key);
10569 pic16_popReleaseTempReg(pctemp,1);
10571 size = AOP_SIZE(result);
10573 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10574 pic16_emitcode("rlc","a");
10575 pic16_emitcode("mov","ov,c");
10576 /* if it is only one byte then */
10578 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10580 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10581 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10582 pic16_emitcode("mov","c,ov");
10583 pic16_emitcode("rrc","a");
10584 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10585 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10586 pic16_aopPut(AOP(result),"a",0);
10590 reAdjustPreg(AOP(result));
10591 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10592 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10593 pic16_emitcode("mov","c,ov");
10595 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10597 pic16_emitcode("rrc","a");
10598 pic16_aopPut(AOP(result),"a",offset--);
10600 reAdjustPreg(AOP(result));
10601 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10602 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10607 pic16_freeAsmop(left,NULL,ic,TRUE);
10608 pic16_freeAsmop(result,NULL,ic,TRUE);
10609 pic16_freeAsmop(right,NULL,ic,TRUE);
10613 #if !(USE_GENERIC_SIGNED_SHIFT)
10614 #warning This implementation of genRightShift() is incomplete!
10615 /*-----------------------------------------------------------------*/
10616 /* genRightShift - generate code for right shifting */
10617 /*-----------------------------------------------------------------*/
10618 static void genRightShift (iCode *ic)
10620 operand *right, *left, *result;
10624 symbol *tlbl, *tlbl1 ;
10626 /* if signed then we do it the hard way preserve the
10627 sign bit moving it inwards */
10628 letype = getSpec(operandType(IC_LEFT(ic)));
10629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10631 if (!SPEC_USIGN(letype)) {
10632 genSignedRightShift (ic);
10636 /* signed & unsigned types are treated the same : i.e. the
10637 signed is NOT propagated inwards : quoting from the
10638 ANSI - standard : "for E1 >> E2, is equivalent to division
10639 by 2**E2 if unsigned or if it has a non-negative value,
10640 otherwise the result is implementation defined ", MY definition
10641 is that the sign does not get propagated */
10643 right = IC_RIGHT(ic);
10644 left = IC_LEFT(ic);
10645 result = IC_RESULT(ic);
10647 pic16_aopOp(right,ic,FALSE);
10649 /* if the shift count is known then do it
10650 as efficiently as possible */
10651 if (AOP_TYPE(right) == AOP_LIT) {
10652 genRightShiftLiteral (left,right,result,ic, 0);
10656 /* shift count is unknown then we have to form
10657 a loop get the loop count in B : Note: we take
10658 only the lower order byte since shifting
10659 more that 32 bits make no sense anyway, ( the
10660 largest size of an object can be only 32 bits ) */
10662 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10663 pic16_emitcode("inc","b");
10664 pic16_aopOp(left,ic,FALSE);
10665 pic16_aopOp(result,ic,FALSE);
10667 /* now move the left to the result if they are not the
10669 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10670 AOP_SIZE(result) > 1) {
10672 size = AOP_SIZE(result);
10675 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10676 if (*l == '@' && IS_AOP_PREG(result)) {
10678 pic16_emitcode("mov","a,%s",l);
10679 pic16_aopPut(AOP(result),"a",offset);
10681 pic16_aopPut(AOP(result),l,offset);
10686 tlbl = newiTempLabel(NULL);
10687 tlbl1= newiTempLabel(NULL);
10688 size = AOP_SIZE(result);
10691 /* if it is only one byte then */
10694 tlbl = newiTempLabel(NULL);
10695 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10696 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10700 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10701 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10702 pic16_emitpLabel(tlbl->key);
10703 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10704 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10706 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10711 reAdjustPreg(AOP(result));
10712 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10713 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10716 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10718 pic16_emitcode("rrc","a");
10719 pic16_aopPut(AOP(result),"a",offset--);
10721 reAdjustPreg(AOP(result));
10723 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10724 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10727 pic16_freeAsmop(left,NULL,ic,TRUE);
10728 pic16_freeAsmop (right,NULL,ic,TRUE);
10729 pic16_freeAsmop(result,NULL,ic,TRUE);
10733 #if (USE_GENERIC_SIGNED_SHIFT)
10734 /*-----------------------------------------------------------------*/
10735 /* genGenericShift - generates code for left or right shifting */
10736 /*-----------------------------------------------------------------*/
10737 static void genGenericShift (iCode *ic, int isShiftLeft) {
10738 operand *left,*right, *result;
10740 int sign, signedCount;
10741 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10742 PIC_OPCODE pos_shift, neg_shift;
10746 right = IC_RIGHT(ic);
10747 left = IC_LEFT(ic);
10748 result = IC_RESULT(ic);
10750 pic16_aopOp(right,ic,FALSE);
10751 pic16_aopOp(left,ic,FALSE);
10752 pic16_aopOp(result,ic,TRUE);
10754 sign = !SPEC_USIGN(operandType (left));
10755 signedCount = !SPEC_USIGN(operandType (right));
10757 /* if the shift count is known then do it
10758 as efficiently as possible */
10759 if (AOP_TYPE(right) == AOP_LIT) {
10760 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
10761 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10762 // we should modify right->aopu.aop_lit here!
10763 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10764 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10766 pic16_genLeftShiftLiteral (left,right,result,ic);
10768 genRightShiftLiteral (left,right,result,ic, sign);
10771 } // if (right is literal)
10773 /* shift count is unknown then we have to form a loop.
10774 * Note: we take only the lower order byte since shifting
10775 * more than 32 bits make no sense anyway, ( the
10776 * largest size of an object can be only 32 bits )
10777 * Note: we perform arithmetic shifts if the left operand is
10778 * signed and we do an (effective) right shift, i. e. we
10779 * shift in the sign bit from the left. */
10781 label_complete = newiTempLabel ( NULL );
10782 label_loop_pos = newiTempLabel ( NULL );
10783 label_loop_neg = NULL;
10784 label_negative = NULL;
10785 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10786 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10789 // additional labels needed
10790 label_loop_neg = newiTempLabel ( NULL );
10791 label_negative = newiTempLabel ( NULL );
10794 // copy source to result -- this will effectively truncate the left operand to the size of result!
10795 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10796 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10797 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10798 pic16_mov2f (AOP(result),AOP(left), offset);
10801 // if result is longer than left, fill with zeros (or sign)
10802 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10803 if (sign && AOP_SIZE(left) > 0) {
10804 // shift signed operand -- fill with sign
10805 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10806 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10807 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10808 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10809 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10812 // shift unsigned operand -- fill result with zeros
10813 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10814 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10817 } // if (size mismatch)
10819 pic16_mov2w (AOP(right), 0);
10820 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10821 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10824 // perform a shift by one (shift count is positive)
10825 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10826 // 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])
10827 pic16_emitpLabel (label_loop_pos->key);
10829 if (sign && (pos_shift == POC_RRCF)) {
10830 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10833 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10834 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10835 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10837 // perform a shift by one (shift count is positive)
10838 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10839 // 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])
10840 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10841 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10843 pic16_emitpLabel (label_loop_pos->key);
10844 if (sign && (pos_shift == POC_RRCF)) {
10845 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10848 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10849 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10850 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10851 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10855 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10857 pic16_emitpLabel (label_negative->key);
10858 // perform a shift by -1 (shift count is negative)
10859 // 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)
10861 pic16_emitpLabel (label_loop_neg->key);
10862 if (sign && (neg_shift == POC_RRCF)) {
10863 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10866 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10867 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10868 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10869 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10870 } // if (signedCount)
10872 pic16_emitpLabel (label_complete->key);
10875 pic16_freeAsmop (right,NULL,ic,TRUE);
10876 pic16_freeAsmop(left,NULL,ic,TRUE);
10877 pic16_freeAsmop(result,NULL,ic,TRUE);
10880 static void genLeftShift (iCode *ic) {
10881 genGenericShift (ic, 1);
10884 static void genRightShift (iCode *ic) {
10885 genGenericShift (ic, 0);
10890 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10891 void pic16_loadFSR0(operand *op, int lit)
10893 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10894 if (AOP_TYPE(op) == AOP_LIT) {
10895 /* handle 12 bit integers correctly */
10896 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
10897 if ((val & 0x0fff) != val) {
10898 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10899 val, (val & 0x0fff) );
10902 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10904 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10907 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10908 // set up FSR0 with address of result
10909 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10910 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10914 /*----------------------------------------------------------------*/
10915 /* pic16_derefPtr - move one byte from the location ptr points to */
10916 /* to WREG (doWrite == 0) or one byte from WREG */
10917 /* to the location ptr points to (doWrite != 0) */
10918 /*----------------------------------------------------------------*/
10919 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10921 if (!IS_PTR(operandType(ptr)))
10923 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10924 else pic16_mov2w (AOP(ptr), 0);
10928 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10929 /* We might determine pointer type right here: */
10930 p_type = DCL_TYPE(operandType(ptr));
10935 if (!fsr0_setup || !*fsr0_setup)
10937 pic16_loadFSR0( ptr, 0 );
10938 if (fsr0_setup) *fsr0_setup = 1;
10941 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10943 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10947 if (AOP(ptr)->aopu.aop_reg[2]) {
10948 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10949 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10950 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10951 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10952 pic16_mov2w(AOP(ptr), 2);
10953 pic16_callGenericPointerRW(doWrite, 1);
10955 // data pointer (just 2 byte given)
10956 if (!fsr0_setup || !*fsr0_setup)
10958 pic16_loadFSR0( ptr, 0 );
10959 if (fsr0_setup) *fsr0_setup = 1;
10962 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10964 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10969 assert (0 && "invalid pointer type specified");
10974 /*-----------------------------------------------------------------*/
10975 /* genUnpackBits - generates code for unpacking bits */
10976 /*-----------------------------------------------------------------*/
10977 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10980 sym_link *etype, *letype;
10981 int blen=0, bstr=0;
10986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10987 etype = getSpec(operandType(result));
10988 letype = getSpec(operandType(left));
10990 // if(IS_BITFIELD(etype)) {
10991 blen = SPEC_BLEN(etype);
10992 bstr = SPEC_BSTR(etype);
10995 lbstr = SPEC_BSTR( letype );
10997 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10998 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
11001 if((blen == 1) && (bstr < 8)
11002 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
11003 /* it is a single bit, so use the appropriate bit instructions */
11004 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
11006 same = pic16_sameRegs(AOP(left),AOP(result));
11007 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
11008 pic16_emitpcode(POC_CLRF, op);
11010 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
11011 /* workaround to reduce the extra lfsr instruction */
11012 pic16_emitpcode(POC_BTFSC,
11013 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
11015 assert (PIC_IS_DATA_PTR (operandType(left)));
11016 pic16_loadFSR0 (left, 0);
11017 pic16_emitpcode(POC_BTFSC,
11018 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11021 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
11022 /* unsigned bitfields result in either 0 or 1 */
11023 pic16_emitpcode(POC_INCF, op);
11025 /* signed bitfields result in either 0 or -1 */
11026 pic16_emitpcode(POC_DECF, op);
11029 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
11032 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
11038 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
11039 // access symbol directly
11040 pic16_mov2w (AOP(left), 0);
11042 pic16_derefPtr (left, ptype, 0, NULL);
11045 /* if we have bitdisplacement then it fits */
11046 /* into this byte completely or if length is */
11047 /* less than a byte */
11048 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
11050 /* shift right acc */
11053 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11054 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
11056 /* VR -- normally I would use the following, but since we use the hack,
11057 * to avoid the masking from AccRsh, why not mask it right now? */
11060 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
11063 /* extend signed bitfields to 8 bits */
11064 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
11066 assert (blen + bstr > 0);
11067 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
11068 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
11071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11073 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
11077 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
11078 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11079 exit(EXIT_FAILURE);
11085 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
11087 int size, offset = 0, leoffset=0 ;
11089 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11090 pic16_aopOp(result, ic, TRUE);
11094 size = AOP_SIZE(result);
11095 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11099 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11100 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11101 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11106 if(AOP(left)->aopu.pcop->type == PO_DIR)
11107 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11109 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11112 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11114 // pic16_DumpOp("(result)",result);
11115 if(is_LitAOp(AOP(result))) {
11116 pic16_mov2w(AOP(left), offset); // patch 8
11117 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11119 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11120 pic16_popGet(AOP(left), offset), //patch 8
11121 pic16_popGet(AOP(result), offset)));
11129 pic16_freeAsmop(result,NULL,ic,TRUE);
11134 /*-----------------------------------------------------------------*/
11135 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11136 /*-----------------------------------------------------------------*/
11137 static void genNearPointerGet (operand *left,
11141 // asmop *aop = NULL;
11142 //regs *preg = NULL ;
11143 sym_link *rtype, *retype;
11144 sym_link *ltype, *letype;
11148 rtype = operandType(result);
11149 retype= getSpec(rtype);
11150 ltype = operandType(left);
11151 letype= getSpec(ltype);
11153 pic16_aopOp(left,ic,FALSE);
11155 // pic16_DumpOp("(left)",left);
11156 // pic16_DumpOp("(result)",result);
11158 /* if left is rematerialisable and
11159 * result is not bit variable type and
11160 * the left is pointer to data space i.e
11161 * lower 128 bytes of space */
11163 if (AOP_TYPE(left) == AOP_PCODE
11164 && !IS_BITFIELD(retype)
11165 && DCL_TYPE(ltype) == POINTER) {
11167 genDataPointerGet (left,result,ic);
11168 pic16_freeAsmop(left, NULL, ic, TRUE);
11172 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11173 pic16_aopOp (result,ic,TRUE);
11175 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11178 if(IS_BITFIELD( retype )
11179 && (SPEC_BLEN(operandType(result))==1)
11183 int bitstrt, bytestrt;
11185 /* if this is bitfield of size 1, see if we are checking the value
11186 * of a single bit in an if-statement,
11187 * if yes, then don't generate usual code, but execute the
11188 * genIfx directly -- VR */
11192 /* CHECK: if next iCode is IFX
11193 * and current result operand is nextic's conditional operand
11194 * and current result operand live ranges ends at nextic's key number
11196 if((nextic->op == IFX)
11197 && (result == IC_COND(nextic))
11198 && (OP_LIVETO(result) == nextic->seq)
11199 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11201 /* everything is ok then */
11202 /* find a way to optimize the genIfx iCode */
11204 bytestrt = SPEC_BSTR(operandType(result))/8;
11205 bitstrt = SPEC_BSTR(operandType(result))%8;
11207 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11209 genIfxpCOpJump(nextic, jop);
11211 pic16_freeAsmop(left, NULL, ic, TRUE);
11212 pic16_freeAsmop(result, NULL, ic, TRUE);
11218 /* if bitfield then unpack the bits */
11219 if (IS_BITFIELD(letype))
11220 genUnpackBits (result, left, NULL, POINTER);
11222 /* we have can just get the values */
11223 int size = AOP_SIZE(result);
11226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11228 pic16_loadFSR0( left, 0 );
11232 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11233 pic16_popGet(AOP(result), offset++)));
11235 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11236 pic16_popGet(AOP(result), offset++)));
11242 /* now some housekeeping stuff */
11244 /* we had to allocate for this iCode */
11245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11246 pic16_freeAsmop(NULL,aop,ic,TRUE);
11248 /* we did not allocate which means left
11249 * already in a pointer register, then
11250 * if size > 0 && this could be used again
11251 * we have to point it back to where it
11253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11254 if (AOP_SIZE(result) > 1
11255 && !OP_SYMBOL(left)->remat
11256 && ( OP_SYMBOL(left)->liveTo > ic->seq
11258 // int size = AOP_SIZE(result) - 1;
11260 // pic16_emitcode("dec","%s",rname);
11266 pic16_freeAsmop(left,NULL,ic,TRUE);
11267 pic16_freeAsmop(result,NULL,ic,TRUE);
11270 /*-----------------------------------------------------------------*/
11271 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11272 /*-----------------------------------------------------------------*/
11273 static void genPagedPointerGet (operand *left,
11278 regs *preg = NULL ;
11280 sym_link *rtype, *retype;
11282 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11284 rtype = operandType(result);
11285 retype= getSpec(rtype);
11287 pic16_aopOp(left,ic,FALSE);
11289 /* if the value is already in a pointer register
11290 then don't need anything more */
11291 if (!AOP_INPREG(AOP(left))) {
11292 /* otherwise get a free pointer register */
11294 preg = getFreePtr(ic,&aop,FALSE);
11295 pic16_emitcode("mov","%s,%s",
11297 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11298 rname = preg->name ;
11300 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11302 pic16_freeAsmop(left,NULL,ic,TRUE);
11303 pic16_aopOp (result,ic,TRUE);
11305 /* if bitfield then unpack the bits */
11306 if (IS_BITFIELD(retype))
11307 genUnpackBits (result,left,rname,PPOINTER);
11309 /* we have can just get the values */
11310 int size = AOP_SIZE(result);
11315 pic16_emitcode("movx","a,@%s",rname);
11316 pic16_aopPut(AOP(result),"a",offset);
11321 pic16_emitcode("inc","%s",rname);
11325 /* now some housekeeping stuff */
11327 /* we had to allocate for this iCode */
11328 pic16_freeAsmop(NULL,aop,ic,TRUE);
11330 /* we did not allocate which means left
11331 already in a pointer register, then
11332 if size > 0 && this could be used again
11333 we have to point it back to where it
11335 if (AOP_SIZE(result) > 1 &&
11336 !OP_SYMBOL(left)->remat &&
11337 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11339 int size = AOP_SIZE(result) - 1;
11341 pic16_emitcode("dec","%s",rname);
11346 pic16_freeAsmop(result,NULL,ic,TRUE);
11352 /* This code is not adjusted to PIC16 and fails utterly.
11353 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11355 /*-----------------------------------------------------------------*/
11356 /* genFarPointerGet - gget value from far space */
11357 /*-----------------------------------------------------------------*/
11358 static void genFarPointerGet (operand *left,
11359 operand *result, iCode *ic)
11362 sym_link *retype = getSpec(operandType(result));
11364 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11366 pic16_aopOp(left,ic,FALSE);
11368 /* if the operand is already in dptr
11369 then we do nothing else we move the value to dptr */
11370 if (AOP_TYPE(left) != AOP_STR) {
11371 /* if this is remateriazable */
11372 if (AOP_TYPE(left) == AOP_IMMD)
11373 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11374 else { /* we need to get it byte by byte */
11375 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11376 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11377 if (options.model == MODEL_FLAT24)
11379 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11383 /* so dptr know contains the address */
11384 pic16_freeAsmop(left,NULL,ic,TRUE);
11385 pic16_aopOp(result,ic,TRUE);
11387 /* if bit then unpack */
11388 if (IS_BITFIELD(retype))
11389 genUnpackBits(result,left,"dptr",FPOINTER);
11391 size = AOP_SIZE(result);
11395 pic16_emitcode("movx","a,@dptr");
11396 pic16_aopPut(AOP(result),"a",offset++);
11398 pic16_emitcode("inc","dptr");
11402 pic16_freeAsmop(result,NULL,ic,TRUE);
11407 /*-----------------------------------------------------------------*/
11408 /* genCodePointerGet - get value from code space */
11409 /*-----------------------------------------------------------------*/
11410 static void genCodePointerGet (operand *left,
11411 operand *result, iCode *ic)
11414 sym_link *retype = getSpec(operandType(result));
11416 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11418 pic16_aopOp(left,ic,FALSE);
11420 /* if the operand is already in dptr
11421 then we do nothing else we move the value to dptr */
11422 if (AOP_TYPE(left) != AOP_STR) {
11423 /* if this is remateriazable */
11424 if (AOP_TYPE(left) == AOP_IMMD)
11425 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11426 else { /* we need to get it byte by byte */
11427 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11428 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11429 if (options.model == MODEL_FLAT24)
11431 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11435 /* so dptr know contains the address */
11436 pic16_freeAsmop(left,NULL,ic,TRUE);
11437 pic16_aopOp(result,ic,FALSE);
11439 /* if bit then unpack */
11440 if (IS_BITFIELD(retype))
11441 genUnpackBits(result,left,"dptr",CPOINTER);
11443 size = AOP_SIZE(result);
11447 pic16_emitcode("clr","a");
11448 pic16_emitcode("movc","a,@a+dptr");
11449 pic16_aopPut(AOP(result),"a",offset++);
11451 pic16_emitcode("inc","dptr");
11455 pic16_freeAsmop(result,NULL,ic,TRUE);
11460 /*-----------------------------------------------------------------*/
11461 /* genGenPointerGet - gget value from generic pointer space */
11462 /*-----------------------------------------------------------------*/
11463 static void genGenPointerGet (operand *left,
11464 operand *result, iCode *ic)
11466 int size, offset, lit;
11467 sym_link *retype = getSpec(operandType(result));
11469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11470 pic16_aopOp(left,ic,FALSE);
11471 pic16_aopOp(result,ic,FALSE);
11472 size = AOP_SIZE(result);
11474 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11476 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11478 lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11479 // load FSR0 from immediate
11480 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11482 // pic16_loadFSR0( left );
11487 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11489 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11496 else { /* we need to get it byte by byte */
11497 // set up FSR0 with address from left
11498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11499 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11505 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11507 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11514 /* if bit then unpack */
11515 if (IS_BITFIELD(retype))
11516 genUnpackBits(result,left,"BAD",GPOINTER);
11519 pic16_freeAsmop(left,NULL,ic,TRUE);
11520 pic16_freeAsmop(result,NULL,ic,TRUE);
11526 /*-----------------------------------------------------------------*/
11527 /* genGenPointerGet - gget value from generic pointer space */
11528 /*-----------------------------------------------------------------*/
11529 static void genGenPointerGet (operand *left,
11530 operand *result, iCode *ic)
11532 int size, offset, lit;
11533 sym_link *letype = getSpec(operandType(left));
11535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11536 pic16_aopOp(left,ic,FALSE);
11537 pic16_aopOp(result,ic,TRUE);
11538 size = AOP_SIZE(result);
11540 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11542 /* if bit then unpack */
11543 if (IS_BITFIELD(letype)) {
11544 genUnpackBits(result,left,"BAD",GPOINTER);
11548 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11550 lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11551 // load FSR0 from immediate
11552 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11554 werror(W_POSSBUG2, __FILE__, __LINE__);
11559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11561 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11568 } else { /* we need to get it byte by byte */
11570 /* set up WREG:PRODL:FSR0L with address from left */
11571 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11572 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11573 pic16_mov2w(AOP(left), 2);
11574 pic16_callGenericPointerRW(0, size);
11576 assignResultValue(result, size, 1);
11582 pic16_freeAsmop(left,NULL,ic,TRUE);
11583 pic16_freeAsmop(result,NULL,ic,TRUE);
11586 /*-----------------------------------------------------------------*/
11587 /* genConstPointerGet - get value from const generic pointer space */
11588 /*-----------------------------------------------------------------*/
11589 static void genConstPointerGet (operand *left,
11590 operand *result, iCode *ic)
11592 //sym_link *retype = getSpec(operandType(result));
11593 // symbol *albl = newiTempLabel(NULL); // patch 15
11594 // symbol *blbl = newiTempLabel(NULL); //
11595 // PIC_OPCODE poc; // patch 15
11599 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11600 pic16_aopOp(left,ic,FALSE);
11601 pic16_aopOp(result,ic,TRUE);
11602 size = AOP_SIZE(result);
11604 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11606 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11608 // set up table pointer
11609 if( (AOP_TYPE(left) == AOP_PCODE)
11610 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11611 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11613 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11614 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11615 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11616 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11617 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11618 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11620 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11621 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11622 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11626 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11627 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11631 pic16_freeAsmop(left,NULL,ic,TRUE);
11632 pic16_freeAsmop(result,NULL,ic,TRUE);
11636 /*-----------------------------------------------------------------*/
11637 /* genPointerGet - generate code for pointer get */
11638 /*-----------------------------------------------------------------*/
11639 static void genPointerGet (iCode *ic)
11641 operand *left, *result ;
11642 sym_link *type, *etype;
11647 left = IC_LEFT(ic);
11648 result = IC_RESULT(ic) ;
11650 /* depending on the type of pointer we need to
11651 move it to the correct pointer register */
11652 type = operandType(left);
11653 etype = getSpec(type);
11656 if (IS_PTR_CONST(type))
11658 if (IS_CODEPTR(type))
11660 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11662 /* if left is of type of pointer then it is simple */
11663 if (IS_PTR(type) && !IS_FUNC(type->next))
11664 p_type = DCL_TYPE(type);
11666 /* we have to go by the storage class */
11667 p_type = PTR_TYPE(SPEC_OCLS(etype));
11669 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11671 if (SPEC_OCLS(etype)->codesp ) {
11672 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11673 //p_type = CPOINTER ;
11675 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11676 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11677 /*p_type = FPOINTER ;*/
11679 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11680 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11681 /* p_type = PPOINTER; */
11683 if (SPEC_OCLS(etype) == idata ) {
11684 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11685 /* p_type = IPOINTER; */
11687 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11688 /* p_type = POINTER ; */
11692 /* now that we have the pointer type we assign
11693 the pointer values */
11698 genNearPointerGet (left,result,ic);
11702 genPagedPointerGet(left,result,ic);
11706 /* PICs do not support FAR pointers... */
11707 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11709 genFarPointerGet (left,result,ic);
11714 genConstPointerGet (left,result,ic);
11715 //pic16_emitcodePointerGet (left,result,ic);
11720 if (IS_PTR_CONST(type))
11721 genConstPointerGet (left,result,ic);
11724 genGenPointerGet (left,result,ic);
11728 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11729 "genPointerGet: illegal pointer type");
11734 /*-----------------------------------------------------------------*/
11735 /* genPackBits - generates code for packed bit storage */
11736 /*-----------------------------------------------------------------*/
11737 static void genPackBits (sym_link *etype , operand *result,
11739 char *rname, int p_type)
11745 int shifted_and_masked = 0;
11746 unsigned long lit = (unsigned long)-1;
11749 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11750 blen = SPEC_BLEN(etype);
11751 bstr = SPEC_BSTR(etype);
11753 retype = getSpec(operandType(right));
11755 if(AOP_TYPE(right) == AOP_LIT) {
11756 lit = ulFromVal (AOP(right)->aopu.aop_lit);
11758 if((blen == 1) && (bstr < 8)) {
11759 /* it is a single bit, so use the appropriate bit instructions */
11761 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11763 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11764 /* workaround to reduce the extra lfsr instruction */
11766 pic16_emitpcode(POC_BSF,
11767 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11769 pic16_emitpcode(POC_BCF,
11770 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11773 if (PIC_IS_DATA_PTR(operandType(result))) {
11774 pic16_loadFSR0(result, 0);
11775 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11776 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11778 /* get old value */
11779 pic16_derefPtr (result, p_type, 0, NULL);
11780 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11781 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11782 /* write back new value */
11783 pic16_derefPtr (result, p_type, 1, NULL);
11789 /* IORLW below is more efficient */
11790 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11791 lit = (lit & ((1UL << blen) - 1)) << bstr;
11792 shifted_and_masked = 1;
11795 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11796 && IS_BITFIELD(retype)
11797 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11801 rblen = SPEC_BLEN( retype );
11802 rbstr = SPEC_BSTR( retype );
11804 if(IS_BITFIELD(etype)) {
11805 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11806 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11808 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11811 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11813 if(IS_BITFIELD(etype)) {
11814 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11816 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11819 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11823 /* move right to W */
11824 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11827 /* if the bit length is less than or */
11828 /* it exactly fits a byte then */
11829 if((shCnt=SPEC_BSTR(etype))
11830 || SPEC_BLEN(etype) <= 8 ) {
11831 int fsr0_setup = 0;
11833 if (blen != 8 || (bstr % 8) != 0) {
11834 // we need to combine the value with the old value
11835 if(!shifted_and_masked)
11837 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11839 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11840 SPEC_BSTR(etype), SPEC_BLEN(etype));
11842 /* shift left acc, do NOT mask the result again */
11845 /* using PRODH as a temporary register here */
11846 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11849 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11850 || IS_DIRECT(result)) {
11851 /* access symbol directly */
11852 pic16_mov2w (AOP(result), 0);
11854 /* get old value */
11855 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11859 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11860 (unsigned char)(0xff >> (8-bstr))) ));
11861 if (!shifted_and_masked) {
11862 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11864 /* We have the shifted and masked (literal) right value in `lit' */
11866 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11868 } else { // if (blen == 8 && (bstr % 8) == 0)
11869 if (shifted_and_masked) {
11870 // move right (literal) to WREG (only case where right is not yet in WREG)
11871 pic16_mov2w(AOP(right), (bstr / 8));
11875 /* write new value back */
11876 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11877 || IS_DIRECT(result)) {
11878 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11880 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11889 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11890 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11891 exit(EXIT_FAILURE);
11895 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11896 rLen = SPEC_BLEN(etype)-8;
11898 /* now generate for lengths greater than one byte */
11902 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11908 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11914 pic16_emitcode("movx","@dptr,a");
11919 DEBUGpic16_emitcode(";lcall","__gptrput");
11927 pic16_mov2w(AOP(right), offset++);
11930 /* last last was not complete */
11932 /* save the byte & read byte */
11935 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11936 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11941 pic16_emitcode ("mov","b,a");
11942 pic16_emitcode("movx","a,@dptr");
11946 pic16_emitcode ("push","b");
11947 pic16_emitcode ("push","acc");
11948 pic16_emitcode ("lcall","__gptrget");
11949 pic16_emitcode ("pop","b");
11955 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11956 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11957 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11958 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11959 // pic16_emitcode ("orl","a,b");
11962 // if (p_type == GPOINTER)
11963 // pic16_emitcode("pop","b");
11968 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11969 // pic16_emitcode("mov","@%s,a",rname);
11973 pic16_emitcode("movx","@dptr,a");
11977 DEBUGpic16_emitcode(";lcall","__gptrput");
11984 // pic16_freeAsmop(right, NULL, ic, TRUE);
11987 /*-----------------------------------------------------------------*/
11988 /* genDataPointerSet - remat pointer to data space */
11989 /*-----------------------------------------------------------------*/
11990 static void genDataPointerSet(operand *right,
11994 int size, offset = 0, resoffset=0 ;
11996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11997 pic16_aopOp(right,ic,FALSE);
11999 size = AOP_SIZE(right);
12001 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12004 if ( AOP_TYPE(result) == AOP_PCODE) {
12005 fprintf(stderr,"genDataPointerSet %s, %d\n",
12006 AOP(result)->aopu.pcop->name,
12007 (AOP(result)->aopu.pcop->type == PO_DIR)?
12008 PCOR(AOP(result)->aopu.pcop)->instance:
12009 PCOI(AOP(result)->aopu.pcop)->offset);
12013 if(AOP(result)->aopu.pcop->type == PO_DIR)
12014 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12017 if (AOP_TYPE(right) == AOP_LIT) {
12018 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
12019 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
12021 pic16_mov2w(AOP(right), offset);
12022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
12028 pic16_freeAsmop(right,NULL,ic,TRUE);
12033 /*-----------------------------------------------------------------*/
12034 /* genNearPointerSet - pic16_emitcode for near pointer put */
12035 /*-----------------------------------------------------------------*/
12036 static void genNearPointerSet (operand *right,
12042 sym_link *ptype = operandType(result);
12043 sym_link *resetype;
12045 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12046 retype= getSpec(operandType(right));
12047 resetype = getSpec(operandType(result));
12049 pic16_aopOp(result,ic,FALSE);
12051 /* if the result is rematerializable &
12052 * in data space & not a bit variable */
12054 /* and result is not a bit variable */
12055 if (AOP_TYPE(result) == AOP_PCODE
12056 // && AOP_TYPE(result) == AOP_IMMD
12057 && DCL_TYPE(ptype) == POINTER
12058 && !IS_BITFIELD(retype)
12059 && !IS_BITFIELD(resetype)) {
12061 genDataPointerSet (right,result,ic);
12062 pic16_freeAsmop(result,NULL,ic,TRUE);
12066 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12067 pic16_aopOp(right,ic,FALSE);
12068 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12070 /* if bitfield then unpack the bits */
12071 if (IS_BITFIELD(resetype)) {
12072 genPackBits (resetype, result, right, NULL, POINTER);
12074 /* we have can just get the values */
12075 int size = AOP_SIZE(right);
12078 pic16_loadFSR0(result, 0);
12080 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12082 if (is_LitOp(right)) {
12083 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12085 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12087 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12089 } else { // no literal
12091 pic16_emitpcode(POC_MOVFF,
12092 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12093 pic16_popCopyReg(&pic16_pc_postinc0)));
12095 pic16_emitpcode(POC_MOVFF,
12096 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12097 pic16_popCopyReg(&pic16_pc_indf0)));
12105 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12106 /* now some housekeeping stuff */
12108 /* we had to allocate for this iCode */
12109 pic16_freeAsmop(NULL,aop,ic,TRUE);
12111 /* we did not allocate which means left
12112 * already in a pointer register, then
12113 * if size > 0 && this could be used again
12114 * we have to point it back to where it
12116 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12117 if (AOP_SIZE(right) > 1
12118 && !OP_SYMBOL(result)->remat
12119 && ( OP_SYMBOL(result)->liveTo > ic->seq
12122 int size = AOP_SIZE(right) - 1;
12125 pic16_emitcode("decf","fsr0,f");
12126 //pic16_emitcode("dec","%s",rname);
12130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12133 pic16_freeAsmop(right,NULL,ic,TRUE);
12134 pic16_freeAsmop(result,NULL,ic,TRUE);
12137 /*-----------------------------------------------------------------*/
12138 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12139 /*-----------------------------------------------------------------*/
12140 static void genPagedPointerSet (operand *right,
12145 regs *preg = NULL ;
12149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12151 retype= getSpec(operandType(right));
12153 pic16_aopOp(result,ic,FALSE);
12155 /* if the value is already in a pointer register
12156 then don't need anything more */
12157 if (!AOP_INPREG(AOP(result))) {
12158 /* otherwise get a free pointer register */
12160 preg = getFreePtr(ic,&aop,FALSE);
12161 pic16_emitcode("mov","%s,%s",
12163 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12164 rname = preg->name ;
12166 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12168 pic16_freeAsmop(result,NULL,ic,TRUE);
12169 pic16_aopOp (right,ic,FALSE);
12171 /* if bitfield then unpack the bits */
12172 if (IS_BITFIELD(retype))
12173 genPackBits (retype,result,right,rname,PPOINTER);
12175 /* we have can just get the values */
12176 int size = AOP_SIZE(right);
12180 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12183 pic16_emitcode("movx","@%s,a",rname);
12186 pic16_emitcode("inc","%s",rname);
12192 /* now some housekeeping stuff */
12194 /* we had to allocate for this iCode */
12195 pic16_freeAsmop(NULL,aop,ic,TRUE);
12197 /* we did not allocate which means left
12198 already in a pointer register, then
12199 if size > 0 && this could be used again
12200 we have to point it back to where it
12202 if (AOP_SIZE(right) > 1 &&
12203 !OP_SYMBOL(result)->remat &&
12204 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12206 int size = AOP_SIZE(right) - 1;
12208 pic16_emitcode("dec","%s",rname);
12213 pic16_freeAsmop(right,NULL,ic,TRUE);
12219 /* This code is not adjusted to PIC16 and fails utterly...
12220 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12222 /*-----------------------------------------------------------------*/
12223 /* genFarPointerSet - set value from far space */
12224 /*-----------------------------------------------------------------*/
12225 static void genFarPointerSet (operand *right,
12226 operand *result, iCode *ic)
12229 sym_link *retype = getSpec(operandType(right));
12231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12232 pic16_aopOp(result,ic,FALSE);
12234 /* if the operand is already in dptr
12235 then we do nothing else we move the value to dptr */
12236 if (AOP_TYPE(result) != AOP_STR) {
12237 /* if this is remateriazable */
12238 if (AOP_TYPE(result) == AOP_IMMD)
12239 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12240 else { /* we need to get it byte by byte */
12241 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12242 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12243 if (options.model == MODEL_FLAT24)
12245 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12249 /* so dptr know contains the address */
12250 pic16_freeAsmop(result,NULL,ic,TRUE);
12251 pic16_aopOp(right,ic,FALSE);
12253 /* if bit then unpack */
12254 if (IS_BITFIELD(retype))
12255 genPackBits(retype,result,right,"dptr",FPOINTER);
12257 size = AOP_SIZE(right);
12261 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12263 pic16_emitcode("movx","@dptr,a");
12265 pic16_emitcode("inc","dptr");
12269 pic16_freeAsmop(right,NULL,ic,TRUE);
12273 /*-----------------------------------------------------------------*/
12274 /* genGenPointerSet - set value from generic pointer space */
12275 /*-----------------------------------------------------------------*/
12277 static void genGenPointerSet (operand *right,
12278 operand *result, iCode *ic)
12280 int i, size, offset, lit;
12281 sym_link *retype = getSpec(operandType(right));
12283 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12285 pic16_aopOp(result,ic,FALSE);
12286 pic16_aopOp(right,ic,FALSE);
12287 size = AOP_SIZE(right);
12290 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12292 /* if the operand is already in dptr
12293 then we do nothing else we move the value to dptr */
12294 if (AOP_TYPE(result) != AOP_STR) {
12295 /* if this is remateriazable */
12296 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12297 // WARNING: anythig until "else" is untested!
12298 if (AOP_TYPE(result) == AOP_IMMD) {
12299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12300 lit = (unsigned) ulFromVal (AOP(result)->aopu.aop_lit);
12301 // load FSR0 from immediate
12302 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12306 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12308 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12314 else { /* we need to get it byte by byte */
12315 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12316 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12318 // set up FSR0 with address of result
12319 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12320 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12322 /* hack hack! see if this the FSR. If so don't load W */
12323 if(AOP_TYPE(right) != AOP_ACC) {
12325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12327 if(AOP_TYPE(right) == AOP_LIT)
12330 // note: pic16_popGet handles sign extension
12331 for(i=0;i<size;i++) {
12332 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12334 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12336 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12341 for(i=0;i<size;i++) {
12343 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12344 pic16_popCopyReg(&pic16_pc_postinc0)));
12346 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12347 pic16_popCopyReg(&pic16_pc_indf0)));
12353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12354 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12356 } // if (AOP_TYPE(result) != AOP_IMMD)
12358 } // if (AOP_TYPE(result) != AOP_STR)
12359 /* so dptr know contains the address */
12362 /* if bit then unpack */
12363 if (IS_BITFIELD(retype))
12364 genPackBits(retype,result,right,"dptr",GPOINTER);
12366 size = AOP_SIZE(right);
12369 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12371 // set up FSR0 with address of result
12372 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12373 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12376 if (AOP_TYPE(right) == AOP_LIT) {
12377 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12379 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12381 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12383 } else { // no literal
12385 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12387 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12395 pic16_freeAsmop(right,NULL,ic,TRUE);
12396 pic16_freeAsmop(result,NULL,ic,TRUE);
12400 static void genGenPointerSet (operand *right,
12401 operand *result, iCode *ic)
12404 sym_link *retype = getSpec(operandType(result));
12406 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12408 pic16_aopOp(result,ic,FALSE);
12409 pic16_aopOp(right,ic,FALSE);
12410 size = AOP_SIZE(right);
12412 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12415 /* if bit then unpack */
12416 if (IS_BITFIELD(retype)) {
12417 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12418 genPackBits(retype,result,right,"dptr",GPOINTER);
12422 size = AOP_SIZE(right);
12424 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12427 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12429 /* value of right+0 is placed on stack, which will be retrieved
12430 * by the support function thus restoring the stack. The important
12431 * thing is that there is no need to manually restore stack pointer
12433 pushaop(AOP(right), 0);
12434 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12435 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12436 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12437 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12439 /* load address to write to in WREG:FSR0H:FSR0L */
12440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12441 pic16_popCopyReg(&pic16_pc_fsr0l)));
12442 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12443 pic16_popCopyReg(&pic16_pc_prodl)));
12444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12446 pic16_callGenericPointerRW(1, size);
12449 pic16_freeAsmop(right,NULL,ic,TRUE);
12450 pic16_freeAsmop(result,NULL,ic,TRUE);
12453 /*-----------------------------------------------------------------*/
12454 /* genPointerSet - stores the value into a pointer location */
12455 /*-----------------------------------------------------------------*/
12456 static void genPointerSet (iCode *ic)
12458 operand *right, *result ;
12459 sym_link *type, *etype;
12464 right = IC_RIGHT(ic);
12465 result = IC_RESULT(ic) ;
12467 /* depending on the type of pointer we need to
12468 move it to the correct pointer register */
12469 type = operandType(result);
12470 etype = getSpec(type);
12472 /* if left is of type of pointer then it is simple */
12473 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12474 p_type = DCL_TYPE(type);
12477 /* we have to go by the storage class */
12478 p_type = PTR_TYPE(SPEC_OCLS(etype));
12480 /* if (SPEC_OCLS(etype)->codesp ) { */
12481 /* p_type = CPOINTER ; */
12484 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12485 /* p_type = FPOINTER ; */
12487 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12488 /* p_type = PPOINTER ; */
12490 /* if (SPEC_OCLS(etype) == idata ) */
12491 /* p_type = IPOINTER ; */
12493 /* p_type = POINTER ; */
12496 /* now that we have the pointer type we assign
12497 the pointer values */
12502 genNearPointerSet (right,result,ic);
12506 genPagedPointerSet (right,result,ic);
12510 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12512 genFarPointerSet (right,result,ic);
12517 genGenPointerSet (right,result,ic);
12521 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12522 "genPointerSet: illegal pointer type");
12526 /*-----------------------------------------------------------------*/
12527 /* genIfx - generate code for Ifx statement */
12528 /*-----------------------------------------------------------------*/
12529 static void genIfx (iCode *ic, iCode *popIc)
12531 operand *cond = IC_COND(ic);
12536 pic16_aopOp(cond,ic,FALSE);
12538 /* get the value into acc */
12539 if (AOP_TYPE(cond) != AOP_CRY)
12540 pic16_toBoolean(cond);
12543 /* the result is now in the accumulator */
12544 pic16_freeAsmop(cond,NULL,ic,TRUE);
12546 /* if there was something to be popped then do it */
12550 /* if the condition is a bit variable */
12551 if (isbit && IS_ITEMP(cond) &&
12553 genIfxJump(ic,"c");
12554 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12556 if (isbit && !IS_ITEMP(cond))
12557 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12559 genIfxJump(ic,"a");
12564 /*-----------------------------------------------------------------*/
12565 /* genAddrOf - generates code for address of */
12566 /*-----------------------------------------------------------------*/
12567 static void genAddrOf (iCode *ic)
12569 operand *result, *left;
12571 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12572 pCodeOp *pcop0, *pcop1, *pcop2;
12576 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12578 sym = OP_SYMBOL( IC_LEFT(ic) );
12581 /* get address of symbol on stack */
12582 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12584 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12585 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12588 // operands on stack are accessible via "FSR2 + index" with index
12589 // starting at 2 for arguments and growing from 0 downwards for
12590 // local variables (index == 0 is not assigned so we add one here)
12592 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12595 assert (soffs < 0);
12599 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12600 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12601 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12602 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12603 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12604 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12605 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12611 // if(pic16_debug_verbose) {
12612 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12613 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12616 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12617 size = AOP_SIZE(IC_RESULT(ic));
12619 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12620 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12621 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12624 pic16_emitpcode(POC_MOVLW, pcop0);
12625 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12626 pic16_emitpcode(POC_MOVLW, pcop1);
12627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12628 pic16_emitpcode(POC_MOVLW, pcop2);
12629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12632 pic16_emitpcode(POC_MOVLW, pcop0);
12633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12634 pic16_emitpcode(POC_MOVLW, pcop1);
12635 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12637 pic16_emitpcode(POC_MOVLW, pcop0);
12638 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12641 pic16_freeAsmop(left, NULL, ic, FALSE);
12643 pic16_freeAsmop(result,NULL,ic,TRUE);
12648 /*-----------------------------------------------------------------*/
12649 /* genFarFarAssign - assignment when both are in far space */
12650 /*-----------------------------------------------------------------*/
12651 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12653 int size = AOP_SIZE(right);
12656 /* first push the right side on to the stack */
12658 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12660 pic16_emitcode ("push","acc");
12663 pic16_freeAsmop(right,NULL,ic,FALSE);
12664 /* now assign DPTR to result */
12665 pic16_aopOp(result,ic,FALSE);
12666 size = AOP_SIZE(result);
12668 pic16_emitcode ("pop","acc");
12669 pic16_aopPut(AOP(result),"a",--offset);
12671 pic16_freeAsmop(result,NULL,ic,FALSE);
12676 /*-----------------------------------------------------------------*/
12677 /* genAssign - generate code for assignment */
12678 /*-----------------------------------------------------------------*/
12679 static void genAssign (iCode *ic)
12681 operand *result, *right;
12682 sym_link *restype, *rtype;
12683 int size, offset,know_W;
12684 unsigned long lit = 0L;
12686 result = IC_RESULT(ic);
12687 right = IC_RIGHT(ic) ;
12691 /* if they are the same */
12692 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12695 /* reversed order operands are aopOp'ed so that result operand
12696 * is effective in case right is a stack symbol. This maneauver
12697 * allows to use the _G.resDirect flag later */
12698 pic16_aopOp(result,ic,TRUE);
12699 pic16_aopOp(right,ic,FALSE);
12701 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12703 /* if they are the same registers */
12704 if (pic16_sameRegs(AOP(right),AOP(result)))
12707 /* if the result is a bit */
12708 if (AOP_TYPE(result) == AOP_CRY) {
12709 /* if the right size is a literal then
12710 we know what the value is */
12711 if (AOP_TYPE(right) == AOP_LIT) {
12713 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12714 pic16_popGet(AOP(result),0));
12716 if (((int) operandLitValue(right)))
12717 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12718 AOP(result)->aopu.aop_dir,
12719 AOP(result)->aopu.aop_dir);
12721 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12722 AOP(result)->aopu.aop_dir,
12723 AOP(result)->aopu.aop_dir);
12728 /* the right is also a bit variable */
12729 if (AOP_TYPE(right) == AOP_CRY) {
12730 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12731 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12732 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12737 /* we need to or */
12738 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12739 pic16_toBoolean(right);
12741 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12742 //pic16_aopPut(AOP(result),"a",0);
12746 /* bit variables done */
12748 size = AOP_SIZE(result);
12751 /* bit variables done */
12753 size = AOP_SIZE(result);
12754 restype = operandType(result);
12755 rtype = operandType(right);
12758 if(AOP_TYPE(right) == AOP_LIT) {
12759 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12761 lit = ulFromVal (AOP(right)->aopu.aop_lit);
12763 /* patch tag for literals that are cast to pointers */
12764 if (IS_CODEPTR(restype)) {
12765 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12766 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12768 if (IS_GENPTR(restype))
12770 if (IS_CODEPTR(rtype)) {
12771 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12772 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12773 } else if (PIC_IS_DATA_PTR(rtype)) {
12774 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12775 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12776 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12777 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12778 } else if (IS_PTR(rtype)) {
12779 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12780 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12786 unsigned long lit_int;
12791 if(IS_FIXED16X16(operandType(right))) {
12792 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12794 /* take care if literal is a float */
12795 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12796 lit = info.lit_int;
12801 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12802 // sizeof(unsigned long int), sizeof(float));
12805 if (AOP_TYPE(right) == AOP_REG) {
12806 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12808 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12813 /* when do we have to read the program memory?
12814 * - if right itself is a symbol in code space
12815 * (we don't care what it points to if it's a pointer)
12816 * - AND right is not a function (we would want its address)
12818 if(AOP_TYPE(right) != AOP_LIT
12819 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12820 && !IS_FUNC(OP_SYM_TYPE(right))
12821 && !IS_ITEMP(right)) {
12823 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12824 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12826 // set up table pointer
12827 if(is_LitOp(right)) {
12828 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12829 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12830 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12831 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12832 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12833 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12834 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12836 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12837 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12838 pic16_popCopyReg(&pic16_pc_tblptrl)));
12839 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12840 pic16_popCopyReg(&pic16_pc_tblptrh)));
12841 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12842 pic16_popCopyReg(&pic16_pc_tblptru)));
12845 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12846 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12848 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12849 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12850 pic16_popGet(AOP(result),offset)));
12854 /* FIXME: for pointers we need to extend differently (according
12855 * to pointer type DATA/CODE/EEPROM/... :*/
12856 size = getSize(OP_SYM_TYPE(right));
12857 if(AOP_SIZE(result) > size) {
12858 size = AOP_SIZE(result) - size;
12860 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12868 /* VR - What is this?! */
12869 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12870 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12872 if(aopIdx(AOP(result),0) == 4) {
12873 /* this is a workaround to save value of right into wreg too,
12874 * value of wreg is going to be used later */
12875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12876 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12877 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12881 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12885 size = AOP_SIZE(right);
12886 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12889 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12890 if(AOP_TYPE(right) == AOP_LIT) {
12892 if(know_W != (lit&0xff))
12893 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12895 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12897 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12901 } else if (AOP_TYPE(right) == AOP_CRY) {
12902 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12904 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12905 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12906 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12908 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12909 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12910 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12912 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12914 if(!_G.resDirect) { /* use this aopForSym feature */
12915 if(AOP_TYPE(result) == AOP_ACC) {
12916 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12918 if(AOP_TYPE(right) == AOP_ACC) {
12919 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12921 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12928 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12931 pic16_freeAsmop (right,NULL,ic,FALSE);
12932 pic16_freeAsmop (result,NULL,ic,TRUE);
12935 /*-----------------------------------------------------------------*/
12936 /* genJumpTab - generates code for jump table */
12937 /*-----------------------------------------------------------------*/
12938 static void genJumpTab (iCode *ic)
12943 pCodeOp *jt_offs_hi;
12948 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12949 /* get the condition into accumulator */
12950 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12952 /* multiply by three */
12953 pic16_emitcode("add","a,acc");
12954 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12956 jtab = newiTempLabel(NULL);
12957 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12958 pic16_emitcode("jmp","@a+dptr");
12959 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12962 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12963 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12965 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12966 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12967 pic16_emitpLabel(jtab->key);
12971 jt_offs = pic16_popGetTempReg(0);
12972 jt_offs_hi = pic16_popGetTempReg(1);
12973 jt_label = pic16_popGetLabel (jtab->key);
12974 //fprintf (stderr, "Creating jump table...\n");
12976 // calculate offset into jump table (idx * sizeof (GOTO))
12977 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12978 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12979 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12980 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12981 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12982 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12983 pic16_emitpcode(POC_MOVWF , jt_offs);
12985 // prepare PCLATx (set to first entry in jump table)
12986 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12987 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12988 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12989 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12990 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12992 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12993 pic16_emitpcode(POC_ADDWF , jt_offs);
12994 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12995 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12997 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12999 // release temporaries and prepare jump into table (new PCL --> WREG)
13000 pic16_emitpcode(POC_MOVFW , jt_offs);
13001 pic16_popReleaseTempReg (jt_offs_hi, 1);
13002 pic16_popReleaseTempReg (jt_offs, 0);
13004 // jump into the table
13005 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13007 pic16_emitpLabelFORCE(jtab->key);
13010 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13011 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
13013 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13014 /* now generate the jump labels */
13015 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13016 jtab = setNextItem(IC_JTLABELS(ic))) {
13017 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13018 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13021 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13025 /*-----------------------------------------------------------------*/
13026 /* genMixedOperation - gen code for operators between mixed types */
13027 /*-----------------------------------------------------------------*/
13029 TSD - Written for the PIC port - but this unfortunately is buggy.
13030 This routine is good in that it is able to efficiently promote
13031 types to different (larger) sizes. Unfortunately, the temporary
13032 variables that are optimized out by this routine are sometimes
13033 used in other places. So until I know how to really parse the
13034 iCode tree, I'm going to not be using this routine :(.
13036 static int genMixedOperation (iCode *ic)
13039 operand *result = IC_RESULT(ic);
13040 sym_link *ctype = operandType(IC_LEFT(ic));
13041 operand *right = IC_RIGHT(ic);
13047 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13049 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13055 nextright = IC_RIGHT(nextic);
13056 nextleft = IC_LEFT(nextic);
13057 nextresult = IC_RESULT(nextic);
13059 pic16_aopOp(right,ic,FALSE);
13060 pic16_aopOp(result,ic,FALSE);
13061 pic16_aopOp(nextright, nextic, FALSE);
13062 pic16_aopOp(nextleft, nextic, FALSE);
13063 pic16_aopOp(nextresult, nextic, FALSE);
13065 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13067 operand *t = right;
13071 pic16_emitcode(";remove right +","");
13073 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13075 operand *t = right;
13079 pic16_emitcode(";remove left +","");
13083 big = AOP_SIZE(nextleft);
13084 small = AOP_SIZE(nextright);
13086 switch(nextic->op) {
13089 pic16_emitcode(";optimize a +","");
13090 /* if unsigned or not an integral type */
13091 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13092 pic16_emitcode(";add a bit to something","");
13095 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13097 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13098 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13099 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13101 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13109 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13110 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13111 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13114 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13116 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13117 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13118 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13119 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13120 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13123 pic16_emitcode("rlf","known_zero,w");
13130 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13131 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13132 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13134 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13144 pic16_freeAsmop(right,NULL,ic,TRUE);
13145 pic16_freeAsmop(result,NULL,ic,TRUE);
13146 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13147 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13149 nextic->generated = 1;
13156 /*-----------------------------------------------------------------*/
13157 /* genCast - gen code for casting */
13158 /*-----------------------------------------------------------------*/
13159 static void genCast (iCode *ic)
13161 operand *result = IC_RESULT(ic);
13162 sym_link *ctype = operandType(IC_LEFT(ic));
13163 sym_link *rtype = operandType(IC_RIGHT(ic));
13164 sym_link *restype = operandType(IC_RESULT(ic));
13165 operand *right = IC_RIGHT(ic);
13171 /* if they are equivalent then do nothing */
13172 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13175 pic16_aopOp(result,ic,FALSE);
13176 pic16_aopOp(right,ic,FALSE) ;
13178 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13181 /* if the result is a bit */
13182 if (AOP_TYPE(result) == AOP_CRY) {
13184 /* if the right size is a literal then
13185 * we know what the value is */
13186 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13188 if (AOP_TYPE(right) == AOP_LIT) {
13189 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13190 pic16_popGet(AOP(result),0));
13192 if (((int) operandLitValue(right)))
13193 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13194 AOP(result)->aopu.aop_dir,
13195 AOP(result)->aopu.aop_dir);
13197 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13198 AOP(result)->aopu.aop_dir,
13199 AOP(result)->aopu.aop_dir);
13203 /* the right is also a bit variable */
13204 if (AOP_TYPE(right) == AOP_CRY) {
13206 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13208 pic16_emitcode("clrc","");
13209 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13210 AOP(right)->aopu.aop_dir,
13211 AOP(right)->aopu.aop_dir);
13212 pic16_aopPut(AOP(result),"c",0);
13216 /* we need to or */
13217 if (AOP_TYPE(right) == AOP_REG) {
13218 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13219 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13220 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13222 pic16_toBoolean(right);
13223 pic16_aopPut(AOP(result),"a",0);
13227 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13230 size = AOP_SIZE(result);
13232 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13234 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13235 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13236 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13239 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13244 if(IS_BITFIELD(getSpec(restype))
13245 && IS_BITFIELD(getSpec(rtype))) {
13246 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13249 /* port from pic14 to cope with generic pointers */
13250 if (PIC_IS_TAGGED(restype))
13252 operand *result = IC_RESULT(ic);
13253 //operand *left = IC_LEFT(ic);
13254 operand *right = IC_RIGHT(ic);
13257 /* copy common part */
13258 int max, size = AOP_SIZE(result);
13259 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13260 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13265 pic16_mov2w (AOP(right), size);
13266 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13269 /* upcast into generic pointer type? */
13270 if (IS_GENPTR(restype)
13271 && !PIC_IS_TAGGED(rtype)
13272 && (AOP_SIZE(result) > max))
13274 /* determine appropriate tag for right */
13275 if (PIC_IS_DATA_PTR(rtype))
13276 tag = GPTR_TAG_DATA;
13277 else if (IS_CODEPTR(rtype))
13278 tag = GPTR_TAG_CODE;
13279 else if (PIC_IS_DATA_PTR(ctype)) {
13280 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13281 tag = GPTR_TAG_DATA;
13282 } else if (IS_CODEPTR(ctype)) {
13283 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13284 tag = GPTR_TAG_CODE;
13285 } else if (IS_PTR(rtype)) {
13286 PERFORM_ONCE(weirdcast,
13287 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13289 tag = GPTR_TAG_DATA;
13291 PERFORM_ONCE(weirdcast,
13292 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13294 tag = GPTR_TAG_DATA;
13297 assert (AOP_SIZE(result) == 3);
13298 /* zero-extend address... */
13299 for (size = max; size < AOP_SIZE(result)-1; size++)
13300 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13301 /* ...and add tag */
13302 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13303 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13304 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13305 for (size = max; size < AOP_SIZE(result)-1; size++)
13306 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13307 /* add __code tag */
13308 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13309 } else if (AOP_SIZE(result) > max) {
13310 /* extend non-pointers */
13311 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13312 pic16_addSign(result, max, 0);
13317 /* if they are the same size : or less */
13318 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13320 /* if they are in the same place */
13321 if (pic16_sameRegs(AOP(right),AOP(result)))
13324 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13326 if (IS_PTR_CONST(rtype))
13328 if (IS_CODEPTR(rtype))
13330 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13333 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13335 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13337 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13340 if(AOP_TYPE(right) == AOP_IMMD) {
13341 pCodeOp *pcop0, *pcop1, *pcop2;
13342 symbol *sym = OP_SYMBOL( right );
13344 size = AOP_SIZE(result);
13346 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13348 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13350 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13353 pic16_emitpcode(POC_MOVLW, pcop0);
13354 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13355 pic16_emitpcode(POC_MOVLW, pcop1);
13356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13357 pic16_emitpcode(POC_MOVLW, pcop2);
13358 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13361 pic16_emitpcode(POC_MOVLW, pcop0);
13362 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13363 pic16_emitpcode(POC_MOVLW, pcop1);
13364 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13366 pic16_emitpcode(POC_MOVLW, pcop0);
13367 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13371 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13372 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13373 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13375 if(AOP_SIZE(result) < 2) {
13376 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13378 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13382 /* if they in different places then copy */
13383 size = AOP_SIZE(result);
13386 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13387 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13394 /* if the result is of type pointer */
13395 if (IS_PTR(ctype)) {
13397 sym_link *type = operandType(right);
13398 sym_link *etype = getSpec(type);
13400 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13402 /* pointer to generic pointer */
13403 if (IS_GENPTR(ctype)) {
13407 p_type = DCL_TYPE(type);
13409 /* we have to go by the storage class */
13410 p_type = PTR_TYPE(SPEC_OCLS(etype));
13412 /* if (SPEC_OCLS(etype)->codesp ) */
13413 /* p_type = CPOINTER ; */
13415 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13416 /* p_type = FPOINTER ; */
13418 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13419 /* p_type = PPOINTER; */
13421 /* if (SPEC_OCLS(etype) == idata ) */
13422 /* p_type = IPOINTER ; */
13424 /* p_type = POINTER ; */
13427 /* the first two bytes are known */
13428 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13429 size = GPTRSIZE - 1;
13432 if(offset < AOP_SIZE(right)) {
13433 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13434 pic16_mov2f(AOP(result), AOP(right), offset);
13436 if ((AOP_TYPE(right) == AOP_PCODE) &&
13437 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13438 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13442 pic16_aopPut(AOP(result),
13443 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13448 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13451 /* the last byte depending on type */
13456 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13460 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13464 pic16_emitcode(";BUG!? ","%d",__LINE__);
13469 if (GPTRSIZE > AOP_SIZE(right)) {
13470 // assume __data pointer... THIS MIGHT BE WRONG!
13471 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13473 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13478 /* this should never happen */
13479 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13480 "got unknown pointer type");
13483 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13489 /* just copy the pointers */
13490 size = AOP_SIZE(result);
13493 pic16_aopPut(AOP(result),
13494 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13503 /* so we now know that the size of destination is greater
13504 than the size of the source.
13505 Now, if the next iCode is an operator then we might be
13506 able to optimize the operation without performing a cast.
13508 if(genMixedOperation(ic))
13511 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13513 /* we move to result for the size of source */
13514 size = AOP_SIZE(right);
13519 pic16_mov2f(AOP(result), AOP(right), offset);
13523 /* now depending on the sign of the destination */
13524 size = AOP_SIZE(result) - AOP_SIZE(right);
13525 /* if unsigned or not an integral type */
13526 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13528 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13530 /* we need to extend the sign :( */
13533 /* Save one instruction of casting char to int */
13534 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13535 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13536 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13538 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13541 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13543 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13545 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13553 pic16_freeAsmop(right,NULL,ic,TRUE);
13554 pic16_freeAsmop(result,NULL,ic,TRUE);
13558 /*-----------------------------------------------------------------*/
13559 /* genDjnz - generate decrement & jump if not zero instrucion */
13560 /*-----------------------------------------------------------------*/
13561 static int genDjnz (iCode *ic, iCode *ifx)
13563 symbol *lbl, *lbl1;
13564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13569 /* if the if condition has a false label
13570 then we cannot save */
13574 /* if the minus is not of the form
13576 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13577 !IS_OP_LITERAL(IC_RIGHT(ic)))
13580 if (operandLitValue(IC_RIGHT(ic)) != 1)
13583 /* if the size of this greater than one then no
13585 if (getSize(operandType(IC_RESULT(ic))) > 1)
13588 /* otherwise we can save BIG */
13589 lbl = newiTempLabel(NULL);
13590 lbl1= newiTempLabel(NULL);
13592 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13594 if (IS_AOP_PREG(IC_RESULT(ic))) {
13595 pic16_emitcode("dec","%s",
13596 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13597 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13598 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13602 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13605 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13606 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13610 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13611 ifx->generated = 1;
13615 /*-----------------------------------------------------------------*/
13616 /* genReceive - generate code for a receive iCode */
13617 /*-----------------------------------------------------------------*/
13618 static void genReceive (iCode *ic)
13624 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13625 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13627 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13629 if (isOperandInFarSpace(IC_RESULT(ic))
13630 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13631 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13633 int size = getSize(operandType(IC_RESULT(ic)));
13634 int offset = pic16_fReturnSizePic - size;
13638 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13639 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13643 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13645 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13646 size = AOP_SIZE(IC_RESULT(ic));
13649 pic16_emitcode ("pop","acc");
13650 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13653 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13655 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13658 /* set pseudo stack pointer to where it should be - dw*/
13659 GpsuedoStkPtr = ic->parmBytes;
13661 /* setting GpsuedoStkPtr has side effects here: */
13662 /* FIXME: What's the correct size of the return(ed) value?
13663 * For now, assuming '4' as before... */
13664 assignResultValue(IC_RESULT(ic), 4, 0);
13667 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13670 /*-----------------------------------------------------------------*/
13671 /* genDummyRead - generate code for dummy read of volatiles */
13672 /*-----------------------------------------------------------------*/
13674 genDummyRead (iCode * ic)
13680 if (op && IS_SYMOP(op)) {
13681 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13682 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13685 pic16_aopOp (op, ic, FALSE);
13686 for (i=0; i < AOP_SIZE(op); i++) {
13687 // may need to protect this from the peepholer -- this is not nice but works...
13688 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13689 pic16_mov2w (AOP(op),i);
13690 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13692 pic16_freeAsmop (op, NULL, ic, TRUE);
13694 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13698 /*-----------------------------------------------------------------*/
13699 /* genpic16Code - generate code for pic16 based controllers */
13700 /*-----------------------------------------------------------------*/
13702 * At this point, ralloc.c has gone through the iCode and attempted
13703 * to optimize in a way suitable for a PIC. Now we've got to generate
13704 * PIC instructions that correspond to the iCode.
13706 * Once the instructions are generated, we'll pass through both the
13707 * peep hole optimizer and the pCode optimizer.
13708 *-----------------------------------------------------------------*/
13710 void genpic16Code (iCode *lic)
13715 lineHead = lineCurr = NULL;
13717 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13718 pic16_addpBlock(pb);
13721 /* if debug information required */
13722 if (options.debug && currFunc) {
13724 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13729 for (ic = lic ; ic ; ic = ic->next ) {
13731 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13732 if ( cln != ic->lineno ) {
13733 if ( options.debug ) {
13734 debugFile->writeCLine (ic);
13737 if(!options.noCcodeInAsm) {
13738 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13739 printCLine(ic->filename, ic->lineno)));
13745 if(options.iCodeInAsm) {
13748 /* insert here code to print iCode as comment */
13749 iLine = printILine(ic);
13750 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13754 /* if the result is marked as
13755 * spilt and rematerializable or code for
13756 * this has already been generated then
13758 if (resultRemat(ic) || ic->generated )
13761 /* depending on the operation */
13780 /* IPOP happens only when trying to restore a
13781 * spilt live range, if there is an ifx statement
13782 * following this pop then the if statement might
13783 * be using some of the registers being popped which
13784 * would destroy the contents of the register so
13785 * we need to check for this condition and handle it */
13787 && ic->next->op == IFX
13788 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13789 genIfx (ic->next,ic);
13807 genEndFunction (ic);
13823 pic16_genPlus (ic) ;
13827 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13828 pic16_genMinus (ic);
13844 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13848 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13854 /* note these two are xlated by algebraic equivalence
13855 * during parsing SDCC.y */
13856 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13857 "got '>=' or '<=' shouldn't have come here");
13861 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13873 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13877 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13881 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13905 genRightShift (ic);
13908 case GET_VALUE_AT_ADDRESS:
13913 if (POINTER_SET(ic))
13940 addSet(&_G.sendSet,ic);
13943 case DUMMY_READ_VOLATILE:
13953 /* now we are ready to call the
13954 peep hole optimizer */
13955 if (!options.nopeep)
13956 peepHole (&lineHead);
13958 /* now do the actual printing */
13959 printLine (lineHead, codeOutBuf);
13962 DFPRINTF((stderr,"printing pBlock\n\n"));
13963 pic16_printpBlock(stdout,pb);