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__);
8912 assert ((shCount >= 0) && (shCount <= 8));
8917 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8920 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8921 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8924 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8925 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8928 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8931 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8932 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8935 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8936 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8939 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8942 // Rotating by 8 is a NOP.
8947 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8949 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8952 /*-----------------------------------------------------------------*/
8953 /* shiftR1Left2Result - shift right one byte from left to result */
8954 /*-----------------------------------------------------------------*/
8955 static void shiftR1Left2ResultSigned (operand *left, int offl,
8956 operand *result, int offr,
8961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8962 assert ((shCount >= 0) && (shCount <= 8));
8964 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8966 /* Do NOT use result for intermediate results, it might be an SFR!. */
8970 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
8971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
8976 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
8978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
8980 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
8981 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
8986 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
8987 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
8988 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
8989 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
8990 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
8991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
8995 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
8996 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
8997 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
8998 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
8999 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
9000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9004 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9005 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
9006 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
9007 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9012 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9013 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
9015 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
9016 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
9017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9021 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9022 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
9024 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
9025 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9030 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9031 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
9032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9037 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
9042 /*-----------------------------------------------------------------*/
9043 /* shiftR1Left2Result - shift right one byte from left to result */
9044 /*-----------------------------------------------------------------*/
9045 static void shiftR1Left2Result (operand *left, int offl,
9046 operand *result, int offr,
9047 int shCount, int sign)
9051 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9052 assert ((shCount >= 0) && (shCount <= 8));
9054 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9056 /* Copy the msb into the carry if signed. */
9058 shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
9062 /* Do NOT use result for intermediate results, it might be an SFR!. */
9066 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
9067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9074 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
9076 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9077 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
9078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9083 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9084 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9085 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
9086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9090 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9091 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9092 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9093 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9097 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9098 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9099 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9103 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9104 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9105 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9106 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9110 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9111 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9112 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
9113 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9117 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9118 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
9119 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9123 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
9128 /*-----------------------------------------------------------------*/
9129 /* shiftL1Left2Result - shift left one byte from left to result */
9130 /*-----------------------------------------------------------------*/
9131 static void shiftL1Left2Result (operand *left, int offl,
9132 operand *result, int offr, int shCount)
9136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9137 assert ((shCount >= 0) && (shCount <= 8));
9139 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9141 /* Do NOT use result for intermediate results, it might be an SFR!. */
9145 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
9146 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9153 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
9155 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9156 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9162 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9163 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9164 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
9165 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9169 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9170 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9171 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
9172 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9176 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9177 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9178 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9182 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9183 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9184 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
9185 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9189 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9190 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9191 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
9192 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9196 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9197 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
9198 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9202 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
9207 /*-----------------------------------------------------------------*/
9208 /* movLeft2Result - move byte from left to result */
9209 /*-----------------------------------------------------------------*/
9210 static void movLeft2Result (operand *left, int offl,
9211 operand *result, int offr)
9214 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9215 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9216 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9218 if (*l == '@' && (IS_AOP_PREG(result))) {
9219 pic16_emitcode("mov","a,%s",l);
9220 pic16_aopPut(AOP(result),"a",offr);
9222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9223 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9228 /*-----------------------------------------------------------------*/
9229 /* shiftL2Left2Result - shift left two bytes from left to result */
9230 /*-----------------------------------------------------------------*/
9231 static void shiftL2Left2Result (operand *left, int offl,
9232 operand *result, int offr, int shCount)
9234 int same = pic16_sameRegs(AOP(result), AOP(left));
9237 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9239 if (same && (offl != offr)) { // shift bytes
9242 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9243 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9245 } else { // just treat as different later on
9258 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9259 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9260 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9264 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9265 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9271 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9272 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9273 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9274 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9275 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9276 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9277 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9279 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9280 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9284 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9285 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9286 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9287 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9288 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9289 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9290 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9291 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9292 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9293 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9297 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9298 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9300 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9310 /* note, use a mov/add for the shift since the mov has a
9311 chance of getting optimized out */
9312 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9313 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9314 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9315 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9316 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9320 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9321 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9327 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9328 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9329 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9330 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9332 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9333 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9334 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9338 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9339 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9343 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9344 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9345 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9348 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9349 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9350 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9351 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9352 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9353 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9354 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9355 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9358 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9359 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9360 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9361 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9362 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9367 /*-----------------------------------------------------------------*/
9368 /* shiftR2Left2Result - shift right two bytes from left to result */
9369 /*-----------------------------------------------------------------*/
9370 static void shiftR2Left2Result (operand *left, int offl,
9371 operand *result, int offr,
9372 int shCount, int sign)
9374 int same = pic16_sameRegs(AOP(result), AOP(left));
9376 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9378 if (same && (offl != offr)) { // shift right bytes
9381 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9382 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9384 } else { // just treat as different later on
9395 /* obtain sign from left operand */
9397 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9402 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9403 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9405 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9406 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9407 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9408 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9413 /* now get sign from already assigned result (avoid BANKSEL) */
9414 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9417 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9418 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9425 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9426 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9427 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9429 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9430 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9431 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9432 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9434 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9435 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9436 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9438 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9440 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9441 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9442 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9446 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9447 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9451 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9452 pic16_emitpcode(POC_BTFSC,
9453 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9454 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9462 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9463 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9465 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9466 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9467 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9468 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9470 pic16_emitpcode(POC_BTFSC,
9471 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9472 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9474 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9475 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9476 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9477 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9479 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9480 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9481 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9482 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9483 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9484 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9485 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9486 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9488 pic16_emitpcode(POC_BTFSC,
9489 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9490 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9492 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9493 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9500 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9501 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9502 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9503 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9506 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9508 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9513 /*-----------------------------------------------------------------*/
9514 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9515 /*-----------------------------------------------------------------*/
9516 static void shiftLLeftOrResult (operand *left, int offl,
9517 operand *result, int offr, int shCount)
9519 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9521 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9522 /* shift left accumulator */
9524 /* or with result */
9525 /* back to result */
9526 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9529 /*-----------------------------------------------------------------*/
9530 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9531 /*-----------------------------------------------------------------*/
9532 static void shiftRLeftOrResult (operand *left, int offl,
9533 operand *result, int offr, int shCount)
9535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9537 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9538 /* shift right accumulator */
9540 /* or with result */
9541 /* back to result */
9542 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9545 /*-----------------------------------------------------------------*/
9546 /* genlshOne - left shift a one byte quantity by known count */
9547 /*-----------------------------------------------------------------*/
9548 static void genlshOne (operand *result, operand *left, int shCount)
9550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9551 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9554 /*-----------------------------------------------------------------*/
9555 /* genlshTwo - left shift two bytes by known amount != 0 */
9556 /*-----------------------------------------------------------------*/
9557 static void genlshTwo (operand *result,operand *left, int shCount)
9561 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9562 size = pic16_getDataSize(result);
9564 /* if shCount >= 8 */
9570 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9572 movLeft2Result(left, LSB, result, MSB16);
9574 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9577 /* 1 <= shCount <= 7 */
9580 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9582 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9586 /*-----------------------------------------------------------------*/
9587 /* shiftLLong - shift left one long from left to result */
9588 /* offr = LSB or MSB16 */
9589 /*-----------------------------------------------------------------*/
9590 static void shiftLLong (operand *left, operand *result, int offr )
9592 int size = AOP_SIZE(result);
9593 int same = pic16_sameRegs(AOP(left),AOP(result));
9596 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9598 if (same && (offr == MSB16)) { //shift one byte
9599 for(i=size-1;i>=MSB16;i--) {
9600 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9601 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9604 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9607 if (size > LSB+offr ){
9609 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9611 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9612 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9616 if(size > MSB16+offr){
9618 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9620 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9621 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9625 if(size > MSB24+offr){
9627 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9629 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9630 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9634 if(size > MSB32+offr){
9636 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9638 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9639 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9643 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9647 /*-----------------------------------------------------------------*/
9648 /* genlshFour - shift four byte by a known amount != 0 */
9649 /*-----------------------------------------------------------------*/
9650 static void genlshFour (operand *result, operand *left, int shCount)
9654 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9655 size = AOP_SIZE(result);
9657 /* if shifting more that 3 bytes */
9658 if (shCount >= 24 ) {
9661 /* lowest order of left goes to the highest
9662 order of the destination */
9663 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9665 movLeft2Result(left, LSB, result, MSB32);
9667 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9669 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9674 /* more than two bytes */
9675 else if ( shCount >= 16 ) {
9676 /* lower order two bytes goes to higher order two bytes */
9678 /* if some more remaining */
9680 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9682 movLeft2Result(left, MSB16, result, MSB32);
9683 movLeft2Result(left, LSB, result, MSB24);
9685 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9686 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9690 /* if more than 1 byte */
9691 else if ( shCount >= 8 ) {
9692 /* lower order three bytes goes to higher order three bytes */
9696 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9698 movLeft2Result(left, LSB, result, MSB16);
9700 else{ /* size = 4 */
9702 movLeft2Result(left, MSB24, result, MSB32);
9703 movLeft2Result(left, MSB16, result, MSB24);
9704 movLeft2Result(left, LSB, result, MSB16);
9705 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9707 else if(shCount == 1)
9708 shiftLLong(left, result, MSB16);
9710 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9711 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9712 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9713 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9718 /* 1 <= shCount <= 7 */
9719 else if(shCount <= 3)
9721 shiftLLong(left, result, LSB);
9722 while(--shCount >= 1)
9723 shiftLLong(result, result, LSB);
9725 /* 3 <= shCount <= 7, optimize */
9727 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9728 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9729 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9733 /*-----------------------------------------------------------------*/
9734 /* genLeftShiftLiteral - left shifting by known count */
9735 /*-----------------------------------------------------------------*/
9736 void pic16_genLeftShiftLiteral (operand *left,
9741 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
9745 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9746 pic16_freeAsmop(right,NULL,ic,TRUE);
9748 pic16_aopOp(left,ic,FALSE);
9749 pic16_aopOp(result,ic,TRUE);
9751 size = getSize(operandType(result));
9754 pic16_emitcode("; shift left ","result %d, left %d",size,
9758 /* I suppose that the left size >= result size */
9761 movLeft2Result(left, size, result, size);
9765 else if(shCount >= (size * 8))
9767 pic16_aopPut(AOP(result),zero,size);
9771 genlshOne (result,left,shCount);
9776 genlshTwo (result,left,shCount);
9780 genlshFour (result,left,shCount);
9784 pic16_freeAsmop(left,NULL,ic,TRUE);
9785 pic16_freeAsmop(result,NULL,ic,TRUE);
9788 /*-----------------------------------------------------------------*
9789 * genMultiAsm - repeat assembly instruction for size of register.
9790 * if endian == 1, then the high byte (i.e base address + size of
9791 * register) is used first else the low byte is used first;
9792 *-----------------------------------------------------------------*/
9793 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9798 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9811 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9817 #if !(USE_GENERIC_SIGNED_SHIFT)
9818 /*-----------------------------------------------------------------*/
9819 /* genLeftShift - generates code for left shifting */
9820 /*-----------------------------------------------------------------*/
9821 static void genLeftShift (iCode *ic)
9823 operand *left,*right, *result;
9826 symbol *tlbl , *tlbl1;
9829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9831 right = IC_RIGHT(ic);
9833 result = IC_RESULT(ic);
9835 pic16_aopOp(right,ic,FALSE);
9837 /* if the shift count is known then do it
9838 as efficiently as possible */
9839 if (AOP_TYPE(right) == AOP_LIT) {
9840 pic16_genLeftShiftLiteral (left,right,result,ic);
9844 /* shift count is unknown then we have to form
9845 * a loop. Get the loop count in WREG : Note: we take
9846 * only the lower order byte since shifting
9847 * more than 32 bits make no sense anyway, ( the
9848 * largest size of an object can be only 32 bits ) */
9850 pic16_aopOp(left,ic,FALSE);
9851 pic16_aopOp(result,ic,FALSE);
9853 /* now move the left to the result if they are not the
9854 * same, and if size > 1,
9855 * and if right is not same to result (!!!) -- VR */
9856 if (!pic16_sameRegs(AOP(left),AOP(result))
9857 && (AOP_SIZE(result) > 1)) {
9859 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9861 size = AOP_SIZE(result);
9866 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9867 if (*l == '@' && (IS_AOP_PREG(result))) {
9869 pic16_emitcode("mov","a,%s",l);
9870 pic16_aopPut(AOP(result),"a",offset);
9874 /* we don't know if left is a literal or a register, take care -- VR */
9875 pic16_mov2f(AOP(result), AOP(left), offset);
9881 size = AOP_SIZE(result);
9883 /* if it is only one byte then */
9885 if(optimized_for_speed) {
9886 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9887 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9888 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9889 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9890 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9891 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9892 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9893 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9894 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9895 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9896 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9897 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9902 tlbl = newiTempLabel(NULL);
9905 /* this is already done, why change it? */
9906 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9907 pic16_mov2f(AOP(result), AOP(left), 0);
9911 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9912 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9913 pic16_emitpLabel(tlbl->key);
9914 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9915 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9917 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9922 if (pic16_sameRegs(AOP(left),AOP(result))) {
9924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9926 tlbl = newiTempLabel(NULL);
9927 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9928 genMultiAsm(POC_RRCF, result, size,1);
9929 pic16_emitpLabel(tlbl->key);
9930 genMultiAsm(POC_RLCF, result, size,0);
9931 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9933 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9937 //tlbl = newiTempLabel(NULL);
9939 //tlbl1 = newiTempLabel(NULL);
9941 //reAdjustPreg(AOP(result));
9943 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9944 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9945 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9947 //pic16_emitcode("add","a,acc");
9948 //pic16_aopPut(AOP(result),"a",offset++);
9950 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9952 // pic16_emitcode("rlc","a");
9953 // pic16_aopPut(AOP(result),"a",offset++);
9955 //reAdjustPreg(AOP(result));
9957 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9958 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9961 tlbl = newiTempLabel(NULL);
9962 tlbl1= newiTempLabel(NULL);
9964 size = AOP_SIZE(result);
9967 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9969 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9971 /* offset should be 0, 1 or 3 */
9973 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9975 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9977 pic16_emitpcode(POC_MOVWF, pctemp);
9980 pic16_emitpLabel(tlbl->key);
9983 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9985 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9987 pic16_emitpcode(POC_DECFSZ, pctemp);
9988 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9989 pic16_emitpLabel(tlbl1->key);
9991 pic16_popReleaseTempReg(pctemp,1);
9995 pic16_freeAsmop (right,NULL,ic,TRUE);
9996 pic16_freeAsmop(left,NULL,ic,TRUE);
9997 pic16_freeAsmop(result,NULL,ic,TRUE);
10003 #error old code (left here for reference)
10004 /*-----------------------------------------------------------------*/
10005 /* genLeftShift - generates code for left shifting */
10006 /*-----------------------------------------------------------------*/
10007 static void genLeftShift (iCode *ic)
10009 operand *left,*right, *result;
10012 symbol *tlbl , *tlbl1;
10015 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10017 right = IC_RIGHT(ic);
10018 left = IC_LEFT(ic);
10019 result = IC_RESULT(ic);
10021 pic16_aopOp(right,ic,FALSE);
10023 /* if the shift count is known then do it
10024 as efficiently as possible */
10025 if (AOP_TYPE(right) == AOP_LIT) {
10026 pic16_genLeftShiftLiteral (left,right,result,ic);
10030 /* shift count is unknown then we have to form
10031 a loop get the loop count in B : Note: we take
10032 only the lower order byte since shifting
10033 more that 32 bits make no sense anyway, ( the
10034 largest size of an object can be only 32 bits ) */
10037 pic16_aopOp(left,ic,FALSE);
10038 pic16_aopOp(result,ic,FALSE);
10040 /* now move the left to the result if they are not the
10042 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10043 AOP_SIZE(result) > 1) {
10045 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10047 size = AOP_SIZE(result);
10050 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10051 if (*l == '@' && (IS_AOP_PREG(result))) {
10053 pic16_emitcode("mov","a,%s",l);
10054 pic16_aopPut(AOP(result),"a",offset);
10057 /* we don't know if left is a literal or a register, take care -- VR */
10058 pic16_mov2f(AOP(result), AOP(left), offset);
10064 size = AOP_SIZE(result);
10066 /* if it is only one byte then */
10068 if(optimized_for_speed) {
10069 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10070 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10071 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10072 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10074 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10075 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10076 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10077 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10078 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10079 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10080 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10083 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10085 tlbl = newiTempLabel(NULL);
10086 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10087 pic16_mov2f(AOP(result), AOP(left), 0);
10089 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10090 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10093 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10094 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10095 pic16_emitpLabel(tlbl->key);
10096 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10097 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10099 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10104 if (pic16_sameRegs(AOP(left),AOP(result))) {
10106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10108 tlbl = newiTempLabel(NULL);
10109 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10110 genMultiAsm(POC_RRCF, result, size,1);
10111 pic16_emitpLabel(tlbl->key);
10112 genMultiAsm(POC_RLCF, result, size,0);
10113 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10115 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10119 //tlbl = newiTempLabel(NULL);
10121 //tlbl1 = newiTempLabel(NULL);
10123 //reAdjustPreg(AOP(result));
10125 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10126 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10127 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10129 //pic16_emitcode("add","a,acc");
10130 //pic16_aopPut(AOP(result),"a",offset++);
10132 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10134 // pic16_emitcode("rlc","a");
10135 // pic16_aopPut(AOP(result),"a",offset++);
10137 //reAdjustPreg(AOP(result));
10139 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10140 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10143 tlbl = newiTempLabel(NULL);
10144 tlbl1= newiTempLabel(NULL);
10146 size = AOP_SIZE(result);
10149 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10153 /* offset should be 0, 1 or 3 */
10155 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10157 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10159 pic16_emitpcode(POC_MOVWF, pctemp);
10162 pic16_emitpLabel(tlbl->key);
10165 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10167 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10169 pic16_emitpcode(POC_DECFSZ, pctemp);
10170 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10171 pic16_emitpLabel(tlbl1->key);
10173 pic16_popReleaseTempReg(pctemp,1);
10177 pic16_freeAsmop (right,NULL,ic,TRUE);
10178 pic16_freeAsmop(left,NULL,ic,TRUE);
10179 pic16_freeAsmop(result,NULL,ic,TRUE);
10183 /*-----------------------------------------------------------------*/
10184 /* genrshOne - right shift a one byte quantity by known count */
10185 /*-----------------------------------------------------------------*/
10186 static void genrshOne (operand *result, operand *left,
10187 int shCount, int sign)
10189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10190 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10193 /*-----------------------------------------------------------------*/
10194 /* genrshTwo - right shift two bytes by known amount != 0 */
10195 /*-----------------------------------------------------------------*/
10196 static void genrshTwo (operand *result,operand *left,
10197 int shCount, int sign)
10199 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10200 /* if shCount >= 8 */
10201 if (shCount >= 8) {
10204 shiftR1Left2Result(left, MSB16, result, LSB,
10207 movLeft2Result(left, MSB16, result, LSB);
10209 pic16_addSign (result, 1, sign);
10212 /* 1 <= shCount <= 7 */
10214 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10217 /*-----------------------------------------------------------------*/
10218 /* shiftRLong - shift right one long from left to result */
10219 /* offl = LSB or MSB16 */
10220 /*-----------------------------------------------------------------*/
10221 static void shiftRLong (operand *left, int offl,
10222 operand *result, int sign)
10224 int size = AOP_SIZE(result);
10225 int same = pic16_sameRegs(AOP(left),AOP(result));
10227 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10229 if (same && (offl == MSB16)) { //shift one byte right
10230 for(i=MSB16;i<size;i++) {
10231 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10232 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10237 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10243 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10245 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10246 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10249 if(offl == MSB16) {
10250 /* add sign of "a" */
10251 pic16_addSign(result, MSB32, sign);
10255 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10257 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10262 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10264 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10269 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10272 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10278 /*-----------------------------------------------------------------*/
10279 /* genrshFour - shift four byte by a known amount != 0 */
10280 /*-----------------------------------------------------------------*/
10281 static void genrshFour (operand *result, operand *left,
10282 int shCount, int sign)
10284 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10285 /* if shifting more that 3 bytes */
10286 if(shCount >= 24 ) {
10289 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10291 movLeft2Result(left, MSB32, result, LSB);
10293 pic16_addSign(result, MSB16, sign);
10295 else if(shCount >= 16){
10298 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10300 movLeft2Result(left, MSB24, result, LSB);
10301 movLeft2Result(left, MSB32, result, MSB16);
10303 pic16_addSign(result, MSB24, sign);
10305 else if(shCount >= 8){
10308 shiftRLong(left, MSB16, result, sign);
10309 else if(shCount == 0){
10310 movLeft2Result(left, MSB16, result, LSB);
10311 movLeft2Result(left, MSB24, result, MSB16);
10312 movLeft2Result(left, MSB32, result, MSB24);
10313 pic16_addSign(result, MSB32, sign);
10315 else{ //shcount >= 2
10316 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10317 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10318 /* the last shift is signed */
10319 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10320 pic16_addSign(result, MSB32, sign);
10323 else{ /* 1 <= shCount <= 7 */
10325 shiftRLong(left, LSB, result, sign);
10327 shiftRLong(result, LSB, result, sign);
10330 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10331 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10332 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10337 /*-----------------------------------------------------------------*/
10338 /* genRightShiftLiteral - right shifting by known count */
10339 /*-----------------------------------------------------------------*/
10340 static void genRightShiftLiteral (operand *left,
10346 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
10347 int lsize,res_size;
10349 pic16_freeAsmop(right,NULL,ic,TRUE);
10351 pic16_aopOp(left,ic,FALSE);
10352 pic16_aopOp(result,ic,TRUE);
10354 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10357 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10361 lsize = pic16_getDataSize(left);
10362 res_size = pic16_getDataSize(result);
10363 /* test the LEFT size !!! */
10365 /* I suppose that the left size >= result size */
10366 if (shCount == 0) {
10367 assert (res_size <= lsize);
10368 while (res_size--) {
10369 pic16_mov2f (AOP(result), AOP(left), res_size);
10371 } else if (shCount >= (lsize * 8)) {
10378 * even for 8-bit operands; result might be an SFR.
10380 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
10381 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
10382 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10383 while (res_size--) {
10384 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
10386 } else { // unsigned
10387 while (res_size--) {
10388 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
10391 } else { // 0 < shCount < 8*lsize
10392 switch (res_size) {
10394 genrshOne (result,left,shCount,sign);
10398 genrshTwo (result,left,shCount,sign);
10402 genrshFour (result,left,shCount,sign);
10409 pic16_freeAsmop(left,NULL,ic,TRUE);
10410 pic16_freeAsmop(result,NULL,ic,TRUE);
10413 #if !(USE_GENERIC_SIGNED_SHIFT)
10414 /*-----------------------------------------------------------------*/
10415 /* genSignedRightShift - right shift of signed number */
10416 /*-----------------------------------------------------------------*/
10417 static void genSignedRightShift (iCode *ic)
10419 operand *right, *left, *result;
10422 symbol *tlbl, *tlbl1 ;
10425 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10427 /* we do it the hard way put the shift count in b
10428 and loop thru preserving the sign */
10429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10431 right = IC_RIGHT(ic);
10432 left = IC_LEFT(ic);
10433 result = IC_RESULT(ic);
10435 pic16_aopOp(right,ic,FALSE);
10436 pic16_aopOp(left,ic,FALSE);
10437 pic16_aopOp(result,ic,FALSE);
10440 if ( AOP_TYPE(right) == AOP_LIT) {
10441 genRightShiftLiteral (left,right,result,ic,1);
10444 /* shift count is unknown then we have to form
10445 a loop get the loop count in B : Note: we take
10446 only the lower order byte since shifting
10447 more that 32 bits make no sense anyway, ( the
10448 largest size of an object can be only 32 bits ) */
10450 /* now move the left to the result if they are not the
10452 if (!pic16_sameRegs(AOP(left), AOP(result))
10453 && AOP_SIZE(result) > 1)
10455 size = AOP_SIZE(result);
10458 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
10459 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10464 /* mov the highest order bit to OVR */
10465 tlbl = newiTempLabel(NULL);
10466 tlbl1= newiTempLabel(NULL);
10468 size = AOP_SIZE(result);
10471 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10473 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10475 /* offset should be 0, 1 or 3 */
10476 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10478 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10480 pic16_emitpcode(POC_MOVWF, pctemp);
10483 pic16_emitpLabel(tlbl->key);
10485 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10486 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10489 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10492 pic16_emitpcode(POC_DECFSZ, pctemp);
10493 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10494 pic16_emitpLabel(tlbl1->key);
10496 pic16_popReleaseTempReg(pctemp,1);
10498 pic16_freeAsmop(left,NULL,ic,TRUE);
10499 pic16_freeAsmop(result,NULL,ic,TRUE);
10500 pic16_freeAsmop(right,NULL,ic,TRUE);
10504 #if !(USE_GENERIC_SIGNED_SHIFT)
10505 #warning This implementation of genRightShift() is incomplete!
10506 /*-----------------------------------------------------------------*/
10507 /* genRightShift - generate code for right shifting */
10508 /*-----------------------------------------------------------------*/
10509 static void genRightShift (iCode *ic)
10511 operand *right, *left, *result;
10515 symbol *tlbl, *tlbl1 ;
10517 /* if signed then we do it the hard way preserve the
10518 sign bit moving it inwards */
10519 letype = getSpec(operandType(IC_LEFT(ic)));
10520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10522 if (!SPEC_USIGN(letype)) {
10523 genSignedRightShift (ic);
10527 /* signed & unsigned types are treated the same : i.e. the
10528 signed is NOT propagated inwards : quoting from the
10529 ANSI - standard : "for E1 >> E2, is equivalent to division
10530 by 2**E2 if unsigned or if it has a non-negative value,
10531 otherwise the result is implementation defined ", MY definition
10532 is that the sign does not get propagated */
10534 right = IC_RIGHT(ic);
10535 left = IC_LEFT(ic);
10536 result = IC_RESULT(ic);
10538 pic16_aopOp(right,ic,FALSE);
10540 /* if the shift count is known then do it
10541 as efficiently as possible */
10542 if (AOP_TYPE(right) == AOP_LIT) {
10543 genRightShiftLiteral (left,right,result,ic, 0);
10547 /* shift count is unknown then we have to form
10548 a loop get the loop count in B : Note: we take
10549 only the lower order byte since shifting
10550 more that 32 bits make no sense anyway, ( the
10551 largest size of an object can be only 32 bits ) */
10553 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10554 pic16_emitcode("inc","b");
10555 pic16_aopOp(left,ic,FALSE);
10556 pic16_aopOp(result,ic,FALSE);
10558 /* now move the left to the result if they are not the
10560 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10561 AOP_SIZE(result) > 1) {
10563 size = AOP_SIZE(result);
10566 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10567 if (*l == '@' && IS_AOP_PREG(result)) {
10569 pic16_emitcode("mov","a,%s",l);
10570 pic16_aopPut(AOP(result),"a",offset);
10572 pic16_aopPut(AOP(result),l,offset);
10577 tlbl = newiTempLabel(NULL);
10578 tlbl1= newiTempLabel(NULL);
10579 size = AOP_SIZE(result);
10582 /* if it is only one byte then */
10585 tlbl = newiTempLabel(NULL);
10586 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10587 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10588 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10591 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10592 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10593 pic16_emitpLabel(tlbl->key);
10594 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10602 reAdjustPreg(AOP(result));
10603 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10604 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10607 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10609 pic16_emitcode("rrc","a");
10610 pic16_aopPut(AOP(result),"a",offset--);
10612 reAdjustPreg(AOP(result));
10614 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10615 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10618 pic16_freeAsmop(left,NULL,ic,TRUE);
10619 pic16_freeAsmop (right,NULL,ic,TRUE);
10620 pic16_freeAsmop(result,NULL,ic,TRUE);
10624 #if (USE_GENERIC_SIGNED_SHIFT)
10625 /*-----------------------------------------------------------------*/
10626 /* genGenericShift - generates code for left or right shifting */
10627 /*-----------------------------------------------------------------*/
10628 static void genGenericShift (iCode *ic, int isShiftLeft) {
10629 operand *left,*right, *result;
10631 int sign, signedCount;
10632 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10633 PIC_OPCODE pos_shift, neg_shift;
10637 right = IC_RIGHT(ic);
10638 left = IC_LEFT(ic);
10639 result = IC_RESULT(ic);
10641 pic16_aopOp(right,ic,FALSE);
10642 pic16_aopOp(left,ic,FALSE);
10643 pic16_aopOp(result,ic,TRUE);
10645 sign = !SPEC_USIGN(operandType (left));
10646 signedCount = !SPEC_USIGN(operandType (right));
10648 /* if the shift count is known then do it
10649 as efficiently as possible */
10650 if (AOP_TYPE(right) == AOP_LIT) {
10651 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
10652 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10653 // we should modify right->aopu.aop_lit here!
10654 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10655 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10657 pic16_genLeftShiftLiteral (left,right,result,ic);
10659 genRightShiftLiteral (left,right,result,ic, sign);
10662 } // if (right is literal)
10664 /* shift count is unknown then we have to form a loop.
10665 * Note: we take only the lower order byte since shifting
10666 * more than 32 bits make no sense anyway, ( the
10667 * largest size of an object can be only 32 bits )
10668 * Note: we perform arithmetic shifts if the left operand is
10669 * signed and we do an (effective) right shift, i. e. we
10670 * shift in the sign bit from the left. */
10672 label_complete = newiTempLabel ( NULL );
10673 label_loop_pos = newiTempLabel ( NULL );
10674 label_loop_neg = NULL;
10675 label_negative = NULL;
10676 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10677 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10680 // additional labels needed
10681 label_loop_neg = newiTempLabel ( NULL );
10682 label_negative = newiTempLabel ( NULL );
10685 // copy source to result -- this will effectively truncate the left operand to the size of result!
10686 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10687 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10688 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10689 pic16_mov2f (AOP(result),AOP(left), offset);
10692 // if result is longer than left, fill with zeros (or sign)
10693 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10694 if (sign && AOP_SIZE(left) > 0) {
10695 // shift signed operand -- fill with sign
10696 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10697 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10698 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10699 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10700 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10703 // shift unsigned operand -- fill result with zeros
10704 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10705 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10708 } // if (size mismatch)
10710 pic16_mov2w (AOP(right), 0);
10711 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10712 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10715 // perform a shift by one (shift count is positive)
10716 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10717 // 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])
10718 pic16_emitpLabel (label_loop_pos->key);
10720 if (sign && (pos_shift == POC_RRCF)) {
10721 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10724 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10725 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10726 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10728 // perform a shift by one (shift count is positive)
10729 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10730 // 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])
10731 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10732 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10734 pic16_emitpLabel (label_loop_pos->key);
10735 if (sign && (pos_shift == POC_RRCF)) {
10736 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10739 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10740 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10741 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10742 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10746 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10748 pic16_emitpLabel (label_negative->key);
10749 // perform a shift by -1 (shift count is negative)
10750 // 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)
10752 pic16_emitpLabel (label_loop_neg->key);
10753 if (sign && (neg_shift == POC_RRCF)) {
10754 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10757 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10758 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10759 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10760 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10761 } // if (signedCount)
10763 pic16_emitpLabel (label_complete->key);
10766 pic16_freeAsmop (right,NULL,ic,TRUE);
10767 pic16_freeAsmop(left,NULL,ic,TRUE);
10768 pic16_freeAsmop(result,NULL,ic,TRUE);
10771 static void genLeftShift (iCode *ic) {
10772 genGenericShift (ic, 1);
10775 static void genRightShift (iCode *ic) {
10776 genGenericShift (ic, 0);
10781 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10782 void pic16_loadFSR0(operand *op, int lit)
10784 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10785 if (AOP_TYPE(op) == AOP_LIT) {
10786 /* handle 12 bit integers correctly */
10787 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
10788 if ((val & 0x0fff) != val) {
10789 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10790 val, (val & 0x0fff) );
10793 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10795 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10798 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10799 // set up FSR0 with address of result
10800 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10801 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10805 /*----------------------------------------------------------------*/
10806 /* pic16_derefPtr - move one byte from the location ptr points to */
10807 /* to WREG (doWrite == 0) or one byte from WREG */
10808 /* to the location ptr points to (doWrite != 0) */
10809 /*----------------------------------------------------------------*/
10810 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10812 if (!IS_PTR(operandType(ptr)))
10814 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10815 else pic16_mov2w (AOP(ptr), 0);
10819 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10820 /* We might determine pointer type right here: */
10821 p_type = DCL_TYPE(operandType(ptr));
10826 if (!fsr0_setup || !*fsr0_setup)
10828 pic16_loadFSR0( ptr, 0 );
10829 if (fsr0_setup) *fsr0_setup = 1;
10832 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10834 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10838 if (AOP(ptr)->aopu.aop_reg[2]) {
10839 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10840 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10841 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10842 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10843 pic16_mov2w(AOP(ptr), 2);
10844 pic16_callGenericPointerRW(doWrite, 1);
10846 // data pointer (just 2 byte given)
10847 if (!fsr0_setup || !*fsr0_setup)
10849 pic16_loadFSR0( ptr, 0 );
10850 if (fsr0_setup) *fsr0_setup = 1;
10853 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10855 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10860 assert (0 && "invalid pointer type specified");
10865 /*-----------------------------------------------------------------*/
10866 /* genUnpackBits - generates code for unpacking bits */
10867 /*-----------------------------------------------------------------*/
10868 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10871 sym_link *etype, *letype;
10872 int blen=0, bstr=0;
10877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10878 etype = getSpec(operandType(result));
10879 letype = getSpec(operandType(left));
10881 // if(IS_BITFIELD(etype)) {
10882 blen = SPEC_BLEN(etype);
10883 bstr = SPEC_BSTR(etype);
10886 lbstr = SPEC_BSTR( letype );
10888 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10889 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10892 if((blen == 1) && (bstr < 8)
10893 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10894 /* it is a single bit, so use the appropriate bit instructions */
10895 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10897 same = pic16_sameRegs(AOP(left),AOP(result));
10898 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10899 pic16_emitpcode(POC_CLRF, op);
10901 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10902 /* workaround to reduce the extra lfsr instruction */
10903 pic16_emitpcode(POC_BTFSC,
10904 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10906 assert (PIC_IS_DATA_PTR (operandType(left)));
10907 pic16_loadFSR0 (left, 0);
10908 pic16_emitpcode(POC_BTFSC,
10909 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10912 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10913 /* unsigned bitfields result in either 0 or 1 */
10914 pic16_emitpcode(POC_INCF, op);
10916 /* signed bitfields result in either 0 or -1 */
10917 pic16_emitpcode(POC_DECF, op);
10920 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10923 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10929 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10930 // access symbol directly
10931 pic16_mov2w (AOP(left), 0);
10933 pic16_derefPtr (left, ptype, 0, NULL);
10936 /* if we have bitdisplacement then it fits */
10937 /* into this byte completely or if length is */
10938 /* less than a byte */
10939 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10941 /* shift right acc */
10944 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10945 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10947 /* VR -- normally I would use the following, but since we use the hack,
10948 * to avoid the masking from AccRsh, why not mask it right now? */
10951 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10954 /* extend signed bitfields to 8 bits */
10955 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10957 assert (blen + bstr > 0);
10958 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10959 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10964 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10968 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10969 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10970 exit(EXIT_FAILURE);
10976 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10978 int size, offset = 0, leoffset=0 ;
10980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10981 pic16_aopOp(result, ic, TRUE);
10985 size = AOP_SIZE(result);
10986 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10990 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10991 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10992 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10997 if(AOP(left)->aopu.pcop->type == PO_DIR)
10998 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11000 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11003 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11005 // pic16_DumpOp("(result)",result);
11006 if(is_LitAOp(AOP(result))) {
11007 pic16_mov2w(AOP(left), offset); // patch 8
11008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11010 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11011 pic16_popGet(AOP(left), offset), //patch 8
11012 pic16_popGet(AOP(result), offset)));
11020 pic16_freeAsmop(result,NULL,ic,TRUE);
11025 /*-----------------------------------------------------------------*/
11026 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11027 /*-----------------------------------------------------------------*/
11028 static void genNearPointerGet (operand *left,
11032 // asmop *aop = NULL;
11033 //regs *preg = NULL ;
11034 sym_link *rtype, *retype;
11035 sym_link *ltype, *letype;
11039 rtype = operandType(result);
11040 retype= getSpec(rtype);
11041 ltype = operandType(left);
11042 letype= getSpec(ltype);
11044 pic16_aopOp(left,ic,FALSE);
11046 // pic16_DumpOp("(left)",left);
11047 // pic16_DumpOp("(result)",result);
11049 /* if left is rematerialisable and
11050 * result is not bit variable type and
11051 * the left is pointer to data space i.e
11052 * lower 128 bytes of space */
11054 if (AOP_TYPE(left) == AOP_PCODE
11055 && !IS_BITFIELD(retype)
11056 && DCL_TYPE(ltype) == POINTER) {
11058 genDataPointerGet (left,result,ic);
11059 pic16_freeAsmop(left, NULL, ic, TRUE);
11063 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11064 pic16_aopOp (result,ic,TRUE);
11066 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11069 if(IS_BITFIELD( retype )
11070 && (SPEC_BLEN(operandType(result))==1)
11074 int bitstrt, bytestrt;
11076 /* if this is bitfield of size 1, see if we are checking the value
11077 * of a single bit in an if-statement,
11078 * if yes, then don't generate usual code, but execute the
11079 * genIfx directly -- VR */
11083 /* CHECK: if next iCode is IFX
11084 * and current result operand is nextic's conditional operand
11085 * and current result operand live ranges ends at nextic's key number
11087 if((nextic->op == IFX)
11088 && (result == IC_COND(nextic))
11089 && (OP_LIVETO(result) == nextic->seq)
11090 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11092 /* everything is ok then */
11093 /* find a way to optimize the genIfx iCode */
11095 bytestrt = SPEC_BSTR(operandType(result))/8;
11096 bitstrt = SPEC_BSTR(operandType(result))%8;
11098 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11100 genIfxpCOpJump(nextic, jop);
11102 pic16_freeAsmop(left, NULL, ic, TRUE);
11103 pic16_freeAsmop(result, NULL, ic, TRUE);
11109 /* if bitfield then unpack the bits */
11110 if (IS_BITFIELD(letype))
11111 genUnpackBits (result, left, NULL, POINTER);
11113 /* we have can just get the values */
11114 int size = AOP_SIZE(result);
11117 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11119 pic16_loadFSR0( left, 0 );
11123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11124 pic16_popGet(AOP(result), offset++)));
11126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11127 pic16_popGet(AOP(result), offset++)));
11133 /* now some housekeeping stuff */
11135 /* we had to allocate for this iCode */
11136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11137 pic16_freeAsmop(NULL,aop,ic,TRUE);
11139 /* we did not allocate which means left
11140 * already in a pointer register, then
11141 * if size > 0 && this could be used again
11142 * we have to point it back to where it
11144 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11145 if (AOP_SIZE(result) > 1
11146 && !OP_SYMBOL(left)->remat
11147 && ( OP_SYMBOL(left)->liveTo > ic->seq
11149 // int size = AOP_SIZE(result) - 1;
11151 // pic16_emitcode("dec","%s",rname);
11157 pic16_freeAsmop(left,NULL,ic,TRUE);
11158 pic16_freeAsmop(result,NULL,ic,TRUE);
11161 /*-----------------------------------------------------------------*/
11162 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11163 /*-----------------------------------------------------------------*/
11164 static void genPagedPointerGet (operand *left,
11169 regs *preg = NULL ;
11171 sym_link *rtype, *retype;
11173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11175 rtype = operandType(result);
11176 retype= getSpec(rtype);
11178 pic16_aopOp(left,ic,FALSE);
11180 /* if the value is already in a pointer register
11181 then don't need anything more */
11182 if (!AOP_INPREG(AOP(left))) {
11183 /* otherwise get a free pointer register */
11185 preg = getFreePtr(ic,&aop,FALSE);
11186 pic16_emitcode("mov","%s,%s",
11188 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11189 rname = preg->name ;
11191 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11193 pic16_freeAsmop(left,NULL,ic,TRUE);
11194 pic16_aopOp (result,ic,TRUE);
11196 /* if bitfield then unpack the bits */
11197 if (IS_BITFIELD(retype))
11198 genUnpackBits (result,left,rname,PPOINTER);
11200 /* we have can just get the values */
11201 int size = AOP_SIZE(result);
11206 pic16_emitcode("movx","a,@%s",rname);
11207 pic16_aopPut(AOP(result),"a",offset);
11212 pic16_emitcode("inc","%s",rname);
11216 /* now some housekeeping stuff */
11218 /* we had to allocate for this iCode */
11219 pic16_freeAsmop(NULL,aop,ic,TRUE);
11221 /* we did not allocate which means left
11222 already in a pointer register, then
11223 if size > 0 && this could be used again
11224 we have to point it back to where it
11226 if (AOP_SIZE(result) > 1 &&
11227 !OP_SYMBOL(left)->remat &&
11228 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11230 int size = AOP_SIZE(result) - 1;
11232 pic16_emitcode("dec","%s",rname);
11237 pic16_freeAsmop(result,NULL,ic,TRUE);
11243 /* This code is not adjusted to PIC16 and fails utterly.
11244 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11246 /*-----------------------------------------------------------------*/
11247 /* genFarPointerGet - gget value from far space */
11248 /*-----------------------------------------------------------------*/
11249 static void genFarPointerGet (operand *left,
11250 operand *result, iCode *ic)
11253 sym_link *retype = getSpec(operandType(result));
11255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11257 pic16_aopOp(left,ic,FALSE);
11259 /* if the operand is already in dptr
11260 then we do nothing else we move the value to dptr */
11261 if (AOP_TYPE(left) != AOP_STR) {
11262 /* if this is remateriazable */
11263 if (AOP_TYPE(left) == AOP_IMMD)
11264 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11265 else { /* we need to get it byte by byte */
11266 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11267 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11268 if (options.model == MODEL_FLAT24)
11270 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11274 /* so dptr know contains the address */
11275 pic16_freeAsmop(left,NULL,ic,TRUE);
11276 pic16_aopOp(result,ic,TRUE);
11278 /* if bit then unpack */
11279 if (IS_BITFIELD(retype))
11280 genUnpackBits(result,left,"dptr",FPOINTER);
11282 size = AOP_SIZE(result);
11286 pic16_emitcode("movx","a,@dptr");
11287 pic16_aopPut(AOP(result),"a",offset++);
11289 pic16_emitcode("inc","dptr");
11293 pic16_freeAsmop(result,NULL,ic,TRUE);
11298 /*-----------------------------------------------------------------*/
11299 /* genCodePointerGet - get value from code space */
11300 /*-----------------------------------------------------------------*/
11301 static void genCodePointerGet (operand *left,
11302 operand *result, iCode *ic)
11305 sym_link *retype = getSpec(operandType(result));
11307 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11309 pic16_aopOp(left,ic,FALSE);
11311 /* if the operand is already in dptr
11312 then we do nothing else we move the value to dptr */
11313 if (AOP_TYPE(left) != AOP_STR) {
11314 /* if this is remateriazable */
11315 if (AOP_TYPE(left) == AOP_IMMD)
11316 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11317 else { /* we need to get it byte by byte */
11318 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11319 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11320 if (options.model == MODEL_FLAT24)
11322 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11326 /* so dptr know contains the address */
11327 pic16_freeAsmop(left,NULL,ic,TRUE);
11328 pic16_aopOp(result,ic,FALSE);
11330 /* if bit then unpack */
11331 if (IS_BITFIELD(retype))
11332 genUnpackBits(result,left,"dptr",CPOINTER);
11334 size = AOP_SIZE(result);
11338 pic16_emitcode("clr","a");
11339 pic16_emitcode("movc","a,@a+dptr");
11340 pic16_aopPut(AOP(result),"a",offset++);
11342 pic16_emitcode("inc","dptr");
11346 pic16_freeAsmop(result,NULL,ic,TRUE);
11351 /*-----------------------------------------------------------------*/
11352 /* genGenPointerGet - gget value from generic pointer space */
11353 /*-----------------------------------------------------------------*/
11354 static void genGenPointerGet (operand *left,
11355 operand *result, iCode *ic)
11357 int size, offset, lit;
11358 sym_link *retype = getSpec(operandType(result));
11360 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11361 pic16_aopOp(left,ic,FALSE);
11362 pic16_aopOp(result,ic,FALSE);
11363 size = AOP_SIZE(result);
11365 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11367 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11369 lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11370 // load FSR0 from immediate
11371 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11373 // pic16_loadFSR0( left );
11378 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11380 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11387 else { /* we need to get it byte by byte */
11388 // set up FSR0 with address from left
11389 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11390 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11396 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11398 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11405 /* if bit then unpack */
11406 if (IS_BITFIELD(retype))
11407 genUnpackBits(result,left,"BAD",GPOINTER);
11410 pic16_freeAsmop(left,NULL,ic,TRUE);
11411 pic16_freeAsmop(result,NULL,ic,TRUE);
11417 /*-----------------------------------------------------------------*/
11418 /* genGenPointerGet - gget value from generic pointer space */
11419 /*-----------------------------------------------------------------*/
11420 static void genGenPointerGet (operand *left,
11421 operand *result, iCode *ic)
11423 int size, offset, lit;
11424 sym_link *letype = getSpec(operandType(left));
11426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11427 pic16_aopOp(left,ic,FALSE);
11428 pic16_aopOp(result,ic,TRUE);
11429 size = AOP_SIZE(result);
11431 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11433 /* if bit then unpack */
11434 if (IS_BITFIELD(letype)) {
11435 genUnpackBits(result,left,"BAD",GPOINTER);
11439 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11441 lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11442 // load FSR0 from immediate
11443 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11445 werror(W_POSSBUG2, __FILE__, __LINE__);
11450 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11452 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11459 } else { /* we need to get it byte by byte */
11461 /* set up WREG:PRODL:FSR0L with address from left */
11462 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11463 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11464 pic16_mov2w(AOP(left), 2);
11465 pic16_callGenericPointerRW(0, size);
11467 assignResultValue(result, size, 1);
11473 pic16_freeAsmop(left,NULL,ic,TRUE);
11474 pic16_freeAsmop(result,NULL,ic,TRUE);
11477 /*-----------------------------------------------------------------*/
11478 /* genConstPointerGet - get value from const generic pointer space */
11479 /*-----------------------------------------------------------------*/
11480 static void genConstPointerGet (operand *left,
11481 operand *result, iCode *ic)
11483 //sym_link *retype = getSpec(operandType(result));
11484 // symbol *albl = newiTempLabel(NULL); // patch 15
11485 // symbol *blbl = newiTempLabel(NULL); //
11486 // PIC_OPCODE poc; // patch 15
11490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11491 pic16_aopOp(left,ic,FALSE);
11492 pic16_aopOp(result,ic,TRUE);
11493 size = AOP_SIZE(result);
11495 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11497 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11499 // set up table pointer
11500 if( (AOP_TYPE(left) == AOP_PCODE)
11501 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11502 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11504 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11505 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11506 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11507 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11508 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11509 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11511 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11512 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11513 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11517 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11518 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11522 pic16_freeAsmop(left,NULL,ic,TRUE);
11523 pic16_freeAsmop(result,NULL,ic,TRUE);
11527 /*-----------------------------------------------------------------*/
11528 /* genPointerGet - generate code for pointer get */
11529 /*-----------------------------------------------------------------*/
11530 static void genPointerGet (iCode *ic)
11532 operand *left, *result ;
11533 sym_link *type, *etype;
11538 left = IC_LEFT(ic);
11539 result = IC_RESULT(ic) ;
11541 /* depending on the type of pointer we need to
11542 move it to the correct pointer register */
11543 type = operandType(left);
11544 etype = getSpec(type);
11547 if (IS_PTR_CONST(type))
11549 if (IS_CODEPTR(type))
11551 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11553 /* if left is of type of pointer then it is simple */
11554 if (IS_PTR(type) && !IS_FUNC(type->next))
11555 p_type = DCL_TYPE(type);
11557 /* we have to go by the storage class */
11558 p_type = PTR_TYPE(SPEC_OCLS(etype));
11560 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11562 if (SPEC_OCLS(etype)->codesp ) {
11563 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11564 //p_type = CPOINTER ;
11566 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11567 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11568 /*p_type = FPOINTER ;*/
11570 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11571 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11572 /* p_type = PPOINTER; */
11574 if (SPEC_OCLS(etype) == idata ) {
11575 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11576 /* p_type = IPOINTER; */
11578 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11579 /* p_type = POINTER ; */
11583 /* now that we have the pointer type we assign
11584 the pointer values */
11589 genNearPointerGet (left,result,ic);
11593 genPagedPointerGet(left,result,ic);
11597 /* PICs do not support FAR pointers... */
11598 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11600 genFarPointerGet (left,result,ic);
11605 genConstPointerGet (left,result,ic);
11606 //pic16_emitcodePointerGet (left,result,ic);
11611 if (IS_PTR_CONST(type))
11612 genConstPointerGet (left,result,ic);
11615 genGenPointerGet (left,result,ic);
11619 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11620 "genPointerGet: illegal pointer type");
11625 /*-----------------------------------------------------------------*/
11626 /* genPackBits - generates code for packed bit storage */
11627 /*-----------------------------------------------------------------*/
11628 static void genPackBits (sym_link *etype , operand *result,
11630 char *rname, int p_type)
11636 int shifted_and_masked = 0;
11637 unsigned long lit = (unsigned long)-1;
11640 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11641 blen = SPEC_BLEN(etype);
11642 bstr = SPEC_BSTR(etype);
11644 retype = getSpec(operandType(right));
11646 if(AOP_TYPE(right) == AOP_LIT) {
11647 lit = ulFromVal (AOP(right)->aopu.aop_lit);
11649 if((blen == 1) && (bstr < 8)) {
11650 /* it is a single bit, so use the appropriate bit instructions */
11652 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11654 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11655 /* workaround to reduce the extra lfsr instruction */
11657 pic16_emitpcode(POC_BSF,
11658 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11660 pic16_emitpcode(POC_BCF,
11661 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11664 if (PIC_IS_DATA_PTR(operandType(result))) {
11665 pic16_loadFSR0(result, 0);
11666 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11667 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11669 /* get old value */
11670 pic16_derefPtr (result, p_type, 0, NULL);
11671 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11672 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11673 /* write back new value */
11674 pic16_derefPtr (result, p_type, 1, NULL);
11680 /* IORLW below is more efficient */
11681 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11682 lit = (lit & ((1UL << blen) - 1)) << bstr;
11683 shifted_and_masked = 1;
11686 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11687 && IS_BITFIELD(retype)
11688 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11692 rblen = SPEC_BLEN( retype );
11693 rbstr = SPEC_BSTR( retype );
11695 if(IS_BITFIELD(etype)) {
11696 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11697 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11699 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11702 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11704 if(IS_BITFIELD(etype)) {
11705 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11707 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11710 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11714 /* move right to W */
11715 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11718 /* if the bit length is less than or */
11719 /* it exactly fits a byte then */
11720 if((shCnt=SPEC_BSTR(etype))
11721 || SPEC_BLEN(etype) <= 8 ) {
11722 int fsr0_setup = 0;
11724 if (blen != 8 || (bstr % 8) != 0) {
11725 // we need to combine the value with the old value
11726 if(!shifted_and_masked)
11728 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11730 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11731 SPEC_BSTR(etype), SPEC_BLEN(etype));
11733 /* shift left acc, do NOT mask the result again */
11736 /* using PRODH as a temporary register here */
11737 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11740 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11741 || IS_DIRECT(result)) {
11742 /* access symbol directly */
11743 pic16_mov2w (AOP(result), 0);
11745 /* get old value */
11746 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11749 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11750 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11751 (unsigned char)(0xff >> (8-bstr))) ));
11752 if (!shifted_and_masked) {
11753 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11755 /* We have the shifted and masked (literal) right value in `lit' */
11757 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11759 } else { // if (blen == 8 && (bstr % 8) == 0)
11760 if (shifted_and_masked) {
11761 // move right (literal) to WREG (only case where right is not yet in WREG)
11762 pic16_mov2w(AOP(right), (bstr / 8));
11766 /* write new value back */
11767 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11768 || IS_DIRECT(result)) {
11769 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11771 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11780 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11781 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11782 exit(EXIT_FAILURE);
11786 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11787 rLen = SPEC_BLEN(etype)-8;
11789 /* now generate for lengths greater than one byte */
11793 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11799 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11805 pic16_emitcode("movx","@dptr,a");
11810 DEBUGpic16_emitcode(";lcall","__gptrput");
11818 pic16_mov2w(AOP(right), offset++);
11821 /* last last was not complete */
11823 /* save the byte & read byte */
11826 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11827 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11832 pic16_emitcode ("mov","b,a");
11833 pic16_emitcode("movx","a,@dptr");
11837 pic16_emitcode ("push","b");
11838 pic16_emitcode ("push","acc");
11839 pic16_emitcode ("lcall","__gptrget");
11840 pic16_emitcode ("pop","b");
11846 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11847 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11848 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11849 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11850 // pic16_emitcode ("orl","a,b");
11853 // if (p_type == GPOINTER)
11854 // pic16_emitcode("pop","b");
11859 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11860 // pic16_emitcode("mov","@%s,a",rname);
11864 pic16_emitcode("movx","@dptr,a");
11868 DEBUGpic16_emitcode(";lcall","__gptrput");
11875 // pic16_freeAsmop(right, NULL, ic, TRUE);
11878 /*-----------------------------------------------------------------*/
11879 /* genDataPointerSet - remat pointer to data space */
11880 /*-----------------------------------------------------------------*/
11881 static void genDataPointerSet(operand *right,
11885 int size, offset = 0, resoffset=0 ;
11887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11888 pic16_aopOp(right,ic,FALSE);
11890 size = AOP_SIZE(right);
11892 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11895 if ( AOP_TYPE(result) == AOP_PCODE) {
11896 fprintf(stderr,"genDataPointerSet %s, %d\n",
11897 AOP(result)->aopu.pcop->name,
11898 (AOP(result)->aopu.pcop->type == PO_DIR)?
11899 PCOR(AOP(result)->aopu.pcop)->instance:
11900 PCOI(AOP(result)->aopu.pcop)->offset);
11904 if(AOP(result)->aopu.pcop->type == PO_DIR)
11905 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11908 if (AOP_TYPE(right) == AOP_LIT) {
11909 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11910 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11912 pic16_mov2w(AOP(right), offset);
11913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11919 pic16_freeAsmop(right,NULL,ic,TRUE);
11924 /*-----------------------------------------------------------------*/
11925 /* genNearPointerSet - pic16_emitcode for near pointer put */
11926 /*-----------------------------------------------------------------*/
11927 static void genNearPointerSet (operand *right,
11933 sym_link *ptype = operandType(result);
11934 sym_link *resetype;
11936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11937 retype= getSpec(operandType(right));
11938 resetype = getSpec(operandType(result));
11940 pic16_aopOp(result,ic,FALSE);
11942 /* if the result is rematerializable &
11943 * in data space & not a bit variable */
11945 /* and result is not a bit variable */
11946 if (AOP_TYPE(result) == AOP_PCODE
11947 // && AOP_TYPE(result) == AOP_IMMD
11948 && DCL_TYPE(ptype) == POINTER
11949 && !IS_BITFIELD(retype)
11950 && !IS_BITFIELD(resetype)) {
11952 genDataPointerSet (right,result,ic);
11953 pic16_freeAsmop(result,NULL,ic,TRUE);
11957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11958 pic16_aopOp(right,ic,FALSE);
11959 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11961 /* if bitfield then unpack the bits */
11962 if (IS_BITFIELD(resetype)) {
11963 genPackBits (resetype, result, right, NULL, POINTER);
11965 /* we have can just get the values */
11966 int size = AOP_SIZE(right);
11969 pic16_loadFSR0(result, 0);
11971 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11973 if (is_LitOp(right)) {
11974 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11976 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11978 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11980 } else { // no literal
11982 pic16_emitpcode(POC_MOVFF,
11983 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11984 pic16_popCopyReg(&pic16_pc_postinc0)));
11986 pic16_emitpcode(POC_MOVFF,
11987 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11988 pic16_popCopyReg(&pic16_pc_indf0)));
11996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11997 /* now some housekeeping stuff */
11999 /* we had to allocate for this iCode */
12000 pic16_freeAsmop(NULL,aop,ic,TRUE);
12002 /* we did not allocate which means left
12003 * already in a pointer register, then
12004 * if size > 0 && this could be used again
12005 * we have to point it back to where it
12007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12008 if (AOP_SIZE(right) > 1
12009 && !OP_SYMBOL(result)->remat
12010 && ( OP_SYMBOL(result)->liveTo > ic->seq
12013 int size = AOP_SIZE(right) - 1;
12016 pic16_emitcode("decf","fsr0,f");
12017 //pic16_emitcode("dec","%s",rname);
12021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12024 pic16_freeAsmop(right,NULL,ic,TRUE);
12025 pic16_freeAsmop(result,NULL,ic,TRUE);
12028 /*-----------------------------------------------------------------*/
12029 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12030 /*-----------------------------------------------------------------*/
12031 static void genPagedPointerSet (operand *right,
12036 regs *preg = NULL ;
12040 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12042 retype= getSpec(operandType(right));
12044 pic16_aopOp(result,ic,FALSE);
12046 /* if the value is already in a pointer register
12047 then don't need anything more */
12048 if (!AOP_INPREG(AOP(result))) {
12049 /* otherwise get a free pointer register */
12051 preg = getFreePtr(ic,&aop,FALSE);
12052 pic16_emitcode("mov","%s,%s",
12054 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12055 rname = preg->name ;
12057 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12059 pic16_freeAsmop(result,NULL,ic,TRUE);
12060 pic16_aopOp (right,ic,FALSE);
12062 /* if bitfield then unpack the bits */
12063 if (IS_BITFIELD(retype))
12064 genPackBits (retype,result,right,rname,PPOINTER);
12066 /* we have can just get the values */
12067 int size = AOP_SIZE(right);
12071 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12074 pic16_emitcode("movx","@%s,a",rname);
12077 pic16_emitcode("inc","%s",rname);
12083 /* now some housekeeping stuff */
12085 /* we had to allocate for this iCode */
12086 pic16_freeAsmop(NULL,aop,ic,TRUE);
12088 /* we did not allocate which means left
12089 already in a pointer register, then
12090 if size > 0 && this could be used again
12091 we have to point it back to where it
12093 if (AOP_SIZE(right) > 1 &&
12094 !OP_SYMBOL(result)->remat &&
12095 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12097 int size = AOP_SIZE(right) - 1;
12099 pic16_emitcode("dec","%s",rname);
12104 pic16_freeAsmop(right,NULL,ic,TRUE);
12110 /* This code is not adjusted to PIC16 and fails utterly...
12111 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12113 /*-----------------------------------------------------------------*/
12114 /* genFarPointerSet - set value from far space */
12115 /*-----------------------------------------------------------------*/
12116 static void genFarPointerSet (operand *right,
12117 operand *result, iCode *ic)
12120 sym_link *retype = getSpec(operandType(right));
12122 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12123 pic16_aopOp(result,ic,FALSE);
12125 /* if the operand is already in dptr
12126 then we do nothing else we move the value to dptr */
12127 if (AOP_TYPE(result) != AOP_STR) {
12128 /* if this is remateriazable */
12129 if (AOP_TYPE(result) == AOP_IMMD)
12130 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12131 else { /* we need to get it byte by byte */
12132 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12133 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12134 if (options.model == MODEL_FLAT24)
12136 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12140 /* so dptr know contains the address */
12141 pic16_freeAsmop(result,NULL,ic,TRUE);
12142 pic16_aopOp(right,ic,FALSE);
12144 /* if bit then unpack */
12145 if (IS_BITFIELD(retype))
12146 genPackBits(retype,result,right,"dptr",FPOINTER);
12148 size = AOP_SIZE(right);
12152 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12154 pic16_emitcode("movx","@dptr,a");
12156 pic16_emitcode("inc","dptr");
12160 pic16_freeAsmop(right,NULL,ic,TRUE);
12164 /*-----------------------------------------------------------------*/
12165 /* genGenPointerSet - set value from generic pointer space */
12166 /*-----------------------------------------------------------------*/
12168 static void genGenPointerSet (operand *right,
12169 operand *result, iCode *ic)
12171 int i, size, offset, lit;
12172 sym_link *retype = getSpec(operandType(right));
12174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12176 pic16_aopOp(result,ic,FALSE);
12177 pic16_aopOp(right,ic,FALSE);
12178 size = AOP_SIZE(right);
12181 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12183 /* if the operand is already in dptr
12184 then we do nothing else we move the value to dptr */
12185 if (AOP_TYPE(result) != AOP_STR) {
12186 /* if this is remateriazable */
12187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12188 // WARNING: anythig until "else" is untested!
12189 if (AOP_TYPE(result) == AOP_IMMD) {
12190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12191 lit = (unsigned) ulFromVal (AOP(result)->aopu.aop_lit);
12192 // load FSR0 from immediate
12193 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12197 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12199 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12205 else { /* we need to get it byte by byte */
12206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12207 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12209 // set up FSR0 with address of result
12210 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12211 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12213 /* hack hack! see if this the FSR. If so don't load W */
12214 if(AOP_TYPE(right) != AOP_ACC) {
12216 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12218 if(AOP_TYPE(right) == AOP_LIT)
12221 // note: pic16_popGet handles sign extension
12222 for(i=0;i<size;i++) {
12223 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12225 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12227 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12232 for(i=0;i<size;i++) {
12234 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12235 pic16_popCopyReg(&pic16_pc_postinc0)));
12237 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12238 pic16_popCopyReg(&pic16_pc_indf0)));
12244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12245 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12247 } // if (AOP_TYPE(result) != AOP_IMMD)
12249 } // if (AOP_TYPE(result) != AOP_STR)
12250 /* so dptr know contains the address */
12253 /* if bit then unpack */
12254 if (IS_BITFIELD(retype))
12255 genPackBits(retype,result,right,"dptr",GPOINTER);
12257 size = AOP_SIZE(right);
12260 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12262 // set up FSR0 with address of result
12263 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12267 if (AOP_TYPE(right) == AOP_LIT) {
12268 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12270 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12272 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12274 } else { // no literal
12276 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12278 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12286 pic16_freeAsmop(right,NULL,ic,TRUE);
12287 pic16_freeAsmop(result,NULL,ic,TRUE);
12291 static void genGenPointerSet (operand *right,
12292 operand *result, iCode *ic)
12295 sym_link *retype = getSpec(operandType(result));
12297 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12299 pic16_aopOp(result,ic,FALSE);
12300 pic16_aopOp(right,ic,FALSE);
12301 size = AOP_SIZE(right);
12303 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12306 /* if bit then unpack */
12307 if (IS_BITFIELD(retype)) {
12308 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12309 genPackBits(retype,result,right,"dptr",GPOINTER);
12313 size = AOP_SIZE(right);
12315 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12318 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12320 /* value of right+0 is placed on stack, which will be retrieved
12321 * by the support function thus restoring the stack. The important
12322 * thing is that there is no need to manually restore stack pointer
12324 pushaop(AOP(right), 0);
12325 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12326 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12327 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12328 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12330 /* load address to write to in WREG:FSR0H:FSR0L */
12331 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12332 pic16_popCopyReg(&pic16_pc_fsr0l)));
12333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12334 pic16_popCopyReg(&pic16_pc_prodl)));
12335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12337 pic16_callGenericPointerRW(1, size);
12340 pic16_freeAsmop(right,NULL,ic,TRUE);
12341 pic16_freeAsmop(result,NULL,ic,TRUE);
12344 /*-----------------------------------------------------------------*/
12345 /* genPointerSet - stores the value into a pointer location */
12346 /*-----------------------------------------------------------------*/
12347 static void genPointerSet (iCode *ic)
12349 operand *right, *result ;
12350 sym_link *type, *etype;
12355 right = IC_RIGHT(ic);
12356 result = IC_RESULT(ic) ;
12358 /* depending on the type of pointer we need to
12359 move it to the correct pointer register */
12360 type = operandType(result);
12361 etype = getSpec(type);
12363 /* if left is of type of pointer then it is simple */
12364 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12365 p_type = DCL_TYPE(type);
12368 /* we have to go by the storage class */
12369 p_type = PTR_TYPE(SPEC_OCLS(etype));
12371 /* if (SPEC_OCLS(etype)->codesp ) { */
12372 /* p_type = CPOINTER ; */
12375 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12376 /* p_type = FPOINTER ; */
12378 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12379 /* p_type = PPOINTER ; */
12381 /* if (SPEC_OCLS(etype) == idata ) */
12382 /* p_type = IPOINTER ; */
12384 /* p_type = POINTER ; */
12387 /* now that we have the pointer type we assign
12388 the pointer values */
12393 genNearPointerSet (right,result,ic);
12397 genPagedPointerSet (right,result,ic);
12401 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12403 genFarPointerSet (right,result,ic);
12408 genGenPointerSet (right,result,ic);
12412 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12413 "genPointerSet: illegal pointer type");
12417 /*-----------------------------------------------------------------*/
12418 /* genIfx - generate code for Ifx statement */
12419 /*-----------------------------------------------------------------*/
12420 static void genIfx (iCode *ic, iCode *popIc)
12422 operand *cond = IC_COND(ic);
12427 pic16_aopOp(cond,ic,FALSE);
12429 /* get the value into acc */
12430 if (AOP_TYPE(cond) != AOP_CRY)
12431 pic16_toBoolean(cond);
12434 /* the result is now in the accumulator */
12435 pic16_freeAsmop(cond,NULL,ic,TRUE);
12437 /* if there was something to be popped then do it */
12441 /* if the condition is a bit variable */
12442 if (isbit && IS_ITEMP(cond) &&
12444 genIfxJump(ic,"c");
12445 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12447 if (isbit && !IS_ITEMP(cond))
12448 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12450 genIfxJump(ic,"a");
12455 /*-----------------------------------------------------------------*/
12456 /* genAddrOf - generates code for address of */
12457 /*-----------------------------------------------------------------*/
12458 static void genAddrOf (iCode *ic)
12460 operand *result, *left;
12462 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12463 pCodeOp *pcop0, *pcop1, *pcop2;
12467 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12469 sym = OP_SYMBOL( IC_LEFT(ic) );
12472 /* get address of symbol on stack */
12473 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12475 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12476 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12479 // operands on stack are accessible via "FSR2 + index" with index
12480 // starting at 2 for arguments and growing from 0 downwards for
12481 // local variables (index == 0 is not assigned so we add one here)
12483 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12486 assert (soffs < 0);
12490 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12491 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12492 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12493 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12494 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12495 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12496 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12502 // if(pic16_debug_verbose) {
12503 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12504 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12507 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12508 size = AOP_SIZE(IC_RESULT(ic));
12510 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12511 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12515 pic16_emitpcode(POC_MOVLW, pcop0);
12516 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12517 pic16_emitpcode(POC_MOVLW, pcop1);
12518 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12519 pic16_emitpcode(POC_MOVLW, pcop2);
12520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12523 pic16_emitpcode(POC_MOVLW, pcop0);
12524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12525 pic16_emitpcode(POC_MOVLW, pcop1);
12526 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12528 pic16_emitpcode(POC_MOVLW, pcop0);
12529 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12532 pic16_freeAsmop(left, NULL, ic, FALSE);
12534 pic16_freeAsmop(result,NULL,ic,TRUE);
12539 /*-----------------------------------------------------------------*/
12540 /* genFarFarAssign - assignment when both are in far space */
12541 /*-----------------------------------------------------------------*/
12542 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12544 int size = AOP_SIZE(right);
12547 /* first push the right side on to the stack */
12549 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12551 pic16_emitcode ("push","acc");
12554 pic16_freeAsmop(right,NULL,ic,FALSE);
12555 /* now assign DPTR to result */
12556 pic16_aopOp(result,ic,FALSE);
12557 size = AOP_SIZE(result);
12559 pic16_emitcode ("pop","acc");
12560 pic16_aopPut(AOP(result),"a",--offset);
12562 pic16_freeAsmop(result,NULL,ic,FALSE);
12567 /*-----------------------------------------------------------------*/
12568 /* genAssign - generate code for assignment */
12569 /*-----------------------------------------------------------------*/
12570 static void genAssign (iCode *ic)
12572 operand *result, *right;
12573 sym_link *restype, *rtype;
12574 int size, offset,know_W;
12575 unsigned long lit = 0L;
12577 result = IC_RESULT(ic);
12578 right = IC_RIGHT(ic) ;
12582 /* if they are the same */
12583 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12586 /* reversed order operands are aopOp'ed so that result operand
12587 * is effective in case right is a stack symbol. This maneauver
12588 * allows to use the _G.resDirect flag later */
12589 pic16_aopOp(result,ic,TRUE);
12590 pic16_aopOp(right,ic,FALSE);
12592 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12594 /* if they are the same registers */
12595 if (pic16_sameRegs(AOP(right),AOP(result)))
12598 /* if the result is a bit */
12599 if (AOP_TYPE(result) == AOP_CRY) {
12600 /* if the right size is a literal then
12601 we know what the value is */
12602 if (AOP_TYPE(right) == AOP_LIT) {
12604 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12605 pic16_popGet(AOP(result),0));
12607 if (((int) operandLitValue(right)))
12608 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12609 AOP(result)->aopu.aop_dir,
12610 AOP(result)->aopu.aop_dir);
12612 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12613 AOP(result)->aopu.aop_dir,
12614 AOP(result)->aopu.aop_dir);
12619 /* the right is also a bit variable */
12620 if (AOP_TYPE(right) == AOP_CRY) {
12621 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12622 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12623 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12628 /* we need to or */
12629 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12630 pic16_toBoolean(right);
12632 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12633 //pic16_aopPut(AOP(result),"a",0);
12637 /* bit variables done */
12639 size = AOP_SIZE(result);
12642 /* bit variables done */
12644 size = AOP_SIZE(result);
12645 restype = operandType(result);
12646 rtype = operandType(right);
12649 if(AOP_TYPE(right) == AOP_LIT) {
12650 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12652 lit = ulFromVal (AOP(right)->aopu.aop_lit);
12654 /* patch tag for literals that are cast to pointers */
12655 if (IS_CODEPTR(restype)) {
12656 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12657 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12659 if (IS_GENPTR(restype))
12661 if (IS_CODEPTR(rtype)) {
12662 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12663 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12664 } else if (PIC_IS_DATA_PTR(rtype)) {
12665 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12666 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12667 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12668 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12669 } else if (IS_PTR(rtype)) {
12670 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12671 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12677 unsigned long lit_int;
12682 if(IS_FIXED16X16(operandType(right))) {
12683 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12685 /* take care if literal is a float */
12686 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12687 lit = info.lit_int;
12692 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12693 // sizeof(unsigned long int), sizeof(float));
12696 if (AOP_TYPE(right) == AOP_REG) {
12697 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12699 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12704 /* when do we have to read the program memory?
12705 * - if right itself is a symbol in code space
12706 * (we don't care what it points to if it's a pointer)
12707 * - AND right is not a function (we would want its address)
12709 if(AOP_TYPE(right) != AOP_LIT
12710 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12711 && !IS_FUNC(OP_SYM_TYPE(right))
12712 && !IS_ITEMP(right)) {
12714 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12715 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12717 // set up table pointer
12718 if(is_LitOp(right)) {
12719 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12720 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12721 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12722 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12723 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12724 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12725 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12727 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12728 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12729 pic16_popCopyReg(&pic16_pc_tblptrl)));
12730 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12731 pic16_popCopyReg(&pic16_pc_tblptrh)));
12732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12733 pic16_popCopyReg(&pic16_pc_tblptru)));
12736 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12737 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12739 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12740 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12741 pic16_popGet(AOP(result),offset)));
12745 /* FIXME: for pointers we need to extend differently (according
12746 * to pointer type DATA/CODE/EEPROM/... :*/
12747 size = getSize(OP_SYM_TYPE(right));
12748 if(AOP_SIZE(result) > size) {
12749 size = AOP_SIZE(result) - size;
12751 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12759 /* VR - What is this?! */
12760 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12763 if(aopIdx(AOP(result),0) == 4) {
12764 /* this is a workaround to save value of right into wreg too,
12765 * value of wreg is going to be used later */
12766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12772 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12776 size = AOP_SIZE(right);
12777 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12780 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12781 if(AOP_TYPE(right) == AOP_LIT) {
12783 if(know_W != (lit&0xff))
12784 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12788 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12792 } else if (AOP_TYPE(right) == AOP_CRY) {
12793 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12795 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12796 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12797 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12799 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12800 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12801 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12805 if(!_G.resDirect) { /* use this aopForSym feature */
12806 if(AOP_TYPE(result) == AOP_ACC) {
12807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12809 if(AOP_TYPE(right) == AOP_ACC) {
12810 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12812 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12819 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12822 pic16_freeAsmop (right,NULL,ic,FALSE);
12823 pic16_freeAsmop (result,NULL,ic,TRUE);
12826 /*-----------------------------------------------------------------*/
12827 /* genJumpTab - generates code for jump table */
12828 /*-----------------------------------------------------------------*/
12829 static void genJumpTab (iCode *ic)
12834 pCodeOp *jt_offs_hi;
12839 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12840 /* get the condition into accumulator */
12841 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12843 /* multiply by three */
12844 pic16_emitcode("add","a,acc");
12845 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12847 jtab = newiTempLabel(NULL);
12848 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12849 pic16_emitcode("jmp","@a+dptr");
12850 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12853 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12854 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12856 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12857 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12858 pic16_emitpLabel(jtab->key);
12862 jt_offs = pic16_popGetTempReg(0);
12863 jt_offs_hi = pic16_popGetTempReg(1);
12864 jt_label = pic16_popGetLabel (jtab->key);
12865 //fprintf (stderr, "Creating jump table...\n");
12867 // calculate offset into jump table (idx * sizeof (GOTO))
12868 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12869 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12870 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12871 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12872 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12873 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12874 pic16_emitpcode(POC_MOVWF , jt_offs);
12876 // prepare PCLATx (set to first entry in jump table)
12877 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12878 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12879 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12880 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12881 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12883 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12884 pic16_emitpcode(POC_ADDWF , jt_offs);
12885 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12886 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12888 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12890 // release temporaries and prepare jump into table (new PCL --> WREG)
12891 pic16_emitpcode(POC_MOVFW , jt_offs);
12892 pic16_popReleaseTempReg (jt_offs_hi, 1);
12893 pic16_popReleaseTempReg (jt_offs, 0);
12895 // jump into the table
12896 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12898 pic16_emitpLabelFORCE(jtab->key);
12901 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12902 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12904 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12905 /* now generate the jump labels */
12906 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12907 jtab = setNextItem(IC_JTLABELS(ic))) {
12908 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12912 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12916 /*-----------------------------------------------------------------*/
12917 /* genMixedOperation - gen code for operators between mixed types */
12918 /*-----------------------------------------------------------------*/
12920 TSD - Written for the PIC port - but this unfortunately is buggy.
12921 This routine is good in that it is able to efficiently promote
12922 types to different (larger) sizes. Unfortunately, the temporary
12923 variables that are optimized out by this routine are sometimes
12924 used in other places. So until I know how to really parse the
12925 iCode tree, I'm going to not be using this routine :(.
12927 static int genMixedOperation (iCode *ic)
12930 operand *result = IC_RESULT(ic);
12931 sym_link *ctype = operandType(IC_LEFT(ic));
12932 operand *right = IC_RIGHT(ic);
12938 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12940 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12946 nextright = IC_RIGHT(nextic);
12947 nextleft = IC_LEFT(nextic);
12948 nextresult = IC_RESULT(nextic);
12950 pic16_aopOp(right,ic,FALSE);
12951 pic16_aopOp(result,ic,FALSE);
12952 pic16_aopOp(nextright, nextic, FALSE);
12953 pic16_aopOp(nextleft, nextic, FALSE);
12954 pic16_aopOp(nextresult, nextic, FALSE);
12956 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12958 operand *t = right;
12962 pic16_emitcode(";remove right +","");
12964 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12966 operand *t = right;
12970 pic16_emitcode(";remove left +","");
12974 big = AOP_SIZE(nextleft);
12975 small = AOP_SIZE(nextright);
12977 switch(nextic->op) {
12980 pic16_emitcode(";optimize a +","");
12981 /* if unsigned or not an integral type */
12982 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12983 pic16_emitcode(";add a bit to something","");
12986 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12988 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12989 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12990 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12992 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13000 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13001 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13002 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13005 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13007 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13008 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13009 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13010 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13011 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13014 pic16_emitcode("rlf","known_zero,w");
13021 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13022 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13023 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13025 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13035 pic16_freeAsmop(right,NULL,ic,TRUE);
13036 pic16_freeAsmop(result,NULL,ic,TRUE);
13037 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13038 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13040 nextic->generated = 1;
13047 /*-----------------------------------------------------------------*/
13048 /* genCast - gen code for casting */
13049 /*-----------------------------------------------------------------*/
13050 static void genCast (iCode *ic)
13052 operand *result = IC_RESULT(ic);
13053 sym_link *ctype = operandType(IC_LEFT(ic));
13054 sym_link *rtype = operandType(IC_RIGHT(ic));
13055 sym_link *restype = operandType(IC_RESULT(ic));
13056 operand *right = IC_RIGHT(ic);
13062 /* if they are equivalent then do nothing */
13063 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13066 pic16_aopOp(result,ic,FALSE);
13067 pic16_aopOp(right,ic,FALSE) ;
13069 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13072 /* if the result is a bit */
13073 if (AOP_TYPE(result) == AOP_CRY) {
13075 /* if the right size is a literal then
13076 * we know what the value is */
13077 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13079 if (AOP_TYPE(right) == AOP_LIT) {
13080 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13081 pic16_popGet(AOP(result),0));
13083 if (((int) operandLitValue(right)))
13084 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13085 AOP(result)->aopu.aop_dir,
13086 AOP(result)->aopu.aop_dir);
13088 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13089 AOP(result)->aopu.aop_dir,
13090 AOP(result)->aopu.aop_dir);
13094 /* the right is also a bit variable */
13095 if (AOP_TYPE(right) == AOP_CRY) {
13097 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13099 pic16_emitcode("clrc","");
13100 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13101 AOP(right)->aopu.aop_dir,
13102 AOP(right)->aopu.aop_dir);
13103 pic16_aopPut(AOP(result),"c",0);
13107 /* we need to or */
13108 if (AOP_TYPE(right) == AOP_REG) {
13109 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13110 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13111 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13113 pic16_toBoolean(right);
13114 pic16_aopPut(AOP(result),"a",0);
13118 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13121 size = AOP_SIZE(result);
13123 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13125 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13126 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13127 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13130 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13135 if(IS_BITFIELD(getSpec(restype))
13136 && IS_BITFIELD(getSpec(rtype))) {
13137 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13140 /* port from pic14 to cope with generic pointers */
13141 if (PIC_IS_TAGGED(restype))
13143 operand *result = IC_RESULT(ic);
13144 //operand *left = IC_LEFT(ic);
13145 operand *right = IC_RIGHT(ic);
13148 /* copy common part */
13149 int max, size = AOP_SIZE(result);
13150 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13151 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13156 pic16_mov2w (AOP(right), size);
13157 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13160 /* upcast into generic pointer type? */
13161 if (IS_GENPTR(restype)
13162 && !PIC_IS_TAGGED(rtype)
13163 && (AOP_SIZE(result) > max))
13165 /* determine appropriate tag for right */
13166 if (PIC_IS_DATA_PTR(rtype))
13167 tag = GPTR_TAG_DATA;
13168 else if (IS_CODEPTR(rtype))
13169 tag = GPTR_TAG_CODE;
13170 else if (PIC_IS_DATA_PTR(ctype)) {
13171 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13172 tag = GPTR_TAG_DATA;
13173 } else if (IS_CODEPTR(ctype)) {
13174 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13175 tag = GPTR_TAG_CODE;
13176 } else if (IS_PTR(rtype)) {
13177 PERFORM_ONCE(weirdcast,
13178 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13180 tag = GPTR_TAG_DATA;
13182 PERFORM_ONCE(weirdcast,
13183 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13185 tag = GPTR_TAG_DATA;
13188 assert (AOP_SIZE(result) == 3);
13189 /* zero-extend address... */
13190 for (size = max; size < AOP_SIZE(result)-1; size++)
13191 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13192 /* ...and add tag */
13193 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13194 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13195 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13196 for (size = max; size < AOP_SIZE(result)-1; size++)
13197 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13198 /* add __code tag */
13199 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13200 } else if (AOP_SIZE(result) > max) {
13201 /* extend non-pointers */
13202 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13203 pic16_addSign(result, max, 0);
13208 /* if they are the same size : or less */
13209 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13211 /* if they are in the same place */
13212 if (pic16_sameRegs(AOP(right),AOP(result)))
13215 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13217 if (IS_PTR_CONST(rtype))
13219 if (IS_CODEPTR(rtype))
13221 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13224 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13226 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13228 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13231 if(AOP_TYPE(right) == AOP_IMMD) {
13232 pCodeOp *pcop0, *pcop1, *pcop2;
13233 symbol *sym = OP_SYMBOL( right );
13235 size = AOP_SIZE(result);
13237 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13239 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13241 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13244 pic16_emitpcode(POC_MOVLW, pcop0);
13245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13246 pic16_emitpcode(POC_MOVLW, pcop1);
13247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13248 pic16_emitpcode(POC_MOVLW, pcop2);
13249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13252 pic16_emitpcode(POC_MOVLW, pcop0);
13253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13254 pic16_emitpcode(POC_MOVLW, pcop1);
13255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13257 pic16_emitpcode(POC_MOVLW, pcop0);
13258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13262 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13263 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13266 if(AOP_SIZE(result) < 2) {
13267 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13269 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13273 /* if they in different places then copy */
13274 size = AOP_SIZE(result);
13277 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13285 /* if the result is of type pointer */
13286 if (IS_PTR(ctype)) {
13288 sym_link *type = operandType(right);
13289 sym_link *etype = getSpec(type);
13291 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13293 /* pointer to generic pointer */
13294 if (IS_GENPTR(ctype)) {
13298 p_type = DCL_TYPE(type);
13300 /* we have to go by the storage class */
13301 p_type = PTR_TYPE(SPEC_OCLS(etype));
13303 /* if (SPEC_OCLS(etype)->codesp ) */
13304 /* p_type = CPOINTER ; */
13306 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13307 /* p_type = FPOINTER ; */
13309 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13310 /* p_type = PPOINTER; */
13312 /* if (SPEC_OCLS(etype) == idata ) */
13313 /* p_type = IPOINTER ; */
13315 /* p_type = POINTER ; */
13318 /* the first two bytes are known */
13319 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13320 size = GPTRSIZE - 1;
13323 if(offset < AOP_SIZE(right)) {
13324 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13325 pic16_mov2f(AOP(result), AOP(right), offset);
13327 if ((AOP_TYPE(right) == AOP_PCODE) &&
13328 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13329 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13333 pic16_aopPut(AOP(result),
13334 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13339 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13342 /* the last byte depending on type */
13347 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13351 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13355 pic16_emitcode(";BUG!? ","%d",__LINE__);
13360 if (GPTRSIZE > AOP_SIZE(right)) {
13361 // assume __data pointer... THIS MIGHT BE WRONG!
13362 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13364 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13369 /* this should never happen */
13370 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13371 "got unknown pointer type");
13374 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13380 /* just copy the pointers */
13381 size = AOP_SIZE(result);
13384 pic16_aopPut(AOP(result),
13385 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13394 /* so we now know that the size of destination is greater
13395 than the size of the source.
13396 Now, if the next iCode is an operator then we might be
13397 able to optimize the operation without performing a cast.
13399 if(genMixedOperation(ic))
13402 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13404 /* we move to result for the size of source */
13405 size = AOP_SIZE(right);
13410 pic16_mov2f(AOP(result), AOP(right), offset);
13414 /* now depending on the sign of the destination */
13415 size = AOP_SIZE(result) - AOP_SIZE(right);
13416 /* if unsigned or not an integral type */
13417 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13419 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13421 /* we need to extend the sign :( */
13424 /* Save one instruction of casting char to int */
13425 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13426 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13427 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13429 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13432 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13434 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13444 pic16_freeAsmop(right,NULL,ic,TRUE);
13445 pic16_freeAsmop(result,NULL,ic,TRUE);
13449 /*-----------------------------------------------------------------*/
13450 /* genDjnz - generate decrement & jump if not zero instrucion */
13451 /*-----------------------------------------------------------------*/
13452 static int genDjnz (iCode *ic, iCode *ifx)
13454 symbol *lbl, *lbl1;
13455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13460 /* if the if condition has a false label
13461 then we cannot save */
13465 /* if the minus is not of the form
13467 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13468 !IS_OP_LITERAL(IC_RIGHT(ic)))
13471 if (operandLitValue(IC_RIGHT(ic)) != 1)
13474 /* if the size of this greater than one then no
13476 if (getSize(operandType(IC_RESULT(ic))) > 1)
13479 /* otherwise we can save BIG */
13480 lbl = newiTempLabel(NULL);
13481 lbl1= newiTempLabel(NULL);
13483 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13485 if (IS_AOP_PREG(IC_RESULT(ic))) {
13486 pic16_emitcode("dec","%s",
13487 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13488 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13489 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13493 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13494 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13496 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13497 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13501 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13502 ifx->generated = 1;
13506 /*-----------------------------------------------------------------*/
13507 /* genReceive - generate code for a receive iCode */
13508 /*-----------------------------------------------------------------*/
13509 static void genReceive (iCode *ic)
13515 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13516 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13518 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13520 if (isOperandInFarSpace(IC_RESULT(ic))
13521 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13522 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13524 int size = getSize(operandType(IC_RESULT(ic)));
13525 int offset = pic16_fReturnSizePic - size;
13529 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13530 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13534 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13536 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13537 size = AOP_SIZE(IC_RESULT(ic));
13540 pic16_emitcode ("pop","acc");
13541 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13544 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13546 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13549 /* set pseudo stack pointer to where it should be - dw*/
13550 GpsuedoStkPtr = ic->parmBytes;
13552 /* setting GpsuedoStkPtr has side effects here: */
13553 /* FIXME: What's the correct size of the return(ed) value?
13554 * For now, assuming '4' as before... */
13555 assignResultValue(IC_RESULT(ic), 4, 0);
13558 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13561 /*-----------------------------------------------------------------*/
13562 /* genDummyRead - generate code for dummy read of volatiles */
13563 /*-----------------------------------------------------------------*/
13565 genDummyRead (iCode * ic)
13571 if (op && IS_SYMOP(op)) {
13572 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13573 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13576 pic16_aopOp (op, ic, FALSE);
13577 for (i=0; i < AOP_SIZE(op); i++) {
13578 // may need to protect this from the peepholer -- this is not nice but works...
13579 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13580 pic16_mov2w (AOP(op),i);
13581 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13583 pic16_freeAsmop (op, NULL, ic, TRUE);
13585 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13589 /*-----------------------------------------------------------------*/
13590 /* genpic16Code - generate code for pic16 based controllers */
13591 /*-----------------------------------------------------------------*/
13593 * At this point, ralloc.c has gone through the iCode and attempted
13594 * to optimize in a way suitable for a PIC. Now we've got to generate
13595 * PIC instructions that correspond to the iCode.
13597 * Once the instructions are generated, we'll pass through both the
13598 * peep hole optimizer and the pCode optimizer.
13599 *-----------------------------------------------------------------*/
13601 void genpic16Code (iCode *lic)
13606 lineHead = lineCurr = NULL;
13608 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13609 pic16_addpBlock(pb);
13612 /* if debug information required */
13613 if (options.debug && currFunc) {
13615 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13620 for (ic = lic ; ic ; ic = ic->next ) {
13622 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13623 if ( cln != ic->lineno ) {
13624 if ( options.debug ) {
13625 debugFile->writeCLine (ic);
13628 if(!options.noCcodeInAsm) {
13629 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13630 printCLine(ic->filename, ic->lineno)));
13636 if(options.iCodeInAsm) {
13639 /* insert here code to print iCode as comment */
13640 iLine = printILine(ic);
13641 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13645 /* if the result is marked as
13646 * spilt and rematerializable or code for
13647 * this has already been generated then
13649 if (resultRemat(ic) || ic->generated )
13652 /* depending on the operation */
13671 /* IPOP happens only when trying to restore a
13672 * spilt live range, if there is an ifx statement
13673 * following this pop then the if statement might
13674 * be using some of the registers being popped which
13675 * would destroy the contents of the register so
13676 * we need to check for this condition and handle it */
13678 && ic->next->op == IFX
13679 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13680 genIfx (ic->next,ic);
13698 genEndFunction (ic);
13714 pic16_genPlus (ic) ;
13718 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13719 pic16_genMinus (ic);
13735 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13739 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13745 /* note these two are xlated by algebraic equivalence
13746 * during parsing SDCC.y */
13747 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13748 "got '>=' or '<=' shouldn't have come here");
13752 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13764 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13768 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13772 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13796 genRightShift (ic);
13799 case GET_VALUE_AT_ADDRESS:
13804 if (POINTER_SET(ic))
13831 addSet(&_G.sendSet,ic);
13834 case DUMMY_READ_VOLATILE:
13844 /* now we are ready to call the
13845 peep hole optimizer */
13846 if (!options.nopeep)
13847 peepHole (&lineHead);
13849 /* now do the actual printing */
13850 printLine (lineHead, codeOutBuf);
13853 DFPRINTF((stderr,"printing pBlock\n\n"));
13854 pic16_printpBlock(stdout,pb);