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 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
54 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
55 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
57 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
59 /* Wrapper to execute `code' at most once. */
60 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
62 void pic16_genMult8X8_n (operand *, operand *,operand *);
63 extern void pic16_printpBlock(FILE *of, pBlock *pb);
64 static asmop *newAsmop (short type);
65 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
66 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
67 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
68 static pCodeOp *pic16_popRegFromIdx(int rIdx);
70 int pic16_labelOffset=0;
71 extern int pic16_debug_verbose;
75 /* max_key keeps track of the largest label number used in
76 a function. This is then used to adjust the label offset
77 for the next function.
80 static int GpsuedoStkPtr=0;
82 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
84 const char *pic16_AopType(short type);
85 static iCode *ifxForOp ( operand *op, iCode *ic );
87 void pic16_pushpCodeOp(pCodeOp *pcop);
88 void pic16_poppCodeOp(pCodeOp *pcop);
91 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
93 /* set the following macro to 1 to enable passing the
94 * first byte of functions parameters via WREG */
95 #define USE_WREG_IN_FUNC_PARAMS 0
98 /* this is the down and dirty file with all kinds of
99 kludgy & hacky stuff. This is what it is all about
100 CODE GENERATION for a specific MCU . some of the
101 routines may be reusable, will have to see */
102 static char *zero = "#0x00";
103 static char *one = "#0x01";
107 * Function return value policy (MSB-->LSB):
109 * 16 bits -> PRODL:WREG
110 * 24 bits -> PRODH:PRODL:WREG
111 * 32 bits -> FSR0L:PRODH:PRODL:WREG
112 * >32 bits -> on stack, and FSR0 points to the beginning
114 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
115 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
116 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
117 static char **fReturn = fReturnpic16;
119 static char *accUse[] = {"WREG"};
129 bitVect *fregsUsed; /* registers used in function */
131 set *sregsAllocSet; /* registers used to store stack variables */
132 int stack_lat; /* stack offset latency */
134 int useWreg; /* flag when WREG is used to pass function parameter */
137 extern struct dbuf_s *codeOutBuf;
139 static lineNode *lineHead = NULL;
140 static lineNode *lineCurr = NULL;
142 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
143 0xE0, 0xC0, 0x80, 0x00};
144 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
145 0x07, 0x03, 0x01, 0x00};
149 /*-----------------------------------------------------------------*/
150 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
151 /* exponent of 2 is returned, otherwise -1 is */
153 /* note that this is similar to the function `powof2' in SDCCsymt */
157 /*-----------------------------------------------------------------*/
158 int pic16_my_powof2 (unsigned long num)
161 if( (num & (num-1)) == 0) {
174 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
176 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
178 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
179 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
180 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
181 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
182 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
183 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
184 ((result) ? AOP_SIZE(result) : 0));
187 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
190 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
192 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
193 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
194 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
195 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
196 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
197 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
201 void pic16_emitpcomment (char *fmt, ...)
204 char lb[INITIAL_INLINEASM];
205 unsigned char *lbp = (unsigned char *)lb;
210 vsprintf(lb+1,fmt,ap);
212 while (isspace(*lbp)) lbp++;
215 lineCurr = (lineCurr ?
216 connectLine(lineCurr,newLineNode(lb)) :
217 (lineHead = newLineNode(lb)));
218 lineCurr->isInline = _G.inLine;
219 lineCurr->isDebug = _G.debugLine;
220 lineCurr->isComment = 1;
222 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
225 // fprintf(stderr, "%s\n", lb);
228 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
231 char lb[INITIAL_INLINEASM];
232 unsigned char *lbp = (unsigned char *)lb;
234 if(!pic16_debug_verbose)
241 sprintf(lb,"%s\t",inst);
243 sprintf(lb,"%s",inst);
244 vsprintf(lb+(strlen(lb)),fmt,ap);
248 while (isspace(*lbp)) lbp++;
251 lineCurr = (lineCurr ?
252 connectLine(lineCurr,newLineNode(lb)) :
253 (lineHead = newLineNode(lb)));
254 lineCurr->isInline = _G.inLine;
255 lineCurr->isDebug = _G.debugLine;
257 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
260 // fprintf(stderr, "%s\n", lb);
265 void pic16_emitpLabel(int key)
267 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
270 void pic16_emitpLabelFORCE(int key)
272 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
275 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
276 * NEVER call pic16_emitpcode_real directly, please... */
277 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
281 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
283 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
286 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
289 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
291 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
294 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
297 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
303 #define pic16_emitcode DEBUGpic16_emitcode
305 /*-----------------------------------------------------------------*/
306 /* pic16_emitcode - writes the code into a file : for now it is simple */
307 /*-----------------------------------------------------------------*/
308 void pic16_emitcode (char *inst,char *fmt, ...)
311 char lb[INITIAL_INLINEASM];
312 unsigned char *lbp = lb;
318 sprintf(lb,"%s\t",inst);
320 sprintf(lb,"%s",inst);
321 vsprintf(lb+(strlen(lb)),fmt,ap);
325 while (isspace(*lbp)) lbp++;
328 lineCurr = (lineCurr ?
329 connectLine(lineCurr,newLineNode(lb)) :
330 (lineHead = newLineNode(lb)));
331 lineCurr->isInline = _G.inLine;
332 lineCurr->isDebug = _G.debugLine;
333 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
334 lineCurr->isComment = (*lbp == ';');
336 // VR fprintf(stderr, "lb = <%s>\n", lbp);
338 // if(pic16_debug_verbose)
339 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
346 /*-----------------------------------------------------------------*/
347 /* pic16_emitDebuggerSymbol - associate the current code location */
348 /* with a debugger symbol */
349 /*-----------------------------------------------------------------*/
351 pic16_emitDebuggerSymbol (char * debugSym)
354 pic16_emitcode (";", "%s ==.", debugSym);
358 /*-----------------------------------------------------------------*/
359 /* newAsmop - creates a new asmOp */
360 /*-----------------------------------------------------------------*/
361 static asmop *newAsmop (short type)
365 aop = Safe_calloc(1,sizeof(asmop));
370 /*-----------------------------------------------------------------*/
371 /* resolveIfx - converts an iCode ifx into a form more useful for */
372 /* generating code */
373 /*-----------------------------------------------------------------*/
374 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
378 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
384 resIfx->condition = 1; /* assume that the ifx is true */
385 resIfx->generated = 0; /* indicate that the ifx has not been used */
388 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
391 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
392 __FUNCTION__,__LINE__,resIfx->lbl->key);
397 resIfx->lbl = IC_TRUE(ifx);
399 resIfx->lbl = IC_FALSE(ifx);
400 resIfx->condition = 0;
405 DEBUGpic16_emitcode("; +++","ifx true is non-null");
407 DEBUGpic16_emitcode("; +++","ifx true is null");
409 DEBUGpic16_emitcode("; +++","ifx false is non-null");
411 DEBUGpic16_emitcode("; +++","ifx false is null");
415 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
419 /*-----------------------------------------------------------------*/
420 /* pointerCode - returns the code for a pointer type */
421 /*-----------------------------------------------------------------*/
422 static int pointerCode (sym_link *etype)
425 return PTR_TYPE(SPEC_OCLS(etype));
430 /*-----------------------------------------------------------------*/
431 /* aopForSym - for a true symbol */
432 /*-----------------------------------------------------------------*/
433 static asmop *aopForSym (iCode *ic, operand *op, bool result)
435 symbol *sym=OP_SYMBOL(op);
437 memmap *space= SPEC_OCLS(sym->etype);
441 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
443 // sym = OP_SYMBOL(op);
445 /* if already has one */
447 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
452 /* if symbol was initially placed onStack then we must re-place it
453 * to direct memory, since pic16 does not have a specific stack */
455 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
463 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
465 sym->aop = aop = newAsmop (AOP_PAGED);
466 aop->aopu.aop_dir = sym->rname ;
467 aop->size = getSize(sym->type);
468 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
469 pic16_allocDirReg( IC_LEFT(ic) );
477 /* assign depending on the storage class */
478 /* if it is on the stack or indirectly addressable */
479 /* space we need to assign either r0 or r1 to it */
480 if (sym->onStack) // || sym->iaccess)
485 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
486 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
488 /* acquire a temporary register -- it is saved in function */
490 sym->aop = aop = newAsmop(AOP_STA);
491 aop->aopu.stk.stk = sym->stack;
492 aop->size = getSize(sym->type);
495 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
496 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
497 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
498 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
500 for(i=0;i<aop->size;i++)
501 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
502 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
504 if(1 && ic->op == SEND) {
506 /* if SEND do the send here */
509 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
510 for(i=0;i<aop->size;i++) {
511 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
512 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
517 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
520 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
522 // we do not need to load the value if it is to be defined...
523 if (result) return aop;
526 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
529 for(i=0;i<aop->size;i++) {
531 /* initialise for stack access via frame pointer */
532 // operands on stack are accessible via "{FRAME POINTER} + index" with index
533 // starting at 2 for arguments and growing from 0 downwards for
534 // local variables (index == 0 is not assigned so we add one here)
536 int soffs = sym->stack;
542 if(1 && ic->op == SEND) {
543 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
544 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
545 pic16_popCopyReg( pic16_frame_plusw ),
546 pic16_popCopyReg(pic16_stack_postdec )));
548 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
549 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
550 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
556 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
563 /* now assign the address of the variable to
564 the pointer register */
565 if (aop->type != AOP_STK) {
569 pic16_emitcode("push","acc");
571 pic16_emitcode("mov","a,_bp");
572 pic16_emitcode("add","a,#0x%02x",
574 ((char)(sym->stack - _G.nRegsSaved )) :
575 ((char)sym->stack)) & 0xff);
576 pic16_emitcode("mov","%s,a",
577 aop->aopu.aop_ptr->name);
580 pic16_emitcode("pop","acc");
582 pic16_emitcode("mov","%s,#%s",
583 aop->aopu.aop_ptr->name,
585 aop->paged = space->paged;
587 aop->aopu.aop_stk = sym->stack;
595 /* special case for a function */
596 if (IS_FUNC(sym->type)) {
597 sym->aop = aop = newAsmop(AOP_PCODE);
598 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
599 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
600 PCOI(aop->aopu.pcop)->index = 0;
601 aop->size = FPTRSIZE;
602 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
609 //DEBUGpic16_emitcode(";","%d",__LINE__);
610 /* if in bit space */
611 if (IN_BITSPACE(space)) {
612 sym->aop = aop = newAsmop (AOP_CRY);
613 aop->aopu.aop_dir = sym->rname ;
614 aop->size = getSize(sym->type);
615 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
618 /* if it is in direct space */
619 if (IN_DIRSPACE(space)) {
620 if(!strcmp(sym->rname, "_WREG")) {
621 sym->aop = aop = newAsmop (AOP_ACC);
622 aop->size = getSize(sym->type); /* should always be 1 */
623 assert(aop->size == 1);
624 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
627 sym->aop = aop = newAsmop (AOP_DIR);
628 aop->aopu.aop_dir = sym->rname ;
629 aop->size = getSize(sym->type);
630 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
631 pic16_allocDirReg( IC_LEFT(ic) );
636 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
637 sym->aop = aop = newAsmop (AOP_DIR);
638 aop->aopu.aop_dir = sym->rname ;
639 aop->size = getSize(sym->type);
640 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
641 pic16_allocDirReg( IC_LEFT(ic) );
646 /* only remaining is far space */
647 sym->aop = aop = newAsmop(AOP_PCODE);
649 /* change the next if to 1 to revert to good old immediate code */
650 if(IN_CODESPACE(space)) {
651 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
652 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
653 PCOI(aop->aopu.pcop)->index = 0;
655 /* try to allocate via direct register */
656 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
657 // aop->size = getSize( sym->type );
660 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
661 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
664 if(!pic16_allocDirReg (IC_LEFT(ic)))
668 if(IN_DIRSPACE( space ))
670 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
671 aop->size = FPTRSIZE;
672 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
673 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
674 else if(sym->onStack) {
677 if(SPEC_SCLS(sym->etype) == S_PDATA) {
678 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
679 aop->size = FPTRSIZE;
684 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
686 /* if it is in code space */
687 if (IN_CODESPACE(space))
693 /*-----------------------------------------------------------------*/
694 /* aopForRemat - rematerialzes an object */
695 /*-----------------------------------------------------------------*/
696 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
698 symbol *sym = OP_SYMBOL(op);
700 iCode *ic = NULL, *oldic;
701 asmop *aop = newAsmop(AOP_PCODE);
708 ic = sym->rematiCode;
710 if(IS_OP_POINTER(op)) {
711 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
714 // if(!result) /* fixme-vr */
718 // chat *iLine = printILine(ic);
719 // pic16_emitpcomment("ic: %s\n", iLine);
723 val += (int) operandLitValue(IC_RIGHT(ic));
724 } else if (ic->op == '-') {
725 val -= (int) operandLitValue(IC_RIGHT(ic));
729 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
732 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
735 if(!op->isaddr)viaimmd++; else viaimmd=0;
737 /* set the following if to 1 to revert to good old immediate code */
738 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
741 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
743 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
746 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
748 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
751 PCOI(aop->aopu.pcop)->index = val;
753 aop->size = getSize( sym->type );
755 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
757 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
758 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
760 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
764 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
765 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
767 val, IS_PTR_CONST(operandType(op)));
769 val, IS_CODEPTR(operandType(op)));
772 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
774 pic16_allocDirReg (IC_LEFT(ic));
776 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
783 static int aopIdx (asmop *aop, int offset)
788 if(aop->type != AOP_REG)
791 return aop->aopu.aop_reg[offset]->rIdx;
796 /*-----------------------------------------------------------------*/
797 /* regsInCommon - two operands have some registers in common */
798 /*-----------------------------------------------------------------*/
799 static bool regsInCommon (operand *op1, operand *op2)
804 /* if they have registers in common */
805 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
808 sym1 = OP_SYMBOL(op1);
809 sym2 = OP_SYMBOL(op2);
811 if (sym1->nRegs == 0 || sym2->nRegs == 0)
814 for (i = 0 ; i < sym1->nRegs ; i++) {
819 for (j = 0 ; j < sym2->nRegs ;j++ ) {
823 if (sym2->regs[j] == sym1->regs[i])
831 /*-----------------------------------------------------------------*/
832 /* operandsEqu - equivalent */
833 /*-----------------------------------------------------------------*/
834 static bool operandsEqu ( operand *op1, operand *op2)
838 /* if they not symbols */
839 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
842 sym1 = OP_SYMBOL(op1);
843 sym2 = OP_SYMBOL(op2);
845 /* if both are itemps & one is spilt
846 and the other is not then false */
847 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
848 sym1->isspilt != sym2->isspilt )
851 /* if they are the same */
855 if (sym1->rname[0] && sym2->rname[0]
856 && strcmp (sym1->rname, sym2->rname) == 0)
860 /* if left is a tmp & right is not */
864 (sym1->usl.spillLoc == sym2))
871 (sym2->usl.spillLoc == sym1))
877 /*-----------------------------------------------------------------*/
878 /* pic16_sameRegs - two asmops have the same registers */
879 /*-----------------------------------------------------------------*/
880 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
887 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
888 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
890 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
892 if (aop1->type != AOP_REG ||
893 aop2->type != AOP_REG )
896 /* This is a bit too restrictive if one is a subset of the other...
897 if (aop1->size != aop2->size )
901 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
902 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
904 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
905 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
912 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
914 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
915 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
917 if(aop1 == aop2)return TRUE;
918 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
920 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
926 /*-----------------------------------------------------------------*/
927 /* pic16_aopOp - allocates an asmop for an operand : */
928 /*-----------------------------------------------------------------*/
929 void pic16_aopOp (operand *op, iCode *ic, bool result)
938 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
940 /* if this a literal */
941 if (IS_OP_LITERAL(op)) {
942 op->aop = aop = newAsmop(AOP_LIT);
943 aop->aopu.aop_lit = op->operand.valOperand;
944 aop->size = getSize(operandType(op));
949 sym_link *type = operandType(op);
951 if(IS_PTR_CONST(type))
955 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
958 /* if already has a asmop then continue */
962 /* if the underlying symbol has a aop */
963 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
964 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
965 op->aop = OP_SYMBOL(op)->aop;
969 /* if this is a true symbol */
970 if (IS_TRUE_SYMOP(op)) {
971 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
972 op->aop = aopForSym(ic, op, result);
976 /* this is a temporary : this has
982 e) can be a return use only */
986 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
987 /* if the type is a conditional */
988 if (sym->regType == REG_CND) {
989 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
994 /* if it is spilt then two situations
996 b) has a spill location */
997 if (sym->isspilt || sym->nRegs == 0) {
999 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1000 DEBUGpic16_emitcode(";","%d",__LINE__);
1001 /* rematerialize it NOW */
1004 sym->aop = op->aop = aop = aopForRemat (op, result);
1011 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1012 aop->size = getSize(sym->type);
1013 for ( i = 0 ; i < 1 ; i++ ) {
1014 aop->aopu.aop_str[i] = accUse[i];
1015 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1017 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1018 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1026 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1027 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1028 //pic16_allocDirReg (IC_LEFT(ic));
1029 aop->size = getSize(sym->type);
1034 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1035 aop->size = getSize(sym->type);
1036 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1037 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1039 DEBUGpic16_emitcode(";","%d",__LINE__);
1043 /* else spill location */
1044 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1045 /* force a new aop if sizes differ */
1046 sym->usl.spillLoc->aop = NULL;
1050 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1051 __FUNCTION__,__LINE__,
1052 sym->usl.spillLoc->rname,
1053 sym->rname, sym->usl.spillLoc->offset);
1056 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1057 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1058 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1059 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1061 sym->usl.spillLoc->offset, op);
1062 } else if (getSize(sym->type) <= 1) {
1063 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1064 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1065 assert (getSize(sym->type) <= 1);
1066 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1067 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1069 /* We need some kind of dummy area for getSize(sym->type) byte,
1070 * use WREG for all storage locations.
1071 * XXX: This only works if we are implementing a `dummy read',
1072 * the stored value will not be retrievable...
1073 * See #1503234 for a case requiring this. */
1074 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1075 aop->size = getSize(sym->type);
1076 for ( i = 0 ; i < aop->size ;i++)
1077 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1079 aop->size = getSize(sym->type);
1085 sym_link *type = operandType(op);
1087 if(IS_PTR_CONST(type))
1089 if(IS_CODEPTR(type))
1091 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1094 /* must be in a register */
1095 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1096 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1097 aop->size = sym->nRegs;
1098 for ( i = 0 ; i < sym->nRegs ;i++)
1099 aop->aopu.aop_reg[i] = sym->regs[i];
1102 /*-----------------------------------------------------------------*/
1103 /* pic16_freeAsmop - free up the asmop given to an operand */
1104 /*----------------------------------------------------------------*/
1105 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1123 switch (aop->type) {
1128 /* we must store the result on stack */
1129 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1130 // operands on stack are accessible via "FSR2 + index" with index
1131 // starting at 2 for arguments and growing from 0 downwards for
1132 // local variables (index == 0 is not assigned so we add one here)
1133 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1138 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1139 for(i=0;i<aop->size;i++) {
1140 /* initialise for stack access via frame pointer */
1141 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1142 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1143 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1146 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1150 for(i=0;i<aop->size;i++) {
1151 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1153 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1154 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1155 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1162 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1163 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1164 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1165 deleteSetItem( &_G.sregsAllocSet, sr );
1176 int stk = aop->aopu.aop_stk + aop->size;
1177 bitVectUnSetBit(ic->rUsed,R0_IDX);
1178 bitVectUnSetBit(ic->rUsed,R1_IDX);
1180 getFreePtr(ic,&aop,FALSE);
1182 if (options.stack10bit)
1184 /* I'm not sure what to do here yet... */
1187 "*** Warning: probably generating bad code for "
1188 "10 bit stack mode.\n");
1192 pic16_emitcode ("mov","a,_bp");
1193 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1194 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1196 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1200 pic16_emitcode("pop","acc");
1201 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1203 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1206 pic16_freeAsmop(op,NULL,ic,TRUE);
1208 pic16_emitcode("pop","ar0");
1213 pic16_emitcode("pop","ar1");
1223 /* all other cases just dealloc */
1227 OP_SYMBOL(op)->aop = NULL;
1228 /* if the symbol has a spill */
1230 SPIL_LOC(op)->aop = NULL;
1235 /*-----------------------------------------------------------------*/
1236 /* pic16_aopGet - for fetching value of the aop */
1237 /*-----------------------------------------------------------------*/
1238 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1243 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1245 /* offset is greater than size then zero */
1246 if (offset > (aop->size - 1) &&
1247 aop->type != AOP_LIT)
1250 /* depending on type */
1251 switch (aop->type) {
1254 sprintf(s,"(%s + %d)",
1257 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1259 sprintf(s,"%s",aop->aopu.aop_dir);
1260 rs = Safe_calloc(1,strlen(s)+1);
1265 return aop->aopu.aop_reg[offset]->name;
1268 return aop->aopu.aop_dir;
1271 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1272 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1274 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1275 rs = Safe_strdup("WREG");
1279 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1280 rs = Safe_calloc(1,strlen(s)+1);
1285 aop->coff = offset ;
1287 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1290 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1291 aop->type = AOP_ACC;
1292 return Safe_strdup("_WREG");
1294 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1296 return aop->aopu.aop_str[offset];
1300 pCodeOp *pcop = aop->aopu.pcop;
1301 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1303 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1304 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1306 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1308 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1311 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1314 rs = Safe_calloc(1,strlen(s)+1);
1320 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1322 sprintf(s,"(%s + %d)",
1326 sprintf(s,"%s",aop->aopu.aop_dir);
1327 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1328 rs = Safe_calloc(1,strlen(s)+1);
1334 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1338 // pCodeOp *pcop = aop->aop
1343 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1344 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1345 "aopget got unsupported aop->type");
1351 /* lock has the following meaning: When allocating temporary registers
1352 * for stack variables storage, the value of the temporary register is
1353 * saved on stack. Its value is restored at the end. This procedure is
1354 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1355 * a possibility that before a call to pic16_aopOp, a temporary register
1356 * is allocated for a while and it is freed after some time, this will
1357 * mess the stack and values will not be restored properly. So use lock=1
1358 * to allocate temporary registers used internally by the programmer, and
1359 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1360 * to inform the compiler developer about a possible bug. This is an internal
1361 * feature for developing the compiler -- VR */
1363 int _TempReg_lock = 0;
1364 /*-----------------------------------------------------------------*/
1365 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1366 /*-----------------------------------------------------------------*/
1367 pCodeOp *pic16_popGetTempReg(int lock)
1372 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1374 // werror(W_POSSBUG2, __FILE__, __LINE__);
1377 _TempReg_lock += lock;
1382 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1383 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1384 PCOR(pcop)->r->wasUsed=1;
1385 PCOR(pcop)->r->isFree=0;
1387 /* push value on stack */
1388 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1396 /*-----------------------------------------------------------------*/
1397 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1398 /* is not part of f, but don't save if */
1400 /*-----------------------------------------------------------------*/
1401 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1407 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1410 // werror(W_POSSBUG2, __FILE__, __LINE__);
1413 _TempReg_lock += lock;
1418 i = bitVectFirstBit(f);
1421 /* bypass registers that are used by function */
1422 if(!bitVectBitValue(f, i)) {
1424 /* bypass registers that are already allocated for stack access */
1425 if(!bitVectBitValue(v, i)) {
1427 // debugf("getting register rIdx = %d\n", i);
1428 /* ok, get the operand */
1429 pcop = pic16_newpCodeOpReg( i );
1431 /* should never by NULL */
1432 assert( pcop != NULL );
1436 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1439 PCOR(pcop)->r->wasUsed=1;
1440 PCOR(pcop)->r->isFree=0;
1446 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1448 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1449 /* already used in previous steps, break */
1456 /* caller takes care of the following */
1457 // bitVectSetBit(v, i);
1460 /* push value on stack */
1461 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1462 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1478 /*-----------------------------------------------------------------*/
1479 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1480 /*-----------------------------------------------------------------*/
1481 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1485 _TempReg_lock -= lock;
1487 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1488 PCOR(pcop)->r->isFree = 1;
1490 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1493 /*-----------------------------------------------------------------*/
1494 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1495 /*-----------------------------------------------------------------*/
1496 pCodeOp *pic16_popGetLabel(int key)
1499 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1504 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1507 /*-----------------------------------------------------------------*/
1508 /* pic16_popCopyReg - copy a pcode operator */
1509 /*-----------------------------------------------------------------*/
1510 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1514 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1515 memcpy (pcor, pc, sizeof (pCodeOpReg));
1516 pcor->r->wasUsed = 1;
1518 //pcor->pcop.type = pc->pcop.type;
1520 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1521 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1523 pcor->pcop.name = NULL;
1526 //pcor->rIdx = pc->rIdx;
1527 //pcor->r->wasUsed=1;
1528 //pcor->instance = pc->instance;
1530 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1535 /*-----------------------------------------------------------------*/
1536 /* pic16_popGetLit - asm operator to pcode operator conversion */
1537 /*-----------------------------------------------------------------*/
1538 pCodeOp *pic16_popGetLit(int lit)
1540 return pic16_newpCodeOpLit(lit);
1543 /* Allow for 12 bit literals (LFSR x, <here!>). */
1544 pCodeOp *pic16_popGetLit12(int lit)
1546 return pic16_newpCodeOpLit12(lit);
1549 /*-----------------------------------------------------------------*/
1550 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1551 /*-----------------------------------------------------------------*/
1552 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1554 return pic16_newpCodeOpLit2(lit, arg2);
1558 /*-----------------------------------------------------------------*/
1559 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1560 /*-----------------------------------------------------------------*/
1561 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1563 return pic16_newpCodeOpImmd(name, offset,index, 0);
1567 /*-----------------------------------------------------------------*/
1568 /* pic16_popGet - asm operator to pcode operator conversion */
1569 /*-----------------------------------------------------------------*/
1570 pCodeOp *pic16_popGetWithString(char *str)
1576 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1580 pcop = pic16_newpCodeOp(str,PO_STR);
1585 /*-----------------------------------------------------------------*/
1586 /* pic16_popRegFromString - */
1587 /*-----------------------------------------------------------------*/
1588 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1591 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1592 pcop->type = PO_DIR;
1594 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1595 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1600 pcop->name = Safe_calloc(1,strlen(str)+1);
1601 strcpy(pcop->name,str);
1603 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1605 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1606 // PCOR(pcop)->r->wasUsed = 1;
1608 /* make sure that register doesn't exist,
1609 * and operand isn't NULL
1610 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1611 if((PCOR(pcop)->r == NULL)
1613 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1614 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1615 // __FUNCTION__, __LINE__, str, size, offset);
1617 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1618 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1621 PCOR(pcop)->instance = offset;
1626 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1630 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1631 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1633 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1634 PCOR(pcop)->rIdx = rIdx;
1635 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1637 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1639 PCOR(pcop)->r->isFree = 0;
1640 PCOR(pcop)->r->wasUsed = 1;
1642 pcop->type = PCOR(pcop)->r->pc_type;
1647 /*---------------------------------------------------------------------------------*/
1648 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1650 /*---------------------------------------------------------------------------------*/
1651 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1653 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1654 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1660 /*--------------------------------------------------------------------------------.-*/
1661 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1662 /* VR 030601 , adapted by Hans Dorn */
1663 /*--------------------------------------------------------------------------------.-*/
1664 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1667 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1671 /*---------------------------------------------------------------------------------*/
1672 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1673 /* movff instruction */
1674 /*---------------------------------------------------------------------------------*/
1675 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1677 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1678 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1684 /*-----------------------------------------------------------------*/
1685 /* pic16_popGet - asm operator to pcode operator conversion */
1686 /*-----------------------------------------------------------------*/
1687 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1689 // char *s = buffer ;
1695 /* offset is greater than size then zero */
1697 // if (offset > (aop->size - 1) &&
1698 // aop->type != AOP_LIT)
1699 // return NULL; //zero;
1701 /* depending on type */
1702 switch (aop->type) {
1704 /* pCodeOp is already allocated from aopForSym */
1705 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1706 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1711 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1713 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1715 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1717 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1718 PCOR(pcop)->rIdx = rIdx;
1719 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1720 PCOR(pcop)->r->wasUsed=1;
1721 PCOR(pcop)->r->isFree=0;
1723 PCOR(pcop)->instance = offset;
1724 pcop->type = PCOR(pcop)->r->pc_type;
1725 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1729 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1730 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1736 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1737 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1741 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1742 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1749 // debugf2("aop = %p\toffset = %d\n", aop, offset);
1750 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
1751 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1753 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1755 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1756 // pcop->type = PO_GPR_REGISTER;
1757 PCOR(pcop)->rIdx = rIdx;
1758 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1759 PCOR(pcop)->r->wasUsed=1;
1760 PCOR(pcop)->r->isFree=0;
1762 PCOR(pcop)->instance = offset;
1763 pcop->type = PCOR(pcop)->r->pc_type;
1765 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1766 // rs = aop->aopu.aop_reg[offset]->name;
1767 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1772 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1774 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1775 PCOR(pcop)->instance = offset;
1776 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1777 //if(PCOR(pcop)->r == NULL)
1778 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1782 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1783 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1786 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1787 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1790 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1791 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1792 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1793 pcop->type = PCOR(pcop)->r->pc_type;
1794 pcop->name = PCOR(pcop)->r->name;
1800 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1802 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1803 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1804 switch( aop->aopu.pcop->type ) {
1805 case PO_DIR: PCOR(pcop)->instance += offset; break;
1806 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1811 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1812 assert( 0 ); /* should never reach here */;
1817 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1818 "pic16_popGet got unsupported aop->type");
1821 /*-----------------------------------------------------------------*/
1822 /* pic16_aopPut - puts a string for a aop */
1823 /*-----------------------------------------------------------------*/
1824 void pic16_aopPut (asmop *aop, char *s, int offset)
1831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1833 if (aop->size && offset > ( aop->size - 1)) {
1834 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1835 "pic16_aopPut got offset > aop->size");
1839 /* will assign value to value */
1840 /* depending on where it is ofcourse */
1841 switch (aop->type) {
1844 sprintf(d,"(%s + %d)",
1845 aop->aopu.aop_dir,offset);
1846 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1849 sprintf(d,"%s",aop->aopu.aop_dir);
1852 DEBUGpic16_emitcode(";","%d",__LINE__);
1854 pic16_emitcode("movf","%s,w",s);
1855 pic16_emitcode("movwf","%s",d);
1858 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1859 if(offset >= aop->size) {
1860 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1863 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1866 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1873 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1874 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1877 strcmp(s,"r0") == 0 ||
1878 strcmp(s,"r1") == 0 ||
1879 strcmp(s,"r2") == 0 ||
1880 strcmp(s,"r3") == 0 ||
1881 strcmp(s,"r4") == 0 ||
1882 strcmp(s,"r5") == 0 ||
1883 strcmp(s,"r6") == 0 ||
1884 strcmp(s,"r7") == 0 )
1885 pic16_emitcode("mov","%s,%s ; %d",
1886 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1890 if(strcmp(s,"W")==0 )
1891 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1893 pic16_emitcode("movwf","%s",
1894 aop->aopu.aop_reg[offset]->name);
1896 if(strcmp(s,zero)==0) {
1897 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1899 } else if(strcmp(s,"W")==0) {
1900 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1901 pcop->type = PO_GPR_REGISTER;
1903 PCOR(pcop)->rIdx = -1;
1904 PCOR(pcop)->r = NULL;
1906 DEBUGpic16_emitcode(";","%d",__LINE__);
1907 pcop->name = Safe_strdup(s);
1908 pic16_emitpcode(POC_MOVFW,pcop);
1909 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1910 } else if(strcmp(s,one)==0) {
1911 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1912 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1914 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1920 if (strcmp(s,"a") == 0)
1921 pic16_emitcode("push","acc");
1923 pic16_emitcode("push","%s",s);
1928 /* if bit variable */
1929 if (!aop->aopu.aop_dir) {
1930 pic16_emitcode("clr","a");
1931 pic16_emitcode("rlc","a");
1934 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1937 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1940 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1942 lbl = newiTempLabel(NULL);
1944 if (strcmp(s,"a")) {
1947 pic16_emitcode("clr","c");
1948 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1949 pic16_emitcode("cpl","c");
1950 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1951 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1958 if (strcmp(aop->aopu.aop_str[offset],s))
1959 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1964 if (!offset && (strcmp(s,"acc") == 0))
1967 if (strcmp(aop->aopu.aop_str[offset],s))
1968 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1972 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1973 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1974 // "pic16_aopPut got unsupported aop->type");
1980 /*-----------------------------------------------------------------*/
1981 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
1982 /*-----------------------------------------------------------------*/
1983 void pic16_mov2w (asmop *aop, int offset)
1985 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1987 if(pic16_isLitAop(aop))
1988 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1990 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1993 void pic16_mov2w_volatile (asmop *aop)
1997 if(!pic16_isLitAop(aop)) {
1998 // may need to protect this from the peepholer -- this is not nice but works...
1999 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2000 for (i = 0; i < aop->size; i++) {
2002 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2004 pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2006 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2010 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2012 if(pic16_isLitAop(src)) {
2013 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2014 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2016 if(pic16_sameRegsOfs(src, dst, offset))return;
2017 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2018 pic16_popGet(dst, offset)));
2022 static void pic16_movLit2f(pCodeOp *pc, int lit)
2024 if (0 == (lit & 0x00ff))
2026 pic16_emitpcode (POC_CLRF, pc);
2027 } else if (0xff == (lit & 0x00ff))
2029 pic16_emitpcode (POC_SETF, pc);
2031 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2032 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2036 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2038 if(pic16_isLitAop(src)) {
2039 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2040 pic16_emitpcode(POC_MOVWF, dst);
2042 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2046 void pic16_testStackOverflow(void)
2048 #define GSTACK_TEST_NAME "_gstack_test"
2050 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2055 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2056 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2057 // strcpy(sym->rname, GSTACK_TEST_NAME);
2058 checkAddSym(&externs, sym);
2063 /* push pcop into stack */
2064 void pic16_pushpCodeOp(pCodeOp *pcop)
2066 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2067 if (pcop->type == PO_LITERAL) {
2068 pic16_emitpcode(POC_MOVLW, pcop);
2069 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2071 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2073 if(pic16_options.gstack)
2074 pic16_testStackOverflow();
2078 /* pop pcop from stack */
2079 void pic16_poppCodeOp(pCodeOp *pcop)
2081 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2082 if(pic16_options.gstack)
2083 pic16_testStackOverflow();
2087 /*-----------------------------------------------------------------*/
2088 /* pushw - pushes wreg to stack */
2089 /*-----------------------------------------------------------------*/
2092 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2093 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2094 if(pic16_options.gstack)
2095 pic16_testStackOverflow();
2099 /*-----------------------------------------------------------------*/
2100 /* pushaop - pushes aop to stack */
2101 /*-----------------------------------------------------------------*/
2102 void pushaop(asmop *aop, int offset)
2104 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2106 if(_G.resDirect)return;
2108 if(pic16_isLitAop(aop)) {
2109 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2110 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2112 pic16_emitpcode(POC_MOVFF,
2113 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2116 if(pic16_options.gstack)
2117 pic16_testStackOverflow();
2120 /*-----------------------------------------------------------------*/
2121 /* popaop - pops aop from stack */
2122 /*-----------------------------------------------------------------*/
2123 void popaop(asmop *aop, int offset)
2125 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2126 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2127 if(pic16_options.gstack)
2128 pic16_testStackOverflow();
2131 void popaopidx(asmop *aop, int offset, int index)
2135 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2137 if(STACK_MODEL_LARGE)ofs++;
2139 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2140 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2141 if(pic16_options.gstack)
2142 pic16_testStackOverflow();
2145 /*-----------------------------------------------------------------*/
2146 /* pic16_getDataSize - get the operand data size */
2147 /*-----------------------------------------------------------------*/
2148 int pic16_getDataSize(operand *op)
2150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2153 return AOP_SIZE(op);
2155 // tsd- in the pic port, the genptr size is 1, so this code here
2156 // fails. ( in the 8051 port, the size was 4).
2159 size = AOP_SIZE(op);
2160 if (size == GPTRSIZE)
2162 sym_link *type = operandType(op);
2163 if (IS_GENPTR(type))
2165 /* generic pointer; arithmetic operations
2166 * should ignore the high byte (pointer type).
2169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2176 /*-----------------------------------------------------------------*/
2177 /* pic16_outAcc - output Acc */
2178 /*-----------------------------------------------------------------*/
2179 void pic16_outAcc(operand *result)
2182 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2183 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2186 size = pic16_getDataSize(result);
2188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2191 /* unsigned or positive */
2193 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_outBitC - output a bit C */
2200 /* Move to result the value of Carry flag -- VR */
2201 /*-----------------------------------------------------------------*/
2202 void pic16_outBitC(operand *result)
2206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2208 /* if the result is bit */
2209 if (AOP_TYPE(result) == AOP_CRY) {
2210 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2211 pic16_aopPut(AOP(result),"c",0);
2214 i = AOP_SIZE(result);
2216 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2218 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2222 /*-----------------------------------------------------------------*/
2223 /* pic16_outBitOp - output a bit from Op */
2224 /* Move to result the value of set/clr op -- VR */
2225 /*-----------------------------------------------------------------*/
2226 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2232 /* if the result is bit */
2233 if (AOP_TYPE(result) == AOP_CRY) {
2234 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2235 pic16_aopPut(AOP(result),"c",0);
2238 i = AOP_SIZE(result);
2240 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2242 pic16_emitpcode(POC_RRCF, pcop);
2243 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2247 /*-----------------------------------------------------------------*/
2248 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2249 /*-----------------------------------------------------------------*/
2250 void pic16_toBoolean(operand *oper)
2252 int size = AOP_SIZE(oper) - 1;
2255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2257 if ( AOP_TYPE(oper) != AOP_ACC) {
2258 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2261 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2265 /*-----------------------------------------------------------------*/
2266 /* genUminusFloat - unary minus for floating points */
2267 /*-----------------------------------------------------------------*/
2268 static void genUminusFloat(operand *op,operand *result)
2270 int size ,offset =0 ;
2273 /* for this we just need to flip the
2274 first it then copy the rest in place */
2275 size = AOP_SIZE(op);
2276 assert( size == AOP_SIZE(result) );
2279 pic16_mov2f(AOP(result), AOP(op), offset);
2283 /* toggle the MSB's highest bit */
2284 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2287 /*-----------------------------------------------------------------*/
2288 /* genUminus - unary minus code generation */
2289 /*-----------------------------------------------------------------*/
2290 static void genUminus (iCode *ic)
2293 sym_link *optype, *rtype;
2300 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2301 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2303 /* if both in bit space then special case */
2304 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2305 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2307 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2308 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2309 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2313 optype = operandType(IC_LEFT(ic));
2314 rtype = operandType(IC_RESULT(ic));
2317 /* if float then do float stuff */
2318 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2319 if(IS_FIXED(optype))
2320 debugf("implement fixed16x16 type\n", 0);
2322 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2326 /* otherwise subtract from zero by taking the 2's complement */
2327 size = AOP_SIZE(IC_LEFT(ic));
2328 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2329 label = newiTempLabel ( NULL );
2331 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2332 for (i=size-1; i > 0; i--) {
2333 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2335 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2336 for (i=1; i < size; i++) {
2337 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2338 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2341 for (i=size-1; i >= 0; i--) {
2342 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2343 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2346 for (i=0; i < size-2; i++) {
2347 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2348 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2350 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2352 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2355 pic16_emitpLabel (label->key);
2358 /* release the aops */
2359 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2360 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2363 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2365 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2366 pic16_emitpcode(POC_MOVFW, src);
2367 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2369 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2370 src, pic16_popGet(AOP(op), offset)));
2375 /*-----------------------------------------------------------------*/
2376 /* assignResultValue - assign results to oper, rescall==1 is */
2377 /* called from genCall() or genPcall() */
2378 /*-----------------------------------------------------------------*/
2379 static void assignResultValue(operand * oper, int res_size, int rescall)
2381 int size = AOP_SIZE(oper);
2385 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2386 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2389 /* assign result from a call/pcall function() */
2391 /* function results are stored in a special order,
2392 * see top of file with Function return policy, or manual */
2395 /* 8-bits, result in WREG */
2396 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2398 if(size > 1 && res_size > 1) {
2399 /* 16-bits, result in PRODL:WREG */
2400 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2403 if(size > 2 && res_size > 2) {
2404 /* 24-bits, result in PRODH:PRODL:WREG */
2405 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2408 if(size > 3 && res_size > 3) {
2409 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2410 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2413 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2416 /* >32-bits, result on stack, and FSR0 points to beginning.
2417 * Fix stack when done */
2419 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2421 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2422 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2424 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2430 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2431 if(STACK_MODEL_LARGE) {
2433 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2437 int areg = 0; /* matching argument register */
2439 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2440 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2443 /* its called from genReceive (probably) -- VR */
2444 /* I hope this code will not be called from somewhere else in the future!
2445 * We manually set the pseudo stack pointer in genReceive. - dw
2447 if(!GpsuedoStkPtr && _G.useWreg) {
2448 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2450 /* The last byte in the assignment is in W */
2451 if(areg <= GpsuedoStkPtr) {
2453 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2455 // debugf("receive from WREG\n", 0);
2457 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2460 _G.stack_lat = AOP_SIZE(oper)-1;
2465 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2466 // debugf("receive from STACK\n", 0);
2473 /*-----------------------------------------------------------------*/
2474 /* genIpush - generate code for pushing this gets a little complex */
2475 /*-----------------------------------------------------------------*/
2476 static void genIpush (iCode *ic)
2478 // int size, offset=0;
2481 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2484 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2486 /* send to stack as normal */
2487 addSet(&_G.sendSet,ic);
2488 // addSetHead(&_G.sendSet,ic);
2489 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2494 int size, offset = 0 ;
2498 /* if this is not a parm push : ie. it is spill push
2499 and spill push is always done on the local stack */
2500 if (!ic->parmPush) {
2502 /* and the item is spilt then do nothing */
2503 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2506 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2507 size = AOP_SIZE(IC_LEFT(ic));
2508 /* push it on the stack */
2510 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2515 pic16_emitcode("push","%s",l);
2520 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2524 /*-----------------------------------------------------------------*/
2525 /* genIpop - recover the registers: can happen only for spilling */
2526 /*-----------------------------------------------------------------*/
2527 static void genIpop (iCode *ic)
2530 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2535 /* if the temp was not pushed then */
2536 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2539 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2540 size = AOP_SIZE(IC_LEFT(ic));
2543 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2546 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2550 static int wparamCmp(void *p1, void *p2)
2552 return (!strcmp((char *)p1, (char *)p2));
2555 int inWparamList(char *s)
2557 return isinSetWith(wparamList, s, wparamCmp);
2561 /*-----------------------------------------------------------------*/
2562 /* genCall - generates a call statement */
2563 /*-----------------------------------------------------------------*/
2564 static void genCall (iCode *ic)
2574 ftype = OP_SYM_TYPE(IC_LEFT(ic));
2575 /* if caller saves & we have not saved then */
2576 // if (!ic->regsSaved)
2577 // saveRegisters(ic);
2579 /* initialise stackParms for IPUSH pushes */
2580 // stackParms = psuedoStkPtr;
2581 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2582 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2583 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2586 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2589 /* if send set is not empty the assign */
2592 int psuedoStkPtr=-1;
2593 int firstTimeThruLoop = 1;
2596 /* reverse sendSet if function is not reentrant */
2597 if(!IFFUNC_ISREENT(ftype))
2598 _G.sendSet = reverseSet(_G.sendSet);
2600 /* First figure how many parameters are getting passed */
2604 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2608 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2609 size = AOP_SIZE(IC_LEFT(sic));
2613 /* pass the last byte through WREG */
2617 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2618 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2619 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2621 if(!firstTimeThruLoop) {
2622 /* If this is not the first time we've been through the loop
2623 * then we need to save the parameter in a temporary
2624 * register. The last byte of the last parameter is
2628 // --psuedoStkPtr; // sanity check
2632 firstTimeThruLoop=0;
2634 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2639 /* all arguments are passed via stack */
2643 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2644 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2645 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2647 // pushaop(AOP(IC_LEFT(sic)), size);
2648 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2655 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2659 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2660 pushw(); /* save last parameter to stack if functions has varargs */
2664 } else use_wreg = 0;
2666 _G.stackRegSet = _G.sendSet;
2671 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2675 /* if we need to assign a result value */
2676 if ((IS_ITEMP(IC_RESULT(ic))
2677 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2678 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2679 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2682 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2685 /* Must not assign an 8-bit result to a 16-bit variable;
2686 * this would use (used...) the uninitialized PRODL! */
2687 /* FIXME: Need a proper way to obtain size of function result type,
2688 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2689 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2691 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2692 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2694 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2697 if(!stackParms && ic->parmBytes) {
2698 stackParms = ic->parmBytes;
2701 stackParms -= use_wreg;
2704 if(stackParms == 1) {
2705 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
2707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2708 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2710 if(STACK_MODEL_LARGE) {
2712 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2717 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2720 /* adjust the stack for parameters if required */
2721 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2724 /* if register bank was saved then pop them */
2726 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2728 /* if we hade saved some registers then unsave them */
2729 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2730 unsaveRegisters (ic);
2736 /*-----------------------------------------------------------------*/
2737 /* genPcall - generates a call by pointer statement */
2738 /* new version, created from genCall - HJD */
2739 /*-----------------------------------------------------------------*/
2740 static void genPcall (iCode *ic)
2744 symbol *retlbl = newiTempLabel(NULL);
2745 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2749 fntype = operandType( IC_LEFT(ic) )->next;
2751 /* if send set is not empty the assign */
2754 int psuedoStkPtr=-1;
2756 /* reverse sendSet if function is not reentrant */
2757 if(!IFFUNC_ISREENT(fntype))
2758 _G.sendSet = reverseSet(_G.sendSet);
2762 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2765 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2766 size = AOP_SIZE(IC_LEFT(sic));
2769 /* all parameters are passed via stack, since WREG is clobbered
2770 * by the calling sequence */
2772 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2773 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2774 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2776 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2780 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2783 _G.stackRegSet = _G.sendSet;
2787 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2789 // push return address
2790 // push $ on return stack, then replace with retlbl
2792 /* Thanks to Thorsten Klose for pointing out that the following
2793 * snippet should be interrupt safe */
2794 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2795 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2797 pic16_emitpcodeNULLop(POC_PUSH);
2799 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2800 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2801 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2802 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2803 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2804 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2807 /* restore interrupt control register */
2808 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2809 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2811 /* make the call by writing the pointer into pc */
2812 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2813 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2815 // note: MOVFF to PCL not allowed
2816 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2817 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2820 /* return address is here: (X) */
2821 pic16_emitpLabelFORCE(retlbl->key);
2823 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2826 /* if we need assign a result value */
2827 if ((IS_ITEMP(IC_RESULT(ic))
2828 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2829 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2830 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2833 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2836 /* FIXME: Need proper way to obtain the function result's type.
2837 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2838 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2840 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2841 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2843 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2846 // stackParms -= use_wreg;
2849 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2850 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2851 if(STACK_MODEL_LARGE) {
2853 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2858 /*-----------------------------------------------------------------*/
2859 /* resultRemat - result is rematerializable */
2860 /*-----------------------------------------------------------------*/
2861 static int resultRemat (iCode *ic)
2863 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2864 if (SKIP_IC(ic) || ic->op == IFX)
2867 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2868 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2869 if (sym->remat && !POINTER_SET(ic))
2877 /*-----------------------------------------------------------------*/
2878 /* inExcludeList - return 1 if the string is in exclude Reg list */
2879 /*-----------------------------------------------------------------*/
2880 static bool inExcludeList(char *s)
2882 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2885 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2886 if (options.excludeRegs[i] &&
2887 STRCASECMP(options.excludeRegs[i],"none") == 0)
2890 for ( i = 0 ; options.excludeRegs[i]; i++) {
2891 if (options.excludeRegs[i] &&
2892 STRCASECMP(s,options.excludeRegs[i]) == 0)
2899 /*-----------------------------------------------------------------*/
2900 /* genFunction - generated code for function entry */
2901 /*-----------------------------------------------------------------*/
2902 static void genFunction (iCode *ic)
2908 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2910 pic16_labelOffset += (max_key+4);
2915 ftype = operandType(IC_LEFT(ic));
2916 sym = OP_SYMBOL(IC_LEFT(ic));
2918 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2919 /* create an absolute section at the interrupt vector:
2920 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2925 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2927 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2928 sprintf(asymname, "ivec_%s", sym->name);
2930 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2932 /* when an interrupt is declared as naked, do not emit the special
2933 * wrapper segment at vector address. The user should take care for
2934 * this instead. -- VR */
2936 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2937 asym = newSymbol(asymname, 0);
2938 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2939 pic16_addpBlock( apb );
2941 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2942 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2943 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2944 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2945 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2947 /* mark the end of this tiny function */
2948 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2950 sprintf(asymname, "%s", sym->rname);
2956 abSym = Safe_calloc(1, sizeof(absSym));
2957 strcpy(abSym->name, asymname);
2959 switch( FUNC_INTNO(sym->type) ) {
2960 case 0: abSym->address = 0x000000; break;
2961 case 1: abSym->address = 0x000008; break;
2962 case 2: abSym->address = 0x000018; break;
2965 // fprintf(stderr, "no interrupt number is given\n");
2966 abSym->address = -1; break;
2969 /* relocate interrupt vectors if needed */
2970 if(abSym->address != -1)
2971 abSym->address += pic16_options.ivt_loc;
2973 addSet(&absSymSet, abSym);
2977 /* create the function header */
2978 pic16_emitcode(";","-----------------------------------------");
2979 pic16_emitcode(";"," function %s",sym->name);
2980 pic16_emitcode(";","-----------------------------------------");
2982 /* prevent this symbol from being emitted as 'extern' */
2983 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2985 pic16_emitcode("","%s:",sym->rname);
2986 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2991 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2992 if(!strcmp(ab->name, sym->rname)) {
2993 pic16_pBlockConvert2Absolute(pb);
2999 if(IFFUNC_ISNAKED(ftype)) {
3000 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3004 /* if critical function then turn interrupts off */
3005 if (IFFUNC_ISCRITICAL(ftype)) {
3006 //pic16_emitcode("clr","ea");
3009 currFunc = sym; /* update the currFunc symbol */
3010 _G.fregsUsed = sym->regsUsed;
3011 _G.sregsAlloc = newBitVect(128);
3014 /* if this is an interrupt service routine then
3015 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3016 if (IFFUNC_ISISR(sym->type)) {
3017 _G.usefastretfie = 1; /* use shadow registers by default */
3019 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3020 if(!FUNC_ISSHADOWREGS(sym->type)) {
3021 /* do not save WREG,STATUS,BSR for high priority interrupts
3022 * because they are stored in the hardware shadow registers already */
3023 _G.usefastretfie = 0;
3024 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3025 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3026 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3029 /* these should really be optimized somehow, because not all
3030 * interrupt handlers modify them */
3031 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3032 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3033 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3034 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3035 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3036 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3038 // pic16_pBlockConvert2ISR(pb);
3041 /* emit code to setup stack frame if user enabled,
3042 * and function is not main() */
3044 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3045 if(strcmp(sym->name, "main")) {
3047 || !options.ommitFramePtr
3049 || IFFUNC_ARGS(sym->type)
3050 || FUNC_HASSTACKPARM(sym->etype)
3052 /* setup the stack frame */
3053 if(STACK_MODEL_LARGE)
3054 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3055 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3057 if(STACK_MODEL_LARGE)
3058 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3059 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3063 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3066 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3068 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3069 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3071 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3074 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3075 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3082 /* if callee-save to be used for this function
3083 * then save the registers being used in this function */
3084 // if (IFFUNC_CALLEESAVES(sym->type))
3085 if(strcmp(sym->name, "main")) {
3088 /* if any registers used */
3089 if (sym->regsUsed) {
3090 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3092 if(!pic16_options.xinst) {
3093 /* save the registers used */
3094 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3095 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3096 if (bitVectBitValue(sym->regsUsed,i)) {
3098 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3100 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3103 if(!pic16_regWithIdx(i)->wasUsed) {
3104 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3105 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3106 pic16_regWithIdx(i)->wasUsed = 1;
3113 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3114 for(i=0;i<sym->regsUsed->size;i++) {
3115 if(bitVectBitValue(sym->regsUsed, i)) {
3120 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3123 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3128 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3129 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3132 /*-----------------------------------------------------------------*/
3133 /* genEndFunction - generates epilogue for functions */
3134 /*-----------------------------------------------------------------*/
3135 static void genEndFunction (iCode *ic)
3137 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3141 if(IFFUNC_ISNAKED(sym->type)) {
3142 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3148 /* add code for ISCRITICAL */
3149 if(IFFUNC_ISCRITICAL(sym->type)) {
3150 /* if critical function, turn on interrupts */
3152 /* TODO: add code here -- VR */
3155 // sym->regsUsed = _G.fregsUsed;
3157 /* now we need to restore the registers */
3158 /* if any registers used */
3160 /* first restore registers that might be used for stack access */
3161 if(_G.sregsAllocSet) {
3164 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3165 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3166 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3170 if (strcmp(sym->name, "main") && sym->regsUsed) {
3173 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3174 /* restore registers used */
3175 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3176 for ( i = sym->regsUsed->size; i >= 0; i--) {
3177 if (bitVectBitValue(sym->regsUsed,i)) {
3178 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3182 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3187 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3189 if (sym->stack == 1) {
3190 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3191 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3193 // we have to add more than one...
3194 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3195 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3196 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3198 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3199 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3200 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3204 if(strcmp(sym->name, "main")) {
3206 || !options.ommitFramePtr
3208 || IFFUNC_ARGS(sym->type)
3209 || FUNC_HASSTACKPARM(sym->etype)
3211 /* restore stack frame */
3212 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3213 if(STACK_MODEL_LARGE)
3214 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3220 if (IFFUNC_ISISR(sym->type)) {
3221 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3222 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3223 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3224 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3225 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3226 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3228 if(!FUNC_ISSHADOWREGS(sym->type)) {
3229 /* do not restore interrupt vector for WREG,STATUS,BSR
3230 * for high priority interrupt, see genFunction */
3231 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3232 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3233 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3235 // _G.interruptvector = 0; /* sanity check */
3238 /* if debug then send end of function */
3239 /* if (options.debug && currFunc) */
3241 debugFile->writeEndFunction (currFunc, ic, 1);
3244 if(_G.usefastretfie)
3245 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3247 pic16_emitpcodeNULLop(POC_RETFIE);
3249 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3251 _G.usefastretfie = 0;
3255 if (IFFUNC_ISCRITICAL(sym->type)) {
3256 pic16_emitcode("setb","ea");
3259 /* if debug then send end of function */
3261 debugFile->writeEndFunction (currFunc, ic, 1);
3264 /* insert code to restore stack frame, if user enabled it
3265 * and function is not main() */
3268 pic16_emitpcodeNULLop(POC_RETURN);
3270 /* Mark the end of a function */
3271 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3275 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3277 unsigned long lit=1;
3282 // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3283 if(AOP_TYPE(op) == AOP_LIT) {
3284 if(!IS_FLOAT(operandType( op ))) {
3285 lit = ulFromVal (AOP(op)->aopu.aop_lit);
3288 unsigned long lit_int;
3292 /* take care if literal is a float */
3293 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3298 if (AOP_TYPE(op) == AOP_LIT) {
3299 /* FIXME: broken for
3300 * char __at(0x456) foo;
3302 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3303 pic16_movLit2f(dest, (lit >> (8ul*offset)));
3304 } else if (AOP_TYPE(op) == AOP_PCODE
3305 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3306 /* char *s= "aaa"; return s; */
3307 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3308 * that the generic pointer is interpreted correctly
3309 * as referring to __code space, but this is fragile! */
3310 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3311 /* XXX: should check that dest != WREG */
3312 pic16_emitpcode(POC_MOVWF, dest);
3314 if(dest->type == PO_WREG && (offset == 0)) {
3315 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3318 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3322 /*-----------------------------------------------------------------*/
3323 /* genRet - generate code for return statement */
3324 /*-----------------------------------------------------------------*/
3325 static void genRet (iCode *ic)
3331 /* if we have no return value then
3332 * just generate the "ret" */
3337 /* we have something to return then
3338 * move the return value into place */
3339 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3340 size = AOP_SIZE(IC_LEFT(ic));
3344 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3347 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3350 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3352 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3355 /* >32-bits, setup stack and FSR0 */
3357 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3358 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3360 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3362 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3367 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3368 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3370 if(STACK_MODEL_LARGE) {
3371 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3372 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3374 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3378 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3381 /* generate a jump to the return label
3382 * if the next is not the return statement */
3383 if (!(ic->next && ic->next->op == LABEL
3384 && IC_LABEL(ic->next) == returnLabel)) {
3386 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3387 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3391 /*-----------------------------------------------------------------*/
3392 /* genLabel - generates a label */
3393 /*-----------------------------------------------------------------*/
3394 static void genLabel (iCode *ic)
3398 /* special case never generate */
3399 if (IC_LABEL(ic) == entryLabel)
3402 pic16_emitpLabel(IC_LABEL(ic)->key);
3403 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3406 /*-----------------------------------------------------------------*/
3407 /* genGoto - generates a goto */
3408 /*-----------------------------------------------------------------*/
3410 static void genGoto (iCode *ic)
3413 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3414 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3418 /*-----------------------------------------------------------------*/
3419 /* genMultbits :- multiplication of bits */
3420 /*-----------------------------------------------------------------*/
3421 static void genMultbits (operand *left,
3427 if(!pic16_sameRegs(AOP(result),AOP(right)))
3428 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3430 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3431 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3432 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3437 /*-----------------------------------------------------------------*/
3438 /* genMultOneByte : 8 bit multiplication & division */
3439 /*-----------------------------------------------------------------*/
3440 static void genMultOneByte (operand *left,
3446 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3447 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3449 /* (if two literals, the value is computed before) */
3450 /* if one literal, literal on the right */
3451 if (AOP_TYPE(left) == AOP_LIT){
3457 /* size is already checked in genMult == 1 */
3458 // size = AOP_SIZE(result);
3460 if (AOP_TYPE(right) == AOP_LIT){
3461 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3462 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3463 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3464 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3466 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3467 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3468 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3469 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3472 pic16_genMult8X8_n (left, right,result);
3476 /*-----------------------------------------------------------------*/
3477 /* genMultOneWord : 16 bit multiplication */
3478 /*-----------------------------------------------------------------*/
3479 static void genMultOneWord (operand *left,
3484 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3485 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3487 /* (if two literals, the value is computed before)
3488 * if one literal, literal on the right */
3489 if (AOP_TYPE(left) == AOP_LIT){
3495 /* size is checked already == 2 */
3496 // size = AOP_SIZE(result);
3498 if (AOP_TYPE(right) == AOP_LIT) {
3499 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3500 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3501 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3502 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3504 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3505 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3506 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3507 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3510 pic16_genMult16X16_16(left, right,result);
3515 /*-----------------------------------------------------------------*/
3516 /* genMultOneLong : 32 bit multiplication */
3517 /*-----------------------------------------------------------------*/
3518 static void genMultOneLong (operand *left,
3523 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3524 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3526 /* (if two literals, the value is computed before)
3527 * if one literal, literal on the right */
3528 if (AOP_TYPE(left) == AOP_LIT){
3534 /* size is checked already == 4 */
3535 // size = AOP_SIZE(result);
3537 if (AOP_TYPE(right) == AOP_LIT) {
3538 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3539 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3540 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3541 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3543 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3544 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3545 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3546 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3549 pic16_genMult32X32_32(left, right,result);
3555 /*-----------------------------------------------------------------*/
3556 /* genMult - generates code for multiplication */
3557 /*-----------------------------------------------------------------*/
3558 static void genMult (iCode *ic)
3560 operand *left = IC_LEFT(ic);
3561 operand *right = IC_RIGHT(ic);
3562 operand *result= IC_RESULT(ic);
3565 /* assign the amsops */
3566 pic16_aopOp (left,ic,FALSE);
3567 pic16_aopOp (right,ic,FALSE);
3568 pic16_aopOp (result,ic,TRUE);
3570 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3572 /* special cases first *
3574 if (AOP_TYPE(left) == AOP_CRY
3575 && AOP_TYPE(right)== AOP_CRY) {
3576 genMultbits(left,right,result);
3580 /* if both are of size == 1 */
3581 if(AOP_SIZE(left) == 1
3582 && AOP_SIZE(right) == 1) {
3583 genMultOneByte(left,right,result);
3588 /* if both are of size == 2 */
3589 if(AOP_SIZE(left) == 2
3590 && AOP_SIZE(right) == 2) {
3591 genMultOneWord(left, right, result);
3595 /* if both are of size == 4 */
3596 if(AOP_SIZE(left) == 4
3597 && AOP_SIZE(right) == 4) {
3598 genMultOneLong(left, right, result);
3603 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3604 assert( !"Multiplication should have been transformed into function call!" );
3606 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3609 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3610 /* should have been converted to function call */
3614 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3615 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3616 pic16_freeAsmop(result,NULL,ic,TRUE);
3620 /*-----------------------------------------------------------------*/
3621 /* genDivbits :- division of bits */
3622 /*-----------------------------------------------------------------*/
3623 static void genDivbits (operand *left,
3630 /* the result must be bit */
3631 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3632 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3636 pic16_emitcode("div","ab");
3637 pic16_emitcode("rrc","a");
3638 pic16_aopPut(AOP(result),"c",0);
3641 /*-----------------------------------------------------------------*/
3642 /* genDivOneByte : 8 bit division */
3643 /*-----------------------------------------------------------------*/
3644 static void genDivOneByte (operand *left,
3648 sym_link *opetype = operandType(result);
3653 /* result = divident / divisor
3654 * - divident may be a register or a literal,
3655 * - divisor may be a register or a literal,
3656 * so there are 3 cases (literal / literal is optimized
3657 * by the front-end) to handle.
3658 * In addition we must handle signed and unsigned, which
3659 * result in 6 final different cases -- VR */
3663 size = AOP_SIZE(result) - 1;
3665 /* signed or unsigned */
3666 if (SPEC_USIGN(opetype)) {
3667 pCodeOp *pct1, /* count */
3670 symbol *label1, *label2, *label3;;
3673 /* unsigned is easy */
3675 pct1 = pic16_popGetTempReg(1);
3676 pct2 = pic16_popGetTempReg(1);
3677 pct3 = pic16_popGetTempReg(1);
3679 label1 = newiTempLabel(NULL);
3680 label2 = newiTempLabel(NULL);
3681 label3 = newiTempLabel(NULL);
3683 /* the following algorithm is extracted from divuint.c */
3685 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3686 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3688 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3690 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3692 pic16_emitpLabel(label1->key);
3695 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3699 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3703 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3705 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3706 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3708 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3709 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3710 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3712 pic16_emitpLabel( label3->key );
3713 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3714 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3718 pic16_emitpLabel(label2->key);
3719 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3720 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3721 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3723 /* result is in wreg */
3724 if(AOP_TYPE(result) != AOP_ACC)
3725 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3727 pic16_popReleaseTempReg( pct3, 1);
3728 pic16_popReleaseTempReg( pct2, 1);
3729 pic16_popReleaseTempReg( pct1, 1);
3734 /* signed is a little bit more difficult */
3736 /* save the signs of the operands */
3737 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3739 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3740 pic16_emitcode("push","acc"); /* save it on the stack */
3742 /* now sign adjust for both left & right */
3743 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3745 lbl = newiTempLabel(NULL);
3746 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3747 pic16_emitcode("cpl","a");
3748 pic16_emitcode("inc","a");
3749 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3750 pic16_emitcode("mov","b,a");
3752 /* sign adjust left side */
3753 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3756 lbl = newiTempLabel(NULL);
3757 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3758 pic16_emitcode("cpl","a");
3759 pic16_emitcode("inc","a");
3760 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3762 /* now the division */
3763 pic16_emitcode("div","ab");
3764 /* we are interested in the lower order
3766 pic16_emitcode("mov","b,a");
3767 lbl = newiTempLabel(NULL);
3768 pic16_emitcode("pop","acc");
3769 /* if there was an over flow we don't
3770 adjust the sign of the result */
3771 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3772 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3774 pic16_emitcode("clr","a");
3775 pic16_emitcode("subb","a,b");
3776 pic16_emitcode("mov","b,a");
3777 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3779 /* now we are done */
3780 pic16_aopPut(AOP(result),"b",0);
3782 pic16_emitcode("mov","c,b.7");
3783 pic16_emitcode("subb","a,acc");
3786 pic16_aopPut(AOP(result),"a",offset++);
3791 /*-----------------------------------------------------------------*/
3792 /* genDiv - generates code for division */
3793 /*-----------------------------------------------------------------*/
3794 static void genDiv (iCode *ic)
3796 operand *left = IC_LEFT(ic);
3797 operand *right = IC_RIGHT(ic);
3798 operand *result= IC_RESULT(ic);
3800 int leftVal = 0, rightVal = 0;
3802 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3805 /* Division is a very lengthy algorithm, so it is better
3806 * to call support routines than inlining algorithm.
3807 * Division functions written here just in case someone
3808 * wants to inline and not use the support libraries -- VR */
3812 /* assign the amsops */
3813 pic16_aopOp (left,ic,FALSE);
3814 pic16_aopOp (right,ic,FALSE);
3815 pic16_aopOp (result,ic,TRUE);
3819 else if (ic->op == '%')
3822 assert( !"invalid operation requested in genDivMod" );
3824 /* get literal values */
3825 if (IS_VALOP(left)) {
3826 leftVal = (int) ulFromVal ( OP_VALUE(left) );
3827 assert( leftVal >= -128 && leftVal < 256 );
3828 if (leftVal < 0) { signedLits++; }
3830 if (IS_VALOP(right)) {
3831 rightVal = (int) ulFromVal ( OP_VALUE(right) );
3832 assert( rightVal >= -128 && rightVal < 256 );
3833 if (rightVal < 0) { signedLits++; }
3836 /* We should only come here to convert all
3837 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3838 * with exactly one operand being s8_t into
3839 * u8_t x u8_t -> u8_t. All other cases should have been
3840 * turned into calls to support routines beforehand... */
3841 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3842 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3844 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3845 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3847 /* Both operands are signed or negative, use _divschar
3848 * instead of _divuchar */
3849 pushaop(AOP(right), 0);
3850 pushaop(AOP(left), 0);
3852 /* call _divschar */
3853 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3857 sym = newSymbol( functions[op][0], 0 );
3859 strcpy(sym->rname, functions[op][0]);
3860 checkAddSym(&externs, sym);
3864 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3865 if (AOP_SIZE(result) > 1)
3867 pic16_emitpcode(POC_MOVFF,
3868 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3869 pic16_popGet(AOP(result), 1)));
3871 pic16_addSign(result, 2, 1);
3874 /* clean up stack */
3875 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3876 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3881 /* push right operand */
3882 if (IS_VALOP(right)) {
3884 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3887 pushaop(AOP(right), 0);
3889 } else if (!IS_UNSIGNED(operandType(right))) {
3890 pic16_mov2w(AOP(right), 0);
3891 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3892 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3893 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3896 pushaop(AOP(right), 0);
3899 /* push left operand */
3900 if (IS_VALOP(left)) {
3902 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3905 pushaop(AOP(left), 0);
3907 } else if (!IS_UNSIGNED(operandType(left))) {
3908 pic16_mov2w(AOP(left),0);
3909 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3910 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3911 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3914 pushaop(AOP(left), 0);
3917 /* call _divuchar */
3918 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3922 sym = newSymbol( functions[op][1], 0 );
3924 strcpy(sym->rname, functions[op][1]);
3925 checkAddSym(&externs, sym);
3928 /* Revert negation(s) from above.
3929 * This is inefficient: if both operands are negative, this
3930 * should not touch WREG. However, determining that exactly
3931 * one operand was negated costs at least 3 instructions,
3932 * so there is nothing to be gained here, is there?
3934 * I negate WREG because either operand might share registers with
3935 * result, so assigning first might destroy an operand. */
3937 /* For the modulus operator, (a/b)*b == a shall hold.
3938 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3939 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
3940 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
3941 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
3942 * Only invert the result if the left operand is negative (sigh).
3944 if (AOP_SIZE(result) <= 1 || !negated)
3948 if (IS_VALOP(right)) {
3950 /* we negated this operand above */
3951 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3953 } else if (!IS_UNSIGNED(operandType(right))) {
3954 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3955 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3959 if (IS_VALOP(left)) {
3961 /* we negated this operand above */
3962 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3964 } else if (!IS_UNSIGNED(operandType(left))) {
3965 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3966 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3969 /* Move result to destination. */
3970 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3972 /* Zero-extend: no operand was signed (or result is just a byte). */
3973 pic16_addSign(result, 1, 0);
3975 assert( AOP_SIZE(result) > 1 );
3976 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3979 if (IS_VALOP(right)) {
3981 /* we negated this operand above */
3982 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3984 } else if (!IS_UNSIGNED(operandType(right))) {
3985 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3986 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3990 if (IS_VALOP(left)) {
3992 /* we negated this operand above */
3993 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3995 } else if (!IS_UNSIGNED(operandType(left))) {
3996 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3997 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4000 /* Move result to destination. */
4001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4003 /* Negate result if required. */
4004 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4005 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4008 pic16_addSign(result, 2, 1);
4011 /* clean up stack */
4012 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4013 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4018 /* special cases first */
4020 if (AOP_TYPE(left) == AOP_CRY &&
4021 AOP_TYPE(right)== AOP_CRY) {
4022 genDivbits(left,right,result);
4026 /* if both are of size == 1 */
4027 if (AOP_SIZE(left) == 1 &&
4028 AOP_SIZE(right) == 1 ) {
4029 genDivOneByte(left,right,result);
4034 /* should have been converted to function call */
4037 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4038 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4039 pic16_freeAsmop(result,NULL,ic,TRUE);
4043 /*-----------------------------------------------------------------*/
4044 /* genModbits :- modulus of bits */
4045 /*-----------------------------------------------------------------*/
4046 static void genModbits (operand *left,
4054 werror(W_POSSBUG2, __FILE__, __LINE__);
4055 /* the result must be bit */
4056 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4057 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4061 pic16_emitcode("div","ab");
4062 pic16_emitcode("mov","a,b");
4063 pic16_emitcode("rrc","a");
4064 pic16_aopPut(AOP(result),"c",0);
4067 /*-----------------------------------------------------------------*/
4068 /* genModOneByte : 8 bit modulus */
4069 /*-----------------------------------------------------------------*/
4070 static void genModOneByte (operand *left,
4074 sym_link *opetype = operandType(result);
4079 werror(W_POSSBUG2, __FILE__, __LINE__);
4081 /* signed or unsigned */
4082 if (SPEC_USIGN(opetype)) {
4083 /* unsigned is easy */
4084 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4085 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4087 pic16_emitcode("div","ab");
4088 pic16_aopPut(AOP(result),"b",0);
4092 /* signed is a little bit more difficult */
4094 /* save the signs of the operands */
4095 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4098 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4099 pic16_emitcode("push","acc"); /* save it on the stack */
4101 /* now sign adjust for both left & right */
4102 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4105 lbl = newiTempLabel(NULL);
4106 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4107 pic16_emitcode("cpl","a");
4108 pic16_emitcode("inc","a");
4109 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4110 pic16_emitcode("mov","b,a");
4112 /* sign adjust left side */
4113 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4116 lbl = newiTempLabel(NULL);
4117 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4118 pic16_emitcode("cpl","a");
4119 pic16_emitcode("inc","a");
4120 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4122 /* now the multiplication */
4123 pic16_emitcode("div","ab");
4124 /* we are interested in the lower order
4126 lbl = newiTempLabel(NULL);
4127 pic16_emitcode("pop","acc");
4128 /* if there was an over flow we don't
4129 adjust the sign of the result */
4130 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4131 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4133 pic16_emitcode("clr","a");
4134 pic16_emitcode("subb","a,b");
4135 pic16_emitcode("mov","b,a");
4136 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4138 /* now we are done */
4139 pic16_aopPut(AOP(result),"b",0);
4144 /*-----------------------------------------------------------------*/
4145 /* genMod - generates code for division */
4146 /*-----------------------------------------------------------------*/
4147 static void genMod (iCode *ic)
4149 /* Task deferred to genDiv */
4152 operand *left = IC_LEFT(ic);
4153 operand *right = IC_RIGHT(ic);
4154 operand *result= IC_RESULT(ic);
4158 /* assign the amsops */
4159 pic16_aopOp (left,ic,FALSE);
4160 pic16_aopOp (right,ic,FALSE);
4161 pic16_aopOp (result,ic,TRUE);
4163 /* special cases first */
4165 if (AOP_TYPE(left) == AOP_CRY &&
4166 AOP_TYPE(right)== AOP_CRY) {
4167 genModbits(left,right,result);
4171 /* if both are of size == 1 */
4172 if (AOP_SIZE(left) == 1 &&
4173 AOP_SIZE(right) == 1 ) {
4174 genModOneByte(left,right,result);
4178 /* should have been converted to function call */
4182 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4183 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184 pic16_freeAsmop(result,NULL,ic,TRUE);
4188 /*-----------------------------------------------------------------*/
4189 /* genIfxJump :- will create a jump depending on the ifx */
4190 /*-----------------------------------------------------------------*/
4192 note: May need to add parameter to indicate when a variable is in bit space.
4194 static void genIfxJump (iCode *ic, char *jval)
4198 /* if true label then we jump if condition
4200 if ( IC_TRUE(ic) ) {
4202 if(strcmp(jval,"a") == 0)
4204 else if (strcmp(jval,"c") == 0)
4207 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4208 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4211 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4212 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4216 /* false label is present */
4217 if(strcmp(jval,"a") == 0)
4219 else if (strcmp(jval,"c") == 0)
4222 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4223 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4226 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4227 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4232 /* mark the icode as generated */
4236 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4240 /* if true label then we jump if condition
4242 if ( IC_TRUE(ic) ) {
4243 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4244 pic16_emitpcode(POC_BTFSC, jop);
4246 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4247 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4250 /* false label is present */
4251 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4252 pic16_emitpcode(POC_BTFSS, jop);
4254 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4255 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4259 /* mark the icode as generated */
4266 /*-----------------------------------------------------------------*/
4268 /*-----------------------------------------------------------------*/
4269 static void genSkip(iCode *ifx,int status_bit)
4271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4275 if ( IC_TRUE(ifx) ) {
4276 switch(status_bit) {
4291 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4292 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4296 switch(status_bit) {
4310 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4311 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4318 /*-----------------------------------------------------------------*/
4320 /*-----------------------------------------------------------------*/
4321 static void genSkipc(resolvedIfx *rifx)
4323 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4333 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4334 rifx->generated = 1;
4337 /*-----------------------------------------------------------------*/
4338 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4339 /* aop (if it's NOT a literal) or from lit (if */
4340 /* aop is a literal) */
4341 /*-----------------------------------------------------------------*/
4342 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4343 if (aop->type == AOP_LIT) {
4344 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4346 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4350 /*-----------------------------------------------------------------*/
4351 /* genCmp :- greater or less than comparison */
4352 /*-----------------------------------------------------------------*/
4354 /* genCmp performs a left < right comparison, stores
4355 * the outcome in result (if != NULL) and generates
4356 * control flow code for the ifx (if != NULL).
4358 * This version leaves in sequences like
4359 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4360 * which should be optmized by the peephole
4361 * optimizer - RN 2005-01-01 */
4362 static void genCmp (operand *left,operand *right,
4363 operand *result, iCode *ifx, int sign)
4376 assert (left && right);
4377 assert (AOP_SIZE(left) == AOP_SIZE(right));
4379 size = AOP_SIZE(right) - 1;
4380 mask = (0x100UL << (size*8)) - 1;
4381 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4386 resolveIfx (&rIfx, ifx);
4388 /* handle for special cases */
4389 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4392 /**********************************************************************
4393 * handle bits - bit compares are promoted to int compares seemingly! *
4394 **********************************************************************/
4396 // THIS IS COMPLETELY UNTESTED!
4397 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4398 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4399 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4400 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4403 // 1 < {0,1} is false --> clear C by skipping the next instruction
4404 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4405 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4406 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4407 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4408 emitCLRC; // only skipped for left=0 && right=1
4410 goto correct_result_in_carry;
4414 /*************************************************
4415 * make sure that left is register (or the like) *
4416 *************************************************/
4417 if (!isAOP_REGlike(left)) {
4418 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4419 assert (isAOP_LIT(left));
4420 assert (isAOP_REGlike(right));
4421 // swap left and right
4422 // left < right <==> right > left <==> (right >= left + 1)
4423 lit = ulFromVal (AOP(left)->aopu.aop_lit);
4425 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4426 // MAXVALUE < right? always false
4427 if (performedLt) emitCLRC; else emitSETC;
4428 goto correct_result_in_carry;
4431 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4432 // that's why we handled it above.
4439 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4440 } else if (isAOP_LIT(right)) {
4441 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4444 assert (isAOP_REGlike(left)); // left must be register or the like
4445 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4447 /*************************************************
4448 * special cases go here *
4449 *************************************************/
4451 if (isAOP_LIT(right)) {
4453 // unsigned comparison to a literal
4454 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4456 // unsigned left < 0? always false
4457 if (performedLt) emitCLRC; else emitSETC;
4458 goto correct_result_in_carry;
4461 // signed comparison to a literal
4462 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4463 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4464 // signed left < 0x80000000? always false
4465 if (performedLt) emitCLRC; else emitSETC;
4466 goto correct_result_in_carry;
4467 } else if (lit == 0) {
4468 // compare left < 0; set CARRY if SIGNBIT(left) is set
4469 if (performedLt) emitSETC; else emitCLRC;
4470 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4471 if (performedLt) emitCLRC; else emitSETC;
4472 goto correct_result_in_carry;
4475 } // right is literal
4477 /*************************************************
4478 * perform a general case comparison *
4479 * make sure we get CARRY==1 <==> left >= right *
4480 *************************************************/
4481 // compare most significant bytes
4482 //DEBUGpc ("comparing bytes at offset %d", size);
4484 // unsigned comparison
4485 mov2w_regOrLit (AOP(right), lit, size);
4486 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4488 // signed comparison
4489 // (add 2^n to both operands then perform an unsigned comparison)
4490 if (isAOP_LIT(right)) {
4491 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4492 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4494 if (litbyte == 0x80) {
4495 // left >= 0x80 -- always true, but more bytes to come
4496 pic16_mov2w (AOP(left), size);
4497 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4500 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4501 pic16_mov2w (AOP(left), size);
4502 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4503 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4506 /* using PRODL as a temporary register here */
4507 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4508 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4509 pic16_mov2w (AOP(left), size);
4510 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4511 pic16_emitpcode (POC_MOVWF, pctemp);
4512 pic16_mov2w (AOP(right), size);
4513 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4514 pic16_emitpcode (POC_SUBFW, pctemp);
4515 //pic16_popReleaseTempReg(pctemp, 1);
4519 // compare remaining bytes (treat as unsigned case from above)
4520 templbl = newiTempLabel ( NULL );
4523 //DEBUGpc ("comparing bytes at offset %d", offs);
4524 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4525 mov2w_regOrLit (AOP(right), lit, offs);
4526 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4528 pic16_emitpLabel (templbl->key);
4529 goto result_in_carry;
4533 /****************************************************
4534 * now CARRY contains the result of the comparison: *
4535 * SUBWF sets CARRY iff *
4536 * F-W >= 0 <==> F >= W <==> !(F < W) *
4537 * (F=left, W=right) *
4538 ****************************************************/
4541 if (result && AOP_TYPE(result) != AOP_CRY) {
4542 // value will be stored
4545 // value wil only be used in the following genSkipc()
4546 rIfx.condition ^= 1;
4550 correct_result_in_carry:
4552 // assign result to variable (if neccessary)
4553 if (result && AOP_TYPE(result) != AOP_CRY) {
4554 //DEBUGpc ("assign result");
4555 size = AOP_SIZE(result);
4557 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4559 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4562 // perform conditional jump
4564 //DEBUGpc ("generate control flow");
4570 /*-----------------------------------------------------------------*/
4571 /* genCmpGt :- greater than comparison */
4572 /*-----------------------------------------------------------------*/
4573 static void genCmpGt (iCode *ic, iCode *ifx)
4575 operand *left, *right, *result;
4576 sym_link *letype , *retype;
4582 right= IC_RIGHT(ic);
4583 result = IC_RESULT(ic);
4585 letype = getSpec(operandType(left));
4586 retype =getSpec(operandType(right));
4587 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4588 /* assign the amsops */
4589 pic16_aopOp (left,ic,FALSE);
4590 pic16_aopOp (right,ic,FALSE);
4591 pic16_aopOp (result,ic,TRUE);
4593 genCmp(right, left, result, ifx, sign);
4595 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4596 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4597 pic16_freeAsmop(result,NULL,ic,TRUE);
4600 /*-----------------------------------------------------------------*/
4601 /* genCmpLt - less than comparisons */
4602 /*-----------------------------------------------------------------*/
4603 static void genCmpLt (iCode *ic, iCode *ifx)
4605 operand *left, *right, *result;
4606 sym_link *letype , *retype;
4612 right= IC_RIGHT(ic);
4613 result = IC_RESULT(ic);
4615 letype = getSpec(operandType(left));
4616 retype =getSpec(operandType(right));
4617 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4619 /* assign the amsops */
4620 pic16_aopOp (left,ic,FALSE);
4621 pic16_aopOp (right,ic,FALSE);
4622 pic16_aopOp (result,ic,TRUE);
4624 genCmp(left, right, result, ifx, sign);
4626 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4627 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628 pic16_freeAsmop(result,NULL,ic,TRUE);
4631 /*-----------------------------------------------------------------*/
4632 /* pic16_isLitOp - check if operand has to be treated as literal */
4633 /*-----------------------------------------------------------------*/
4634 bool pic16_isLitOp(operand *op)
4636 return ((AOP_TYPE(op) == AOP_LIT)
4637 || ( (AOP_TYPE(op) == AOP_PCODE)
4638 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4639 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4642 /*-----------------------------------------------------------------*/
4643 /* pic16_isLitAop - check if operand has to be treated as literal */
4644 /*-----------------------------------------------------------------*/
4645 bool pic16_isLitAop(asmop *aop)
4647 return ((aop->type == AOP_LIT)
4648 || ( (aop->type == AOP_PCODE)
4649 && ( (aop->aopu.pcop->type == PO_LITERAL)
4650 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4655 /*-----------------------------------------------------------------*/
4656 /* genCmpEq - generates code for equal to */
4657 /*-----------------------------------------------------------------*/
4658 static void genCmpEq (iCode *ic, iCode *ifx)
4660 operand *left, *right, *result;
4661 symbol *falselbl = newiTempLabel(NULL);
4662 symbol *donelbl = newiTempLabel(NULL);
4664 int preserve_result = 0;
4665 int generate_result = 0;
4667 unsigned long lit = -1;
4671 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4672 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4673 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4675 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4677 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4679 werror(W_POSSBUG2, __FILE__, __LINE__);
4680 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4681 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4685 if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4687 operand *tmp = right ;
4692 if (AOP_TYPE(right) == AOP_LIT) {
4693 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4696 if ( regsInCommon(left, result) || regsInCommon(right, result) )
4697 preserve_result = 1;
4699 if(result && AOP_SIZE(result))
4700 generate_result = 1;
4702 if(generate_result && !preserve_result)
4704 for(i = 0; i < AOP_SIZE(result); i++)
4705 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4708 assert( AOP_SIZE(left) == AOP_SIZE(right) );
4709 for(i=0; i < AOP_SIZE(left); i++)
4711 if(AOP_TYPE(left) != AOP_ACC)
4713 if(pic16_isLitOp(left))
4714 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4716 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4718 if(pic16_isLitOp(right)) {
4719 if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4720 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4723 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4725 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4730 if(generate_result && preserve_result)
4732 for(i = 0; i < AOP_SIZE(result); i++)
4733 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4737 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4739 if(generate_result && preserve_result)
4740 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4742 if(ifx && IC_TRUE(ifx))
4743 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4745 if(ifx && IC_FALSE(ifx))
4746 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4748 pic16_emitpLabel(falselbl->key);
4752 if(ifx && IC_FALSE(ifx))
4753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4755 if(generate_result && preserve_result)
4757 for(i = 0; i < AOP_SIZE(result); i++)
4758 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4761 pic16_emitpLabel(donelbl->key);
4767 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4768 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4769 pic16_freeAsmop(result,NULL,ic,TRUE);
4775 // old version kept for reference
4777 /*-----------------------------------------------------------------*/
4778 /* genCmpEq - generates code for equal to */
4779 /*-----------------------------------------------------------------*/
4780 static void genCmpEq (iCode *ic, iCode *ifx)
4782 operand *left, *right, *result;
4783 unsigned long lit = 0L;
4785 symbol *falselbl = newiTempLabel(NULL);
4788 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4791 DEBUGpic16_emitcode ("; ifx is non-null","");
4793 DEBUGpic16_emitcode ("; ifx is null","");
4795 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4796 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4797 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4799 size = max(AOP_SIZE(left),AOP_SIZE(right));
4801 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4803 /* if literal, literal on the right or
4804 if the right is in a pointer register and left
4806 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4807 operand *tmp = right ;
4813 if(ifx && !AOP_SIZE(result)){
4815 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
4816 /* if they are both bit variables */
4817 if (AOP_TYPE(left) == AOP_CRY &&
4818 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4819 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
4820 if(AOP_TYPE(right) == AOP_LIT){
4821 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4823 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4824 pic16_emitcode("cpl","c");
4825 } else if(lit == 1L) {
4826 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4828 pic16_emitcode("clr","c");
4830 /* AOP_TYPE(right) == AOP_CRY */
4832 symbol *lbl = newiTempLabel(NULL);
4833 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4834 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4835 pic16_emitcode("cpl","c");
4836 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4838 /* if true label then we jump if condition
4840 tlbl = newiTempLabel(NULL);
4841 if ( IC_TRUE(ifx) ) {
4842 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4843 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4845 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4846 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4848 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4851 /* left and right are both bit variables, result is carry */
4854 resolveIfx(&rIfx,ifx);
4856 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4857 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4858 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4859 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4864 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
4866 /* They're not both bit variables. Is the right a literal? */
4867 if(AOP_TYPE(right) == AOP_LIT) {
4868 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4873 switch(lit & 0xff) {
4875 if ( IC_TRUE(ifx) ) {
4876 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4880 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4881 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4885 if ( IC_TRUE(ifx) ) {
4886 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4888 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4890 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4895 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4897 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4902 /* end of size == 1 */
4906 genc16bit2lit(left,lit,offset);
4909 /* end of size == 2 */
4914 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4915 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4916 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4917 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4920 /* search for patterns that can be optimized */
4922 genc16bit2lit(left,lit,0);
4926 emitSKPZ; // if hi word unequal
4928 emitSKPNZ; // if hi word equal
4930 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4931 genc16bit2lit(left,lit,2);
4934 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4935 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4939 pic16_emitpLabel(falselbl->key);
4948 } else if(AOP_TYPE(right) == AOP_CRY ) {
4949 /* we know the left is not a bit, but that the right is */
4950 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4951 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4952 pic16_popGet(AOP(right),offset));
4953 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4955 /* if the two are equal, then W will be 0 and the Z bit is set
4956 * we could test Z now, or go ahead and check the high order bytes if
4957 * the variable we're comparing is larger than a byte. */
4960 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4962 if ( IC_TRUE(ifx) ) {
4964 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4965 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4968 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4969 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4973 /* They're both variables that are larger than bits */
4976 tlbl = newiTempLabel(NULL);
4979 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4980 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4982 if ( IC_TRUE(ifx) ) {
4986 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4988 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4989 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4993 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
4996 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4997 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5002 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5005 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5009 if(s>1 && IC_TRUE(ifx)) {
5010 pic16_emitpLabel(tlbl->key);
5011 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5015 /* mark the icode as generated */
5020 /* if they are both bit variables */
5021 if (AOP_TYPE(left) == AOP_CRY &&
5022 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5023 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5024 if(AOP_TYPE(right) == AOP_LIT){
5025 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5027 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5028 pic16_emitcode("cpl","c");
5029 } else if(lit == 1L) {
5030 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5032 pic16_emitcode("clr","c");
5034 /* AOP_TYPE(right) == AOP_CRY */
5036 symbol *lbl = newiTempLabel(NULL);
5037 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5038 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5039 pic16_emitcode("cpl","c");
5040 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5043 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5044 pic16_outBitC(result);
5048 genIfxJump (ifx,"c");
5051 /* if the result is used in an arithmetic operation
5052 then put the result in place */
5053 pic16_outBitC(result);
5056 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5057 gencjne(left,right,result,ifx);
5060 gencjne(left,right,newiTempLabel(NULL));
5062 if(IC_TRUE(ifx)->key)
5063 gencjne(left,right,IC_TRUE(ifx)->key);
5065 gencjne(left,right,IC_FALSE(ifx)->key);
5069 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5070 pic16_aopPut(AOP(result),"a",0);
5075 genIfxJump (ifx,"a");
5079 /* if the result is used in an arithmetic operation
5080 then put the result in place */
5082 if (AOP_TYPE(result) != AOP_CRY)
5083 pic16_outAcc(result);
5085 /* leave the result in acc */
5089 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5090 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5091 pic16_freeAsmop(result,NULL,ic,TRUE);
5095 /*-----------------------------------------------------------------*/
5096 /* ifxForOp - returns the icode containing the ifx for operand */
5097 /*-----------------------------------------------------------------*/
5098 static iCode *ifxForOp ( operand *op, iCode *ic )
5102 /* if true symbol then needs to be assigned */
5103 if (IS_TRUE_SYMOP(op))
5106 /* if this has register type condition and
5107 the next instruction is ifx with the same operand
5108 and live to of the operand is upto the ifx only then */
5110 && ic->next->op == IFX
5111 && IC_COND(ic->next)->key == op->key
5112 && OP_SYMBOL(op)->liveTo <= ic->next->seq
5114 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5120 ic->next->op == IFX &&
5121 IC_COND(ic->next)->key == op->key) {
5122 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5127 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5129 ic->next->op == IFX)
5130 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5133 ic->next->op == IFX &&
5134 IC_COND(ic->next)->key == op->key) {
5135 DEBUGpic16_emitcode ("; "," key is okay");
5136 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5137 OP_SYMBOL(op)->liveTo,
5142 /* the code below is completely untested
5143 * it just allows ulong2fs.c compile -- VR */
5146 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5147 __FILE__, __FUNCTION__, __LINE__);
5149 /* if this has register type condition and
5150 the next instruction is ifx with the same operand
5151 and live to of the operand is upto the ifx only then */
5153 ic->next->op == IFX &&
5154 IC_COND(ic->next)->key == op->key &&
5155 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5159 ic->next->op == IFX &&
5160 IC_COND(ic->next)->key == op->key) {
5161 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5165 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5166 __FILE__, __FUNCTION__, __LINE__);
5168 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
5173 /*-----------------------------------------------------------------*/
5174 /* genAndOp - for && operation */
5175 /*-----------------------------------------------------------------*/
5176 static void genAndOp (iCode *ic)
5178 operand *left,*right, *result;
5183 /* note here that && operations that are in an
5184 if statement are taken away by backPatchLabels
5185 only those used in arthmetic operations remain */
5186 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5187 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5188 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5190 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5192 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5193 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5194 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5196 /* if both are bit variables */
5197 /* if (AOP_TYPE(left) == AOP_CRY && */
5198 /* AOP_TYPE(right) == AOP_CRY ) { */
5199 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5200 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5201 /* pic16_outBitC(result); */
5203 /* tlbl = newiTempLabel(NULL); */
5204 /* pic16_toBoolean(left); */
5205 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5206 /* pic16_toBoolean(right); */
5207 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5208 /* pic16_outBitAcc(result); */
5211 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5212 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5213 pic16_freeAsmop(result,NULL,ic,TRUE);
5217 /*-----------------------------------------------------------------*/
5218 /* genOrOp - for || operation */
5219 /*-----------------------------------------------------------------*/
5222 modified this code, but it doesn't appear to ever get called
5225 static void genOrOp (iCode *ic)
5227 operand *left,*right, *result;
5232 /* note here that || operations that are in an
5233 if statement are taken away by backPatchLabels
5234 only those used in arthmetic operations remain */
5235 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5236 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5237 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5239 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5241 /* if both are bit variables */
5242 if (AOP_TYPE(left) == AOP_CRY &&
5243 AOP_TYPE(right) == AOP_CRY ) {
5244 pic16_emitcode("clrc","");
5245 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5246 AOP(left)->aopu.aop_dir,
5247 AOP(left)->aopu.aop_dir);
5248 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5249 AOP(right)->aopu.aop_dir,
5250 AOP(right)->aopu.aop_dir);
5251 pic16_emitcode("setc","");
5254 tlbl = newiTempLabel(NULL);
5255 pic16_toBoolean(left);
5257 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5258 pic16_toBoolean(right);
5259 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5261 pic16_outBitAcc(result);
5264 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5265 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5266 pic16_freeAsmop(result,NULL,ic,TRUE);
5269 /*-----------------------------------------------------------------*/
5270 /* isLiteralBit - test if lit == 2^n */
5271 /*-----------------------------------------------------------------*/
5272 static int isLiteralBit(unsigned long lit)
5274 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5275 0x100L,0x200L,0x400L,0x800L,
5276 0x1000L,0x2000L,0x4000L,0x8000L,
5277 0x10000L,0x20000L,0x40000L,0x80000L,
5278 0x100000L,0x200000L,0x400000L,0x800000L,
5279 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5280 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5283 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5284 for(idx = 0; idx < 32; idx++)
5290 /*-----------------------------------------------------------------*/
5291 /* continueIfTrue - */
5292 /*-----------------------------------------------------------------*/
5293 static void continueIfTrue (iCode *ic)
5297 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5301 /*-----------------------------------------------------------------*/
5303 /*-----------------------------------------------------------------*/
5304 static void jumpIfTrue (iCode *ic)
5308 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5312 /*-----------------------------------------------------------------*/
5313 /* jmpTrueOrFalse - */
5314 /*-----------------------------------------------------------------*/
5315 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5317 // ugly but optimized by peephole
5320 symbol *nlbl = newiTempLabel(NULL);
5321 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5322 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5323 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5324 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5326 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5327 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5332 /*-----------------------------------------------------------------*/
5333 /* genAnd - code for and */
5334 /*-----------------------------------------------------------------*/
5335 static void genAnd (iCode *ic, iCode *ifx)
5337 operand *left, *right, *result;
5338 int size, offset = 0;
5339 unsigned long lit = 0L;
5344 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5345 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5346 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5348 resolveIfx (&rIfx, ifx);
5350 /* if left is a literal & right is not then exchange them */
5351 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5352 AOP_NEEDSACC (left))
5354 operand *tmp = right;
5359 /* if result = right then exchange them */
5360 if (pic16_sameRegs (AOP (result), AOP (right)))
5362 operand *tmp = right;
5367 /* if right is bit then exchange them */
5368 if (AOP_TYPE (right) == AOP_CRY &&
5369 AOP_TYPE (left) != AOP_CRY)
5371 operand *tmp = right;
5376 if (AOP_TYPE (right) == AOP_LIT)
5377 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5379 size = AOP_SIZE (result);
5381 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5384 // result = bit & yy;
5385 if (AOP_TYPE(left) == AOP_CRY){
5386 // c = bit & literal;
5387 if(AOP_TYPE(right) == AOP_LIT){
5389 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5392 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5395 if(size && (AOP_TYPE(result) == AOP_CRY)){
5396 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5399 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5403 pic16_emitcode("clr","c");
5406 if (AOP_TYPE(right) == AOP_CRY){
5408 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5409 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5412 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5414 pic16_emitcode("rrc","a");
5415 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5421 pic16_outBitC(result);
5423 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5424 genIfxJump(ifx, "c");
5428 // if (val & 0xZZ) - size = 0, ifx != FALSE -
5429 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5430 if ((AOP_TYPE (right) == AOP_LIT) &&
5431 (AOP_TYPE (result) == AOP_CRY) &&
5432 (AOP_TYPE (left) != AOP_CRY))
5434 symbol *tlbl = newiTempLabel (NULL);
5435 int sizel = AOP_SIZE (left);
5442 /* get number of non null bytes in literal */
5445 if (lit & (0xff << (sizel * 8)))
5449 emitBra = nonnull || rIfx.condition;
5451 for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5453 unsigned char bytelit = lit;
5461 /* patch provided by Aaron Colwell */
5462 if ((posbit = isLiteralBit (bytelit)) != 0)
5466 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5467 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5471 pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5476 if (bytelit == 0xff)
5478 /* Aaron had a MOVF instruction here, changed to MOVFW cause
5479 * a peephole could optimize it out -- VR */
5480 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5484 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5485 pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5492 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5496 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5501 /* last non null byte */
5511 // bit = left & literal
5515 pic16_emitpLabel (tlbl->key);
5518 // if(left & literal)
5524 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
5527 pic16_emitpLabel (tlbl->key);
5530 pic16_outBitC (result);
5534 /* if left is same as result */
5535 if(pic16_sameRegs(AOP(result),AOP(left))){
5537 for(;size--; offset++,lit>>=8) {
5538 if(AOP_TYPE(right) == AOP_LIT){
5539 switch(lit & 0xff) {
5541 /* and'ing with 0 has clears the result */
5542 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5543 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5546 /* and'ing with 0xff is a nop when the result and left are the same */
5551 int p = pic16_my_powof2( (~lit) & 0xff );
5553 /* only one bit is set in the literal, so use a bcf instruction */
5554 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5555 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5558 pic16_emitcode("movlw","0x%x", (lit & 0xff));
5559 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5560 if(know_W != (lit&0xff))
5561 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5563 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5568 if (AOP_TYPE(left) == AOP_ACC) {
5569 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5571 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5572 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5579 // left & result in different registers
5580 if(AOP_TYPE(result) == AOP_CRY){
5582 // if(size), result in bit
5583 // if(!size && ifx), conditional oper: if(left & right)
5584 symbol *tlbl = newiTempLabel(NULL);
5585 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5587 pic16_emitcode("setb","c");
5589 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5590 pic16_emitcode("anl","a,%s",
5591 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5592 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5597 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5598 pic16_outBitC(result);
5600 jmpTrueOrFalse(ifx, tlbl);
5602 for(;(size--);offset++) {
5604 // result = left & right
5605 if(AOP_TYPE(right) == AOP_LIT){
5606 int t = (lit >> (offset*8)) & 0x0FFL;
5609 pic16_emitcode("clrf","%s",
5610 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5611 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5614 pic16_emitcode("movf","%s,w",
5615 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5616 pic16_emitcode("movwf","%s",
5617 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5618 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5619 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5622 pic16_emitcode("movlw","0x%x",t);
5623 pic16_emitcode("andwf","%s,w",
5624 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5625 pic16_emitcode("movwf","%s",
5626 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5628 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5629 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5630 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5635 if (AOP_TYPE(left) == AOP_ACC) {
5636 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5637 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5639 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5640 pic16_emitcode("andwf","%s,w",
5641 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5642 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5643 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5645 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5646 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5652 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5653 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5654 pic16_freeAsmop(result,NULL,ic,TRUE);
5657 /*-----------------------------------------------------------------*/
5658 /* genOr - code for or */
5659 /*-----------------------------------------------------------------*/
5660 static void genOr (iCode *ic, iCode *ifx)
5662 operand *left, *right, *result;
5663 int size, offset = 0;
5664 unsigned long lit = 0L;
5669 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5670 pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5671 pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5673 resolveIfx (&rIfx, ifx);
5675 /* if left is a literal & right is not then exchange them */
5676 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5677 AOP_NEEDSACC (left))
5679 operand *tmp = right;
5684 /* if result = right then exchange them */
5685 if (pic16_sameRegs (AOP (result), AOP (right)))
5687 operand *tmp = right;
5692 /* if right is bit then exchange them */
5693 if (AOP_TYPE (right) == AOP_CRY &&
5694 AOP_TYPE (left) != AOP_CRY)
5696 operand *tmp = right;
5701 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5703 if (AOP_TYPE (right) == AOP_LIT)
5704 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5706 size = AOP_SIZE (result);
5710 if (AOP_TYPE(left) == AOP_CRY){
5711 if(AOP_TYPE(right) == AOP_LIT){
5712 // c = bit & literal;
5714 // lit != 0 => result = 1
5715 if(AOP_TYPE(result) == AOP_CRY){
5717 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5718 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5719 // AOP(result)->aopu.aop_dir,
5720 // AOP(result)->aopu.aop_dir);
5722 continueIfTrue(ifx);
5726 // lit == 0 => result = left
5727 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5729 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5732 if (AOP_TYPE(right) == AOP_CRY){
5733 if(pic16_sameRegs(AOP(result),AOP(left))){
5735 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5736 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5737 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5740 if( AOP_TYPE(result) == AOP_ACC) {
5741 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5742 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5743 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5744 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5748 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5749 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5750 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5751 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5757 symbol *tlbl = newiTempLabel(NULL);
5758 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5761 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5762 if( AOP_TYPE(right) == AOP_ACC) {
5763 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5765 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5766 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5771 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5772 pic16_emitcode(";XXX setb","c");
5773 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5774 AOP(left)->aopu.aop_dir,tlbl->key+100);
5775 pic16_toBoolean(right);
5776 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5777 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5778 jmpTrueOrFalse(ifx, tlbl);
5782 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5789 pic16_outBitC(result);
5791 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5792 genIfxJump(ifx, "c");
5796 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5797 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5798 if ((AOP_TYPE (right) == AOP_LIT) &&
5799 (AOP_TYPE (result) == AOP_CRY) &&
5800 (AOP_TYPE (left) != AOP_CRY))
5802 if (IS_OP_VOLATILE(left)) {
5803 pic16_mov2w_volatile(AOP(left));
5808 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5817 /* if left is same as result */
5818 if(pic16_sameRegs(AOP(result),AOP(left))){
5820 for(;size--; offset++,lit>>=8) {
5821 if(AOP_TYPE(right) == AOP_LIT){
5822 if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5823 /* or'ing with 0 has no effect */
5826 int p = pic16_my_powof2(lit & 0xff);
5828 /* only one bit is set in the literal, so use a bsf instruction */
5829 pic16_emitpcode(POC_BSF,
5830 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5832 if(know_W != (lit & 0xff))
5833 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5834 know_W = lit & 0xff;
5835 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5840 if (AOP_TYPE(left) == AOP_ACC) {
5841 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
5843 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5844 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5849 // left & result in different registers
5850 if(AOP_TYPE(result) == AOP_CRY){
5852 // if(size), result in bit
5853 // if(!size && ifx), conditional oper: if(left | right)
5854 symbol *tlbl = newiTempLabel(NULL);
5855 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5856 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5860 pic16_emitcode(";XXX setb","c");
5862 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5863 pic16_emitcode(";XXX orl","a,%s",
5864 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5865 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5870 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5871 pic16_outBitC(result);
5873 jmpTrueOrFalse(ifx, tlbl);
5874 } else for(;(size--);offset++){
5876 // result = left & right
5877 if(AOP_TYPE(right) == AOP_LIT){
5878 int t = (lit >> (offset*8)) & 0x0FFL;
5881 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
5882 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5885 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5886 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5887 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5892 // faster than result <- left, anl result,right
5893 // and better if result is SFR
5894 if (AOP_TYPE(left) == AOP_ACC) {
5895 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
5897 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5898 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5900 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5905 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5906 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5907 pic16_freeAsmop(result,NULL,ic,TRUE);
5910 /*-----------------------------------------------------------------*/
5911 /* genXor - code for xclusive or */
5912 /*-----------------------------------------------------------------*/
5913 static void genXor (iCode *ic, iCode *ifx)
5915 operand *left, *right, *result;
5916 int size, offset = 0;
5917 unsigned long lit = 0L;
5922 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5923 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5924 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5926 resolveIfx (&rIfx,ifx);
5928 /* if left is a literal & right is not ||
5929 if left needs acc & right does not */
5930 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5931 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5933 operand *tmp = right;
5938 /* if result = right then exchange them */
5939 if (pic16_sameRegs (AOP (result), AOP (right)))
5941 operand *tmp = right ;
5946 /* if right is bit then exchange them */
5947 if (AOP_TYPE (right) == AOP_CRY &&
5948 AOP_TYPE (left) != AOP_CRY)
5950 operand *tmp = right ;
5955 if (AOP_TYPE (right) == AOP_LIT)
5956 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5958 size = AOP_SIZE (result);
5962 if (AOP_TYPE(left) == AOP_CRY)
5964 if (AOP_TYPE(right) == AOP_LIT)
5966 // c = bit & literal;
5969 // lit>>1 != 0 => result = 1
5970 if (AOP_TYPE(result) == AOP_CRY)
5974 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
5977 continueIfTrue(ifx);
5980 pic16_emitcode("setb", "c");
5987 // lit == 0, result = left
5988 if (size && pic16_sameRegs(AOP(result), AOP(left)))
5990 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
5994 // lit == 1, result = not(left)
5995 if (size && pic16_sameRegs(AOP(result), AOP(left)))
5997 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
5998 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
5999 pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6004 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6005 pic16_emitcode("cpl", "c");
6013 symbol *tlbl = newiTempLabel(NULL);
6014 if (AOP_TYPE(right) == AOP_CRY)
6017 pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6021 int sizer = AOP_SIZE(right);
6023 // if val>>1 != 0, result = 1
6024 pic16_emitcode("setb", "c");
6027 MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6029 // test the msb of the lsb
6030 pic16_emitcode("anl", "a,#0xfe");
6031 pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6035 pic16_emitcode("rrc", "a");
6037 pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6038 pic16_emitcode("cpl", "c");
6039 pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6044 pic16_outBitC(result);
6046 else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6047 genIfxJump(ifx, "c");
6051 // if(val ^ 0xZZ) - size = 0, ifx != FALSE -
6052 // bit = val ^ 0xZZ - size = 1, ifx = FALSE -
6053 if ((AOP_TYPE (right) == AOP_LIT) &&
6054 (AOP_TYPE (result) == AOP_CRY) &&
6055 (AOP_TYPE (left) != AOP_CRY))
6057 symbol *tlbl = newiTempLabel (NULL);
6063 for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6065 unsigned char bytelit = lit;
6070 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6074 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6078 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6079 pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6086 /* rIfx.lbl might be far away... */
6088 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6092 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6097 /* last non null byte */
6105 // bit = left ^ literal
6109 pic16_emitpLabel (tlbl->key);
6111 // if (left ^ literal)
6116 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
6119 pic16_emitpLabel (tlbl->key);
6123 pic16_outBitC (result);
6127 if (pic16_sameRegs(AOP(result), AOP(left)))
6129 /* if left is same as result */
6130 for (; size--; offset++)
6132 if (AOP_TYPE(right) == AOP_LIT)
6134 int t = (lit >> (offset * 8)) & 0x0FFL;
6139 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6140 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6145 if (AOP_TYPE(left) == AOP_ACC)
6146 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6149 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6150 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6157 // left ^ result in different registers
6158 if (AOP_TYPE(result) == AOP_CRY)
6161 // if(size), result in bit
6162 // if(!size && ifx), conditional oper: if(left ^ right)
6163 symbol *tlbl = newiTempLabel(NULL);
6164 int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6166 pic16_emitcode("setb", "c");
6169 if ((AOP_TYPE(right) == AOP_LIT) &&
6170 (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6172 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6176 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6177 pic16_emitcode("xrl", "a,%s",
6178 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6180 pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6186 pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6187 pic16_outBitC(result);
6190 jmpTrueOrFalse(ifx, tlbl);
6194 for (; (size--); offset++)
6197 // result = left ^ right
6198 if (AOP_TYPE(right) == AOP_LIT)
6200 int t = (lit >> (offset * 8)) & 0x0FFL;
6204 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6205 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6209 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6210 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6214 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6215 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6216 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6221 // faster than result <- left, anl result,right
6222 // and better if result is SFR
6223 if (AOP_TYPE(left) == AOP_ACC)
6225 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6229 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6230 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6232 if ( AOP_TYPE(result) != AOP_ACC)
6234 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6241 pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6242 pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6243 pic16_freeAsmop(result, NULL, ic, TRUE);
6246 /*-----------------------------------------------------------------*/
6247 /* genInline - write the inline code out */
6248 /*-----------------------------------------------------------------*/
6249 static void genInline (iCode *ic)
6251 char *buffer, *bp, *bp1;
6252 bool inComment = FALSE;
6254 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6256 _G.inLine += (!options.asmpeep);
6258 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6260 while((bp1=strstr(bp, "\\n"))) {
6268 /* This is an experimental code for #pragma inline
6269 and is temporarily disabled for 2.5.0 release */
6277 cbuf = Safe_strdup(buffer);
6278 cblen = strlen(buffer)+1;
6279 memset(cbuf, 0, cblen);
6284 if(*bp != '%')*bp1++ = *bp++;
6290 if(i>elementsInSet(asmInlineMap))break;
6293 s = indexSet(asmInlineMap, i);
6294 DEBUGpc("searching symbol s = `%s'", s);
6295 sym = findSym(SymbolTab, NULL, s);
6298 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6300 strcat(bp1, sym->rname);
6306 if(strlen(bp1) > cblen - 16) {
6307 int i = strlen(cbuf);
6309 cbuf = realloc(cbuf, cblen);
6310 memset(cbuf+i, 0, 50);
6316 buffer = Safe_strdup( cbuf );
6323 /* emit each line as a code */
6337 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6342 /* Add \n for labels, not dirs such as c:\mydir */
6343 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6348 /* print label, use this special format with NULL directive
6349 * to denote that the argument should not be indented with tab */
6350 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6359 if ((bp1 != bp) && *bp1)
6360 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6364 _G.inLine -= (!options.asmpeep);
6367 /*-----------------------------------------------------------------*/
6368 /* genRRC - rotate right with carry */
6369 /*-----------------------------------------------------------------*/
6370 static void genRRC (iCode *ic)
6372 operand *left , *result ;
6373 int size, offset = 0, same;
6375 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6377 /* rotate right with carry */
6379 result=IC_RESULT(ic);
6380 pic16_aopOp (left,ic,FALSE);
6381 pic16_aopOp (result,ic,TRUE);
6383 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6385 same = pic16_sameRegs(AOP(result),AOP(left));
6387 size = AOP_SIZE(result);
6389 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6391 /* get the lsb and put it into the carry */
6392 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6399 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6401 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6402 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6408 pic16_freeAsmop(left,NULL,ic,TRUE);
6409 pic16_freeAsmop(result,NULL,ic,TRUE);
6412 /*-----------------------------------------------------------------*/
6413 /* genRLC - generate code for rotate left with carry */
6414 /*-----------------------------------------------------------------*/
6415 static void genRLC (iCode *ic)
6417 operand *left , *result ;
6418 int size, offset = 0;
6421 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6422 /* rotate right with carry */
6424 result=IC_RESULT(ic);
6425 pic16_aopOp (left,ic,FALSE);
6426 pic16_aopOp (result,ic,TRUE);
6428 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6430 same = pic16_sameRegs(AOP(result),AOP(left));
6432 /* move it to the result */
6433 size = AOP_SIZE(result);
6435 /* get the msb and put it into the carry */
6436 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6443 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6445 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6446 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6453 pic16_freeAsmop(left,NULL,ic,TRUE);
6454 pic16_freeAsmop(result,NULL,ic,TRUE);
6458 /* gpasm can get the highest order bit with HIGH/UPPER
6459 * so the following probably is not needed -- VR */
6461 /*-----------------------------------------------------------------*/
6462 /* genGetHbit - generates code get highest order bit */
6463 /*-----------------------------------------------------------------*/
6464 static void genGetHbit (iCode *ic)
6466 operand *left, *result;
6468 result=IC_RESULT(ic);
6469 pic16_aopOp (left,ic,FALSE);
6470 pic16_aopOp (result,ic,FALSE);
6472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6473 /* get the highest order byte into a */
6474 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6475 if(AOP_TYPE(result) == AOP_CRY){
6476 pic16_emitcode("rlc","a");
6477 pic16_outBitC(result);
6480 pic16_emitcode("rl","a");
6481 pic16_emitcode("anl","a,#0x01");
6482 pic16_outAcc(result);
6486 pic16_freeAsmop(left,NULL,ic,TRUE);
6487 pic16_freeAsmop(result,NULL,ic,TRUE);
6491 /*-----------------------------------------------------------------*/
6492 /* AccRol - rotate left accumulator by known count */
6493 /*-----------------------------------------------------------------*/
6494 static void AccRol (int shCount)
6496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6497 shCount &= 0x0007; // shCount : 0..7
6502 pic16_emitcode("rl","a");
6505 pic16_emitcode("rl","a");
6506 pic16_emitcode("rl","a");
6509 pic16_emitcode("swap","a");
6510 pic16_emitcode("rr","a");
6513 pic16_emitcode("swap","a");
6516 pic16_emitcode("swap","a");
6517 pic16_emitcode("rl","a");
6520 pic16_emitcode("rr","a");
6521 pic16_emitcode("rr","a");
6524 pic16_emitcode("rr","a");
6530 /*-----------------------------------------------------------------*/
6531 /* AccLsh - left shift accumulator by known count */
6532 /*-----------------------------------------------------------------*/
6533 static void AccLsh (int shCount, int doMask)
6535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6541 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6544 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6545 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6548 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6549 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6552 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6555 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6556 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6559 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6560 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6563 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6567 /* no masking is required in genPackBits */
6568 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6572 /*-----------------------------------------------------------------*/
6573 /* AccRsh - right shift accumulator by known count */
6574 /*-----------------------------------------------------------------*/
6575 static void AccRsh (int shCount, int andmask)
6577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6578 assert ((shCount >= 0) && (shCount <= 8));
6583 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6586 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6587 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6591 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6594 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6598 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6601 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6602 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608 // Rotating by 8 is a NOP.
6613 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6615 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6618 /*-----------------------------------------------------------------*/
6619 /* shiftR1Left2Result - shift right one byte from left to result */
6620 /*-----------------------------------------------------------------*/
6621 static void shiftR1Left2ResultSigned (operand *left, int offl,
6622 operand *result, int offr,
6627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6628 assert ((shCount >= 0) && (shCount <= 8));
6630 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6632 /* Do NOT use result for intermediate results, it might be an SFR!. */
6636 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6637 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6642 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6644 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6646 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6647 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6652 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6653 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6654 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6655 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6656 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6657 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6661 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6662 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6663 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6664 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6665 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6666 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6670 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6671 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6672 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6673 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6674 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6678 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6679 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6680 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6681 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6682 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6683 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6687 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6688 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6689 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6690 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6691 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6692 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6697 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6698 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6703 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6708 /*-----------------------------------------------------------------*/
6709 /* shiftR1Left2Result - shift right one byte from left to result */
6710 /*-----------------------------------------------------------------*/
6711 static void shiftR1Left2Result (operand *left, int offl,
6712 operand *result, int offr,
6713 int shCount, int sign)
6717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6718 assert ((shCount >= 0) && (shCount <= 8));
6720 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6722 /* Copy the msb into the carry if signed. */
6724 shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6728 /* Do NOT use result for intermediate results, it might be an SFR!. */
6732 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6733 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6740 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6742 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6743 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6744 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6749 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6750 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6751 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6756 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6757 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6758 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6759 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6763 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6764 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6765 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6769 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6770 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6771 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6772 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6776 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6777 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6778 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6779 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6783 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6784 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6785 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6789 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6794 /*-----------------------------------------------------------------*/
6795 /* shiftL1Left2Result - shift left one byte from left to result */
6796 /*-----------------------------------------------------------------*/
6797 static void shiftL1Left2Result (operand *left, int offl,
6798 operand *result, int offr, int shCount)
6802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6803 assert ((shCount >= 0) && (shCount <= 8));
6805 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6807 /* Do NOT use result for intermediate results, it might be an SFR!. */
6811 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6812 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6819 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6821 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6822 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6823 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6828 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6829 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6830 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6831 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6835 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6836 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6837 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6842 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6843 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6848 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6849 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6850 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6851 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6855 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6856 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6857 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6858 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6862 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6863 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6864 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6868 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6873 /*-----------------------------------------------------------------*/
6874 /* movLeft2Result - move byte from left to result */
6875 /*-----------------------------------------------------------------*/
6876 static void movLeft2Result (operand *left, int offl,
6877 operand *result, int offr)
6879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6880 if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6881 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6882 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6886 /*-----------------------------------------------------------------*/
6887 /* shiftL2Left2Result - shift left two bytes from left to result */
6888 /*-----------------------------------------------------------------*/
6889 static void shiftL2Left2Result (operand *left, int offl,
6890 operand *result, int offr, int shCount)
6892 int same = pic16_sameRegs(AOP(result), AOP(left));
6895 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6897 if (same && (offl != offr)) { // shift bytes
6900 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6901 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6903 } else { // just treat as different later on
6916 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6917 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6918 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6922 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6923 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6929 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6930 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6931 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6932 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6933 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6934 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6935 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6937 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6942 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6943 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6944 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6945 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6946 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6947 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6948 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6949 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6950 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6951 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6954 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6955 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6956 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6957 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6958 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6968 /* note, use a mov/add for the shift since the mov has a
6969 chance of getting optimized out */
6970 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6972 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6973 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6974 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6978 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6979 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6985 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6986 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6988 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6990 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
6991 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6992 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6996 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6997 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7001 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7002 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7003 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7006 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7007 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7008 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7009 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7010 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7011 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7012 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7013 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7016 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7017 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7018 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7019 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7020 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7025 /*-----------------------------------------------------------------*/
7026 /* shiftR2Left2Result - shift right two bytes from left to result */
7027 /*-----------------------------------------------------------------*/
7028 static void shiftR2Left2Result (operand *left, int offl,
7029 operand *result, int offr,
7030 int shCount, int sign)
7032 int same = pic16_sameRegs(AOP(result), AOP(left));
7034 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7036 if (same && (offl != offr)) { // shift right bytes
7039 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7040 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7042 } else { // just treat as different later on
7053 /* obtain sign from left operand */
7055 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7060 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7061 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7063 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7064 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7065 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7066 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7071 /* now get sign from already assigned result (avoid BANKSEL) */
7072 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7075 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7076 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7083 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7084 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7085 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7087 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7088 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7089 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7090 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7092 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7093 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7094 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7096 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7097 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7098 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7099 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7100 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7104 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7105 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7110 pic16_emitpcode(POC_BTFSC,
7111 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7112 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7120 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7121 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7123 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7124 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7125 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7126 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7128 pic16_emitpcode(POC_BTFSC,
7129 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7130 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7132 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7133 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7134 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7135 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7137 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7138 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7139 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7140 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7141 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7143 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7144 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7146 pic16_emitpcode(POC_BTFSC,
7147 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7148 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7150 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7151 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7158 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7159 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7161 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7164 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7166 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7171 /*-----------------------------------------------------------------*/
7172 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7173 /*-----------------------------------------------------------------*/
7174 static void shiftLLeftOrResult (operand *left, int offl,
7175 operand *result, int offr, int shCount)
7177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7179 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7180 /* shift left accumulator */
7182 /* or with result */
7183 /* back to result */
7184 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7187 /*-----------------------------------------------------------------*/
7188 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7189 /*-----------------------------------------------------------------*/
7190 static void shiftRLeftOrResult (operand *left, int offl,
7191 operand *result, int offr, int shCount)
7193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7195 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7196 /* shift right accumulator */
7198 /* or with result */
7199 /* back to result */
7200 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7203 /*-----------------------------------------------------------------*/
7204 /* genlshOne - left shift a one byte quantity by known count */
7205 /*-----------------------------------------------------------------*/
7206 static void genlshOne (operand *result, operand *left, int shCount)
7208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7209 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7212 /*-----------------------------------------------------------------*/
7213 /* genlshTwo - left shift two bytes by known amount != 0 */
7214 /*-----------------------------------------------------------------*/
7215 static void genlshTwo (operand *result,operand *left, int shCount)
7219 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7220 size = pic16_getDataSize(result);
7222 /* if shCount >= 8 */
7228 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7230 movLeft2Result(left, LSB, result, MSB16);
7232 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7235 /* 1 <= shCount <= 7 */
7238 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7240 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7244 /*-----------------------------------------------------------------*/
7245 /* shiftLLong - shift left one long from left to result */
7246 /* offr = LSB or MSB16 */
7247 /*-----------------------------------------------------------------*/
7248 static void shiftLLong (operand *left, operand *result, int offr )
7250 int size = AOP_SIZE(result);
7251 int same = pic16_sameRegs(AOP(left),AOP(result));
7254 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7256 if (same && (offr == MSB16)) { //shift one byte
7257 for(i=size-1;i>=MSB16;i--) {
7258 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7259 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7262 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7265 if (size > LSB+offr ){
7267 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7269 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7270 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7274 if(size > MSB16+offr){
7276 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7278 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7279 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7283 if(size > MSB24+offr){
7285 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7287 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7288 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7292 if(size > MSB32+offr){
7294 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7296 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7297 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7301 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7305 /*-----------------------------------------------------------------*/
7306 /* genlshFour - shift four byte by a known amount != 0 */
7307 /*-----------------------------------------------------------------*/
7308 static void genlshFour (operand *result, operand *left, int shCount)
7312 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7313 size = AOP_SIZE(result);
7315 /* if shifting more that 3 bytes */
7316 if (shCount >= 24 ) {
7319 /* lowest order of left goes to the highest
7320 order of the destination */
7321 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7323 movLeft2Result(left, LSB, result, MSB32);
7325 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7326 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7327 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7332 /* more than two bytes */
7333 else if ( shCount >= 16 ) {
7334 /* lower order two bytes goes to higher order two bytes */
7336 /* if some more remaining */
7338 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7340 movLeft2Result(left, MSB16, result, MSB32);
7341 movLeft2Result(left, LSB, result, MSB24);
7343 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7344 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7348 /* if more than 1 byte */
7349 else if ( shCount >= 8 ) {
7350 /* lower order three bytes goes to higher order three bytes */
7354 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7356 movLeft2Result(left, LSB, result, MSB16);
7358 else{ /* size = 4 */
7360 movLeft2Result(left, MSB24, result, MSB32);
7361 movLeft2Result(left, MSB16, result, MSB24);
7362 movLeft2Result(left, LSB, result, MSB16);
7363 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7365 else if(shCount == 1)
7366 shiftLLong(left, result, MSB16);
7368 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7369 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7370 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7371 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7376 /* 1 <= shCount <= 7 */
7377 else if(shCount <= 3)
7379 shiftLLong(left, result, LSB);
7380 while(--shCount >= 1)
7381 shiftLLong(result, result, LSB);
7383 /* 3 <= shCount <= 7, optimize */
7385 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7386 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7387 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7391 /*-----------------------------------------------------------------*/
7392 /* genLeftShiftLiteral - left shifting by known count */
7393 /*-----------------------------------------------------------------*/
7394 void pic16_genLeftShiftLiteral (operand *left,
7399 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7403 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7404 pic16_freeAsmop(right,NULL,ic,TRUE);
7406 pic16_aopOp(left,ic,FALSE);
7407 pic16_aopOp(result,ic,TRUE);
7409 size = getSize(operandType(result));
7412 pic16_emitcode("; shift left ","result %d, left %d",size,
7416 /* I suppose that the left size >= result size */
7419 movLeft2Result(left, size, result, size);
7423 else if(shCount >= (size * 8))
7425 pic16_aopPut(AOP(result),zero,size);
7429 genlshOne (result,left,shCount);
7434 genlshTwo (result,left,shCount);
7438 genlshFour (result,left,shCount);
7442 pic16_freeAsmop(left,NULL,ic,TRUE);
7443 pic16_freeAsmop(result,NULL,ic,TRUE);
7446 /*-----------------------------------------------------------------*
7447 * genMultiAsm - repeat assembly instruction for size of register.
7448 * if endian == 1, then the high byte (i.e base address + size of
7449 * register) is used first else the low byte is used first;
7450 *-----------------------------------------------------------------*/
7451 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7469 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7475 /*-----------------------------------------------------------------*/
7476 /* genrshOne - right shift a one byte quantity by known count */
7477 /*-----------------------------------------------------------------*/
7478 static void genrshOne (operand *result, operand *left,
7479 int shCount, int sign)
7481 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7482 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7485 /*-----------------------------------------------------------------*/
7486 /* genrshTwo - right shift two bytes by known amount != 0 */
7487 /*-----------------------------------------------------------------*/
7488 static void genrshTwo (operand *result,operand *left,
7489 int shCount, int sign)
7491 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7492 /* if shCount >= 8 */
7496 shiftR1Left2Result(left, MSB16, result, LSB,
7499 movLeft2Result(left, MSB16, result, LSB);
7501 pic16_addSign (result, 1, sign);
7504 /* 1 <= shCount <= 7 */
7506 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7509 /*-----------------------------------------------------------------*/
7510 /* shiftRLong - shift right one long from left to result */
7511 /* offl = LSB or MSB16 */
7512 /*-----------------------------------------------------------------*/
7513 static void shiftRLong (operand *left, int offl,
7514 operand *result, int sign)
7516 int size = AOP_SIZE(result);
7517 int same = pic16_sameRegs(AOP(left),AOP(result));
7519 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7521 if (same && (offl == MSB16)) { //shift one byte right
7522 for(i=MSB16;i<size;i++) {
7523 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7524 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7529 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7535 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7537 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7538 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7542 /* add sign of "a" */
7543 pic16_addSign(result, MSB32, sign);
7547 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7549 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7550 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7554 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7556 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7557 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7561 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7564 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7565 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7570 /*-----------------------------------------------------------------*/
7571 /* genrshFour - shift four byte by a known amount != 0 */
7572 /*-----------------------------------------------------------------*/
7573 static void genrshFour (operand *result, operand *left,
7574 int shCount, int sign)
7576 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7577 /* if shifting more that 3 bytes */
7578 if(shCount >= 24 ) {
7581 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7583 movLeft2Result(left, MSB32, result, LSB);
7585 pic16_addSign(result, MSB16, sign);
7587 else if(shCount >= 16){
7590 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7592 movLeft2Result(left, MSB24, result, LSB);
7593 movLeft2Result(left, MSB32, result, MSB16);
7595 pic16_addSign(result, MSB24, sign);
7597 else if(shCount >= 8){
7600 shiftRLong(left, MSB16, result, sign);
7601 else if(shCount == 0){
7602 movLeft2Result(left, MSB16, result, LSB);
7603 movLeft2Result(left, MSB24, result, MSB16);
7604 movLeft2Result(left, MSB32, result, MSB24);
7605 pic16_addSign(result, MSB32, sign);
7607 else{ //shcount >= 2
7608 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7609 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7610 /* the last shift is signed */
7611 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7612 pic16_addSign(result, MSB32, sign);
7615 else{ /* 1 <= shCount <= 7 */
7617 shiftRLong(left, LSB, result, sign);
7619 shiftRLong(result, LSB, result, sign);
7622 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7623 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7624 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7629 /*-----------------------------------------------------------------*/
7630 /* genRightShiftLiteral - right shifting by known count */
7631 /*-----------------------------------------------------------------*/
7632 static void genRightShiftLiteral (operand *left,
7638 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7641 pic16_freeAsmop(right,NULL,ic,TRUE);
7643 pic16_aopOp(left,ic,FALSE);
7644 pic16_aopOp(result,ic,TRUE);
7646 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7649 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7653 lsize = pic16_getDataSize(left);
7654 res_size = pic16_getDataSize(result);
7655 /* test the LEFT size !!! */
7657 /* I suppose that the left size >= result size */
7659 assert (res_size <= lsize);
7660 while (res_size--) {
7661 pic16_mov2f (AOP(result), AOP(left), res_size);
7663 } else if (shCount >= (lsize * 8)) {
7670 * even for 8-bit operands; result might be an SFR.
7672 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7673 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7674 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7675 while (res_size--) {
7676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7678 } else { // unsigned
7679 while (res_size--) {
7680 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7683 } else { // 0 < shCount < 8*lsize
7686 genrshOne (result,left,shCount,sign);
7690 genrshTwo (result,left,shCount,sign);
7694 genrshFour (result,left,shCount,sign);
7701 pic16_freeAsmop(left,NULL,ic,TRUE);
7702 pic16_freeAsmop(result,NULL,ic,TRUE);
7705 /*-----------------------------------------------------------------*/
7706 /* genGenericShift - generates code for left or right shifting */
7707 /*-----------------------------------------------------------------*/
7708 static void genGenericShift (iCode *ic, int isShiftLeft)
7710 operand *left,*right, *result;
7712 int sign, signedCount;
7713 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7714 PIC_OPCODE pos_shift, neg_shift;
7718 right = IC_RIGHT(ic);
7720 result = IC_RESULT(ic);
7722 pic16_aopOp(right,ic,FALSE);
7723 pic16_aopOp(left,ic,FALSE);
7724 pic16_aopOp(result,ic,TRUE);
7726 sign = !SPEC_USIGN(operandType (left));
7727 signedCount = !SPEC_USIGN(operandType (right));
7729 /* if the shift count is known then do it
7730 as efficiently as possible */
7731 if (AOP_TYPE(right) == AOP_LIT) {
7732 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7733 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7734 // we should modify right->aopu.aop_lit here!
7735 // Instead we use abs(shCount) in genXXXShiftLiteral()...
7736 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7738 pic16_genLeftShiftLiteral (left,right,result,ic);
7740 genRightShiftLiteral (left,right,result,ic, sign);
7743 } // if (right is literal)
7745 /* shift count is unknown then we have to form a loop.
7746 * Note: we take only the lower order byte since shifting
7747 * more than 32 bits make no sense anyway, ( the
7748 * largest size of an object can be only 32 bits )
7749 * Note: we perform arithmetic shifts if the left operand is
7750 * signed and we do an (effective) right shift, i. e. we
7751 * shift in the sign bit from the left. */
7753 label_complete = newiTempLabel ( NULL );
7754 label_loop_pos = newiTempLabel ( NULL );
7755 label_loop_neg = NULL;
7756 label_negative = NULL;
7757 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7758 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7761 // additional labels needed
7762 label_loop_neg = newiTempLabel ( NULL );
7763 label_negative = newiTempLabel ( NULL );
7766 // copy source to result -- this will effectively truncate the left operand to the size of result!
7767 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7768 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7769 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7770 pic16_mov2f (AOP(result),AOP(left), offset);
7773 // if result is longer than left, fill with zeros (or sign)
7774 if (AOP_SIZE(left) < AOP_SIZE(result)) {
7775 if (sign && AOP_SIZE(left) > 0) {
7776 // shift signed operand -- fill with sign
7777 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7778 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7779 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7780 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7781 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7784 // shift unsigned operand -- fill result with zeros
7785 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7786 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7789 } // if (size mismatch)
7791 pic16_mov2w (AOP(right), 0);
7792 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7793 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7796 // perform a shift by one (shift count is positive)
7797 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7798 // 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])
7799 pic16_emitpLabel (label_loop_pos->key);
7801 if (sign && (pos_shift == POC_RRCF)) {
7802 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7805 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7806 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7807 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7809 // perform a shift by one (shift count is positive)
7810 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7811 // 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])
7812 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7813 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7815 pic16_emitpLabel (label_loop_pos->key);
7816 if (sign && (pos_shift == POC_RRCF)) {
7817 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7820 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7821 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7822 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7823 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7827 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7829 pic16_emitpLabel (label_negative->key);
7830 // perform a shift by -1 (shift count is negative)
7831 // 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)
7833 pic16_emitpLabel (label_loop_neg->key);
7834 if (sign && (neg_shift == POC_RRCF)) {
7835 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7838 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7839 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7840 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7841 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7842 } // if (signedCount)
7844 pic16_emitpLabel (label_complete->key);
7847 pic16_freeAsmop (right,NULL,ic,TRUE);
7848 pic16_freeAsmop(left,NULL,ic,TRUE);
7849 pic16_freeAsmop(result,NULL,ic,TRUE);
7852 static void genLeftShift (iCode *ic) {
7853 genGenericShift (ic, 1);
7856 static void genRightShift (iCode *ic) {
7857 genGenericShift (ic, 0);
7861 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7862 void pic16_loadFSR0(operand *op, int lit)
7864 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7865 if (AOP_TYPE(op) == AOP_LIT) {
7866 /* handle 12 bit integers correctly */
7867 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7868 if ((val & 0x0fff) != val) {
7869 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7870 val, (val & 0x0fff) );
7873 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7875 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7878 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7879 // set up FSR0 with address of result
7880 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7885 /*----------------------------------------------------------------*/
7886 /* pic16_derefPtr - move one byte from the location ptr points to */
7887 /* to WREG (doWrite == 0) or one byte from WREG */
7888 /* to the location ptr points to (doWrite != 0) */
7889 /*----------------------------------------------------------------*/
7890 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7892 if (!IS_PTR(operandType(ptr)))
7894 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7895 else pic16_mov2w (AOP(ptr), 0);
7899 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7900 /* We might determine pointer type right here: */
7901 p_type = DCL_TYPE(operandType(ptr));
7906 if (!fsr0_setup || !*fsr0_setup)
7908 pic16_loadFSR0( ptr, 0 );
7909 if (fsr0_setup) *fsr0_setup = 1;
7912 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7914 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7918 if (AOP(ptr)->aopu.aop_reg[2]) {
7919 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7920 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7921 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7922 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7923 pic16_mov2w(AOP(ptr), 2);
7924 pic16_callGenericPointerRW(doWrite, 1);
7926 // data pointer (just 2 byte given)
7927 if (!fsr0_setup || !*fsr0_setup)
7929 pic16_loadFSR0( ptr, 0 );
7930 if (fsr0_setup) *fsr0_setup = 1;
7933 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7935 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7940 assert (0 && "invalid pointer type specified");
7945 /*-----------------------------------------------------------------*/
7946 /* genUnpackBits - generates code for unpacking bits */
7947 /*-----------------------------------------------------------------*/
7948 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7951 sym_link *etype, *letype;
7957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7958 etype = getSpec(operandType(result));
7959 letype = getSpec(operandType(left));
7961 // if(IS_BITFIELD(etype)) {
7962 blen = SPEC_BLEN(etype);
7963 bstr = SPEC_BSTR(etype);
7966 lbstr = SPEC_BSTR( letype );
7968 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7969 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7972 if((blen == 1) && (bstr < 8)
7973 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
7974 /* it is a single bit, so use the appropriate bit instructions */
7975 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
7977 same = pic16_sameRegs(AOP(left),AOP(result));
7978 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
7979 pic16_emitpcode(POC_CLRF, op);
7981 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
7982 /* workaround to reduce the extra lfsr instruction */
7983 pic16_emitpcode(POC_BTFSC,
7984 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
7986 assert (PIC_IS_DATA_PTR (operandType(left)));
7987 pic16_loadFSR0 (left, 0);
7988 pic16_emitpcode(POC_BTFSC,
7989 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
7992 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7993 /* unsigned bitfields result in either 0 or 1 */
7994 pic16_emitpcode(POC_INCF, op);
7996 /* signed bitfields result in either 0 or -1 */
7997 pic16_emitpcode(POC_DECF, op);
8000 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8003 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8009 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8010 // access symbol directly
8011 pic16_mov2w (AOP(left), 0);
8013 pic16_derefPtr (left, ptype, 0, NULL);
8016 /* if we have bitdisplacement then it fits */
8017 /* into this byte completely or if length is */
8018 /* less than a byte */
8019 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
8021 /* shift right acc */
8024 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8025 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8027 /* VR -- normally I would use the following, but since we use the hack,
8028 * to avoid the masking from AccRsh, why not mask it right now? */
8031 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8034 /* extend signed bitfields to 8 bits */
8035 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8037 assert (blen + bstr > 0);
8038 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8039 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8042 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8044 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8048 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8049 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8056 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8058 int size, offset = 0, leoffset=0 ;
8060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8061 pic16_aopOp(result, ic, TRUE);
8065 size = AOP_SIZE(result);
8066 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8070 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8071 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8072 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8077 if(AOP(left)->aopu.pcop->type == PO_DIR)
8078 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8080 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8083 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8085 // pic16_DumpOp("(result)",result);
8086 if(pic16_isLitAop(AOP(result))) {
8087 pic16_mov2w(AOP(left), offset); // patch 8
8088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8091 pic16_popGet(AOP(left), offset), //patch 8
8092 pic16_popGet(AOP(result), offset)));
8100 pic16_freeAsmop(result,NULL,ic,TRUE);
8105 /*-----------------------------------------------------------------*/
8106 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8107 /*-----------------------------------------------------------------*/
8108 static void genNearPointerGet (operand *left,
8112 // asmop *aop = NULL;
8113 //regs *preg = NULL ;
8114 sym_link *rtype, *retype;
8115 sym_link *ltype, *letype;
8119 rtype = operandType(result);
8120 retype= getSpec(rtype);
8121 ltype = operandType(left);
8122 letype= getSpec(ltype);
8124 pic16_aopOp(left,ic,FALSE);
8126 // pic16_DumpOp("(left)",left);
8127 // pic16_DumpOp("(result)",result);
8129 /* if left is rematerialisable and
8130 * result is not bit variable type and
8131 * the left is pointer to data space i.e
8132 * lower 128 bytes of space */
8134 if (AOP_TYPE(left) == AOP_PCODE
8135 && !IS_BITFIELD(retype)
8136 && DCL_TYPE(ltype) == POINTER) {
8138 genDataPointerGet (left,result,ic);
8139 pic16_freeAsmop(left, NULL, ic, TRUE);
8143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8144 pic16_aopOp (result,ic,TRUE);
8146 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8149 if(IS_BITFIELD( retype )
8150 && (SPEC_BLEN(operandType(result))==1)
8154 int bitstrt, bytestrt;
8156 /* if this is bitfield of size 1, see if we are checking the value
8157 * of a single bit in an if-statement,
8158 * if yes, then don't generate usual code, but execute the
8159 * genIfx directly -- VR */
8163 /* CHECK: if next iCode is IFX
8164 * and current result operand is nextic's conditional operand
8165 * and current result operand live ranges ends at nextic's key number
8167 if((nextic->op == IFX)
8168 && (result == IC_COND(nextic))
8169 && (OP_LIVETO(result) == nextic->seq)
8170 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
8172 /* everything is ok then */
8173 /* find a way to optimize the genIfx iCode */
8175 bytestrt = SPEC_BSTR(operandType(result))/8;
8176 bitstrt = SPEC_BSTR(operandType(result))%8;
8178 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8180 genIfxpCOpJump(nextic, jop);
8182 pic16_freeAsmop(left, NULL, ic, TRUE);
8183 pic16_freeAsmop(result, NULL, ic, TRUE);
8189 /* if bitfield then unpack the bits */
8190 if (IS_BITFIELD(letype))
8191 genUnpackBits (result, left, NULL, POINTER);
8193 /* we have can just get the values */
8194 int size = AOP_SIZE(result);
8197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8199 pic16_loadFSR0( left, 0 );
8203 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8204 pic16_popGet(AOP(result), offset++)));
8206 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8207 pic16_popGet(AOP(result), offset++)));
8213 /* now some housekeeping stuff */
8215 /* we had to allocate for this iCode */
8216 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8217 pic16_freeAsmop(NULL,aop,ic,TRUE);
8219 /* we did not allocate which means left
8220 * already in a pointer register, then
8221 * if size > 0 && this could be used again
8222 * we have to point it back to where it
8224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8225 if (AOP_SIZE(result) > 1
8226 && !OP_SYMBOL(left)->remat
8227 && ( OP_SYMBOL(left)->liveTo > ic->seq
8229 // int size = AOP_SIZE(result) - 1;
8231 // pic16_emitcode("dec","%s",rname);
8237 pic16_freeAsmop(left,NULL,ic,TRUE);
8238 pic16_freeAsmop(result,NULL,ic,TRUE);
8241 /*-----------------------------------------------------------------*/
8242 /* genGenPointerGet - gget value from generic pointer space */
8243 /*-----------------------------------------------------------------*/
8244 static void genGenPointerGet (operand *left,
8245 operand *result, iCode *ic)
8248 sym_link *letype = getSpec(operandType(left));
8250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8251 pic16_aopOp(left,ic,FALSE);
8252 pic16_aopOp(result,ic,TRUE);
8253 size = AOP_SIZE(result);
8255 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8257 /* if bit then unpack */
8258 if (IS_BITFIELD(letype)) {
8259 genUnpackBits(result,left,"BAD",GPOINTER);
8263 /* set up WREG:PRODL:FSR0L with address from left */
8264 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8265 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8266 pic16_mov2w(AOP(left), 2);
8267 pic16_callGenericPointerRW(0, size);
8269 assignResultValue(result, size, 1);
8272 pic16_freeAsmop(left,NULL,ic,TRUE);
8273 pic16_freeAsmop(result,NULL,ic,TRUE);
8276 /*-----------------------------------------------------------------*/
8277 /* genConstPointerGet - get value from const generic pointer space */
8278 /*-----------------------------------------------------------------*/
8279 static void genConstPointerGet (operand *left,
8280 operand *result, iCode *ic)
8282 //sym_link *retype = getSpec(operandType(result));
8283 // symbol *albl = newiTempLabel(NULL); // patch 15
8284 // symbol *blbl = newiTempLabel(NULL); //
8285 // PIC_OPCODE poc; // patch 15
8289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8290 pic16_aopOp(left,ic,FALSE);
8291 pic16_aopOp(result,ic,TRUE);
8292 size = AOP_SIZE(result);
8294 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8296 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8298 // set up table pointer
8299 if( (AOP_TYPE(left) == AOP_PCODE)
8300 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8301 || (AOP(left)->aopu.pcop->type == PO_DIR)))
8303 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8304 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8305 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8306 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8307 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8308 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8310 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8311 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8312 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8316 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8317 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8321 pic16_freeAsmop(left,NULL,ic,TRUE);
8322 pic16_freeAsmop(result,NULL,ic,TRUE);
8326 /*-----------------------------------------------------------------*/
8327 /* genPointerGet - generate code for pointer get */
8328 /*-----------------------------------------------------------------*/
8329 static void genPointerGet (iCode *ic)
8331 operand *left, *result ;
8332 sym_link *type, *etype;
8338 result = IC_RESULT(ic) ;
8340 /* depending on the type of pointer we need to
8341 move it to the correct pointer register */
8342 type = operandType(left);
8343 etype = getSpec(type);
8346 if (IS_PTR_CONST(type))
8348 if (IS_CODEPTR(type))
8350 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8352 /* if left is of type of pointer then it is simple */
8353 if (IS_PTR(type) && !IS_FUNC(type->next))
8354 p_type = DCL_TYPE(type);
8356 /* we have to go by the storage class */
8357 p_type = PTR_TYPE(SPEC_OCLS(etype));
8359 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8361 if (SPEC_OCLS(etype)->codesp ) {
8362 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8363 //p_type = CPOINTER ;
8365 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8366 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8367 /*p_type = FPOINTER ;*/
8369 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8370 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8371 /* p_type = PPOINTER; */
8373 if (SPEC_OCLS(etype) == idata ) {
8374 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8375 /* p_type = IPOINTER; */
8377 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8378 /* p_type = POINTER ; */
8382 /* now that we have the pointer type we assign
8383 the pointer values */
8388 genNearPointerGet (left,result,ic);
8392 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8394 genPagedPointerGet(left,result,ic);
8398 genFarPointerGet (left,result,ic);
8403 genConstPointerGet (left,result,ic);
8404 //pic16_emitcodePointerGet (left,result,ic);
8409 if (IS_PTR_CONST(type))
8410 genConstPointerGet (left,result,ic);
8413 genGenPointerGet (left,result,ic);
8417 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8418 "genPointerGet: illegal pointer type");
8423 /*-----------------------------------------------------------------*/
8424 /* genPackBits - generates code for packed bit storage */
8425 /*-----------------------------------------------------------------*/
8426 static void genPackBits (sym_link *etype , operand *result,
8428 char *rname, int p_type)
8434 int shifted_and_masked = 0;
8435 unsigned long lit = (unsigned long)-1;
8438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8439 blen = SPEC_BLEN(etype);
8440 bstr = SPEC_BSTR(etype);
8442 retype = getSpec(operandType(right));
8444 if(AOP_TYPE(right) == AOP_LIT) {
8445 lit = ulFromVal (AOP(right)->aopu.aop_lit);
8447 if((blen == 1) && (bstr < 8)) {
8448 /* it is a single bit, so use the appropriate bit instructions */
8450 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8452 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8453 /* workaround to reduce the extra lfsr instruction */
8455 pic16_emitpcode(POC_BSF,
8456 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8458 pic16_emitpcode(POC_BCF,
8459 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8462 if (PIC_IS_DATA_PTR(operandType(result))) {
8463 pic16_loadFSR0(result, 0);
8464 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8465 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8468 pic16_derefPtr (result, p_type, 0, NULL);
8469 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8470 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8471 /* write back new value */
8472 pic16_derefPtr (result, p_type, 1, NULL);
8478 /* IORLW below is more efficient */
8479 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8480 lit = (lit & ((1UL << blen) - 1)) << bstr;
8481 shifted_and_masked = 1;
8484 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8485 && IS_BITFIELD(retype)
8486 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8490 rblen = SPEC_BLEN( retype );
8491 rbstr = SPEC_BSTR( retype );
8493 if(IS_BITFIELD(etype)) {
8494 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8495 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8497 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8500 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8502 if(IS_BITFIELD(etype)) {
8503 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8505 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8512 /* move right to W */
8513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8516 /* if the bit length is less than or */
8517 /* it exactly fits a byte then */
8518 if((shCnt=SPEC_BSTR(etype))
8519 || SPEC_BLEN(etype) <= 8 ) {
8522 if (blen != 8 || (bstr % 8) != 0) {
8523 // we need to combine the value with the old value
8524 if(!shifted_and_masked)
8526 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8528 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8529 SPEC_BSTR(etype), SPEC_BLEN(etype));
8531 /* shift left acc, do NOT mask the result again */
8534 /* using PRODH as a temporary register here */
8535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8538 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8539 || IS_DIRECT(result)) {
8540 /* access symbol directly */
8541 pic16_mov2w (AOP(result), 0);
8544 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8547 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8548 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8549 (unsigned char)(0xff >> (8-bstr))) ));
8550 if (!shifted_and_masked) {
8551 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8553 /* We have the shifted and masked (literal) right value in `lit' */
8555 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8557 } else { // if (blen == 8 && (bstr % 8) == 0)
8558 if (shifted_and_masked) {
8559 // move right (literal) to WREG (only case where right is not yet in WREG)
8560 pic16_mov2w(AOP(right), (bstr / 8));
8564 /* write new value back */
8565 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8566 || IS_DIRECT(result)) {
8567 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8569 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8578 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8579 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8584 pic16_loadFSR0(result, 0); // load FSR0 with address of result
8585 rLen = SPEC_BLEN(etype)-8;
8587 /* now generate for lengths greater than one byte */
8591 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8597 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8603 pic16_emitcode("movx","@dptr,a");
8608 DEBUGpic16_emitcode(";lcall","__gptrput");
8616 pic16_mov2w(AOP(right), offset++);
8619 /* last last was not complete */
8621 /* save the byte & read byte */
8624 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8625 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8630 pic16_emitcode ("mov","b,a");
8631 pic16_emitcode("movx","a,@dptr");
8635 pic16_emitcode ("push","b");
8636 pic16_emitcode ("push","acc");
8637 pic16_emitcode ("lcall","__gptrget");
8638 pic16_emitcode ("pop","b");
8644 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8645 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8646 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8647 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8648 // pic16_emitcode ("orl","a,b");
8651 // if (p_type == GPOINTER)
8652 // pic16_emitcode("pop","b");
8657 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8658 // pic16_emitcode("mov","@%s,a",rname);
8662 pic16_emitcode("movx","@dptr,a");
8666 DEBUGpic16_emitcode(";lcall","__gptrput");
8673 // pic16_freeAsmop(right, NULL, ic, TRUE);
8676 /*-----------------------------------------------------------------*/
8677 /* genDataPointerSet - remat pointer to data space */
8678 /*-----------------------------------------------------------------*/
8679 static void genDataPointerSet(operand *right,
8683 int size, offset = 0, resoffset=0 ;
8685 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8686 pic16_aopOp(right,ic,FALSE);
8688 size = AOP_SIZE(right);
8690 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8693 if ( AOP_TYPE(result) == AOP_PCODE) {
8694 fprintf(stderr,"genDataPointerSet %s, %d\n",
8695 AOP(result)->aopu.pcop->name,
8696 (AOP(result)->aopu.pcop->type == PO_DIR)?
8697 PCOR(AOP(result)->aopu.pcop)->instance:
8698 PCOI(AOP(result)->aopu.pcop)->offset);
8702 if(AOP(result)->aopu.pcop->type == PO_DIR)
8703 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8706 if (AOP_TYPE(right) == AOP_LIT) {
8707 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8708 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8710 pic16_mov2w(AOP(right), offset);
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8717 pic16_freeAsmop(right,NULL,ic,TRUE);
8722 /*-----------------------------------------------------------------*/
8723 /* genNearPointerSet - pic16_emitcode for near pointer put */
8724 /*-----------------------------------------------------------------*/
8725 static void genNearPointerSet (operand *right,
8731 sym_link *ptype = operandType(result);
8734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8735 retype= getSpec(operandType(right));
8736 resetype = getSpec(operandType(result));
8738 pic16_aopOp(result,ic,FALSE);
8740 /* if the result is rematerializable &
8741 * in data space & not a bit variable */
8743 /* and result is not a bit variable */
8744 if (AOP_TYPE(result) == AOP_PCODE
8745 && DCL_TYPE(ptype) == POINTER
8746 && !IS_BITFIELD(retype)
8747 && !IS_BITFIELD(resetype)) {
8749 genDataPointerSet (right,result,ic);
8750 pic16_freeAsmop(result,NULL,ic,TRUE);
8754 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8755 pic16_aopOp(right,ic,FALSE);
8756 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8758 /* if bitfield then unpack the bits */
8759 if (IS_BITFIELD(resetype)) {
8760 genPackBits (resetype, result, right, NULL, POINTER);
8762 /* we have can just get the values */
8763 int size = AOP_SIZE(right);
8766 pic16_loadFSR0(result, 0);
8768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8770 if (pic16_isLitOp(right)) {
8771 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8773 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8775 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8777 } else { // no literal
8779 pic16_emitpcode(POC_MOVFF,
8780 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8781 pic16_popCopyReg(&pic16_pc_postinc0)));
8783 pic16_emitpcode(POC_MOVFF,
8784 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8785 pic16_popCopyReg(&pic16_pc_indf0)));
8793 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8794 /* now some housekeeping stuff */
8796 /* we had to allocate for this iCode */
8797 pic16_freeAsmop(NULL,aop,ic,TRUE);
8799 /* we did not allocate which means left
8800 * already in a pointer register, then
8801 * if size > 0 && this could be used again
8802 * we have to point it back to where it
8804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8805 if (AOP_SIZE(right) > 1
8806 && !OP_SYMBOL(result)->remat
8807 && ( OP_SYMBOL(result)->liveTo > ic->seq
8810 int size = AOP_SIZE(right) - 1;
8813 pic16_emitcode("decf","fsr0,f");
8814 //pic16_emitcode("dec","%s",rname);
8818 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8821 pic16_freeAsmop(right,NULL,ic,TRUE);
8822 pic16_freeAsmop(result,NULL,ic,TRUE);
8825 /*-----------------------------------------------------------------*/
8826 /* genGenPointerSet - set value from generic pointer space */
8827 /*-----------------------------------------------------------------*/
8828 static void genGenPointerSet (operand *right,
8829 operand *result, iCode *ic)
8832 sym_link *retype = getSpec(operandType(result));
8834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8836 pic16_aopOp(result,ic,FALSE);
8837 pic16_aopOp(right,ic,FALSE);
8838 size = AOP_SIZE(right);
8840 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8843 /* if bit then unpack */
8844 if (IS_BITFIELD(retype)) {
8845 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8846 genPackBits(retype,result,right,"dptr",GPOINTER);
8850 size = AOP_SIZE(right);
8852 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
8855 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8857 /* value of right+0 is placed on stack, which will be retrieved
8858 * by the support function thus restoring the stack. The important
8859 * thing is that there is no need to manually restore stack pointer
8861 pushaop(AOP(right), 0);
8862 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8863 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8864 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8865 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8867 /* load address to write to in WREG:FSR0H:FSR0L */
8868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8869 pic16_popCopyReg(&pic16_pc_fsr0l)));
8870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8871 pic16_popCopyReg(&pic16_pc_prodl)));
8872 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8874 pic16_callGenericPointerRW(1, size);
8877 pic16_freeAsmop(right,NULL,ic,TRUE);
8878 pic16_freeAsmop(result,NULL,ic,TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* genPointerSet - stores the value into a pointer location */
8883 /*-----------------------------------------------------------------*/
8884 static void genPointerSet (iCode *ic)
8886 operand *right, *result ;
8887 sym_link *type, *etype;
8892 right = IC_RIGHT(ic);
8893 result = IC_RESULT(ic) ;
8895 /* depending on the type of pointer we need to
8896 move it to the correct pointer register */
8897 type = operandType(result);
8898 etype = getSpec(type);
8900 /* if left is of type of pointer then it is simple */
8901 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8902 p_type = DCL_TYPE(type);
8905 /* we have to go by the storage class */
8906 p_type = PTR_TYPE(SPEC_OCLS(etype));
8908 /* if (SPEC_OCLS(etype)->codesp ) { */
8909 /* p_type = CPOINTER ; */
8912 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8913 /* p_type = FPOINTER ; */
8915 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8916 /* p_type = PPOINTER ; */
8918 /* if (SPEC_OCLS(etype) == idata ) */
8919 /* p_type = IPOINTER ; */
8921 /* p_type = POINTER ; */
8924 /* now that we have the pointer type we assign
8925 the pointer values */
8930 genNearPointerSet (right,result,ic);
8934 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8936 genPagedPointerSet (right,result,ic);
8940 genFarPointerSet (right,result,ic);
8945 genGenPointerSet (right,result,ic);
8949 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8950 "genPointerSet: illegal pointer type");
8954 /*-----------------------------------------------------------------*/
8955 /* genIfx - generate code for Ifx statement */
8956 /*-----------------------------------------------------------------*/
8957 static void genIfx (iCode *ic, iCode *popIc)
8959 operand *cond = IC_COND(ic);
8964 pic16_aopOp(cond,ic,FALSE);
8966 /* get the value into acc */
8967 if (AOP_TYPE(cond) != AOP_CRY)
8968 pic16_toBoolean(cond);
8971 /* the result is now in the accumulator */
8972 pic16_freeAsmop(cond,NULL,ic,TRUE);
8974 /* if there was something to be popped then do it */
8978 /* if the condition is a bit variable */
8979 if (isbit && IS_ITEMP(cond) &&
8982 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8984 if (isbit && !IS_ITEMP(cond))
8985 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8992 /*-----------------------------------------------------------------*/
8993 /* genAddrOf - generates code for address of */
8994 /*-----------------------------------------------------------------*/
8995 static void genAddrOf (iCode *ic)
8997 operand *result, *left;
8999 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
9000 pCodeOp *pcop0, *pcop1, *pcop2;
9004 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9006 sym = OP_SYMBOL( IC_LEFT(ic) );
9009 /* get address of symbol on stack */
9010 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9012 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9013 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9016 // operands on stack are accessible via "FSR2 + index" with index
9017 // starting at 2 for arguments and growing from 0 downwards for
9018 // local variables (index == 0 is not assigned so we add one here)
9020 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9027 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9028 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9029 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9030 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9031 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9032 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9033 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9039 // if(pic16_debug_verbose) {
9040 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9041 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9044 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9045 size = AOP_SIZE(IC_RESULT(ic));
9047 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9048 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9049 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9052 pic16_emitpcode(POC_MOVLW, pcop0);
9053 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9054 pic16_emitpcode(POC_MOVLW, pcop1);
9055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9056 pic16_emitpcode(POC_MOVLW, pcop2);
9057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9060 pic16_emitpcode(POC_MOVLW, pcop0);
9061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9062 pic16_emitpcode(POC_MOVLW, pcop1);
9063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9065 pic16_emitpcode(POC_MOVLW, pcop0);
9066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9069 pic16_freeAsmop(left, NULL, ic, FALSE);
9071 pic16_freeAsmop(result,NULL,ic,TRUE);
9075 /*-----------------------------------------------------------------*/
9076 /* genAssign - generate code for assignment */
9077 /*-----------------------------------------------------------------*/
9078 static void genAssign (iCode *ic)
9080 operand *result, *right;
9081 sym_link *restype, *rtype;
9082 int size, offset,know_W;
9083 unsigned long lit = 0L;
9085 result = IC_RESULT(ic);
9086 right = IC_RIGHT(ic) ;
9090 /* if they are the same */
9091 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9094 /* reversed order operands are aopOp'ed so that result operand
9095 * is effective in case right is a stack symbol. This maneauver
9096 * allows to use the _G.resDirect flag later */
9097 pic16_aopOp(result,ic,TRUE);
9098 pic16_aopOp(right,ic,FALSE);
9100 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9102 /* if they are the same registers */
9103 if (pic16_sameRegs(AOP(right),AOP(result)))
9106 /* if the result is a bit */
9107 if (AOP_TYPE(result) == AOP_CRY) {
9108 /* if the right size is a literal then
9109 we know what the value is */
9110 if (AOP_TYPE(right) == AOP_LIT) {
9112 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9113 pic16_popGet(AOP(result),0));
9115 if (((int) operandLitValue(right)))
9116 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9117 AOP(result)->aopu.aop_dir,
9118 AOP(result)->aopu.aop_dir);
9120 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9121 AOP(result)->aopu.aop_dir,
9122 AOP(result)->aopu.aop_dir);
9127 /* the right is also a bit variable */
9128 if (AOP_TYPE(right) == AOP_CRY) {
9129 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9130 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9131 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9137 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9138 pic16_toBoolean(right);
9140 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9141 //pic16_aopPut(AOP(result),"a",0);
9145 /* bit variables done */
9147 size = AOP_SIZE(result);
9150 /* bit variables done */
9152 size = AOP_SIZE(result);
9153 restype = operandType(result);
9154 rtype = operandType(right);
9157 if(AOP_TYPE(right) == AOP_LIT) {
9158 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9160 lit = ulFromVal (AOP(right)->aopu.aop_lit);
9162 /* patch tag for literals that are cast to pointers */
9163 if (IS_CODEPTR(restype)) {
9164 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9165 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9167 if (IS_GENPTR(restype))
9169 if (IS_CODEPTR(rtype)) {
9170 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9171 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9172 } else if (PIC_IS_DATA_PTR(rtype)) {
9173 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9174 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9175 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9176 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9177 } else if (IS_PTR(rtype)) {
9178 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9179 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9185 unsigned long lit_int;
9190 if(IS_FIXED16X16(operandType(right))) {
9191 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9193 /* take care if literal is a float */
9194 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9200 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9201 // sizeof(unsigned long int), sizeof(float));
9204 if (AOP_TYPE(right) == AOP_REG) {
9205 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9207 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9212 /* when do we have to read the program memory?
9213 * - if right itself is a symbol in code space
9214 * (we don't care what it points to if it's a pointer)
9215 * - AND right is not a function (we would want its address)
9217 if(AOP_TYPE(right) != AOP_LIT
9218 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9219 && !IS_FUNC(OP_SYM_TYPE(right))
9220 && !IS_ITEMP(right)) {
9222 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9223 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9225 // set up table pointer
9226 if(pic16_isLitOp(right)) {
9227 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9228 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9229 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9230 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9231 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9232 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9233 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9235 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9236 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9237 pic16_popCopyReg(&pic16_pc_tblptrl)));
9238 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9239 pic16_popCopyReg(&pic16_pc_tblptrh)));
9240 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9241 pic16_popCopyReg(&pic16_pc_tblptru)));
9244 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9245 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9247 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9248 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9249 pic16_popGet(AOP(result),offset)));
9253 /* FIXME: for pointers we need to extend differently (according
9254 * to pointer type DATA/CODE/EEPROM/... :*/
9255 size = getSize(OP_SYM_TYPE(right));
9256 if(AOP_SIZE(result) > size) {
9257 size = AOP_SIZE(result) - size;
9259 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9267 /* VR - What is this?! */
9268 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9269 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9271 if(aopIdx(AOP(result),0) == 4) {
9272 /* this is a workaround to save value of right into wreg too,
9273 * value of wreg is going to be used later */
9274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9275 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9280 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9284 size = AOP_SIZE(right);
9285 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9288 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
9289 if(AOP_TYPE(right) == AOP_LIT) {
9291 if(know_W != (lit&0xff))
9292 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9294 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9296 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9300 } else if (AOP_TYPE(right) == AOP_CRY) {
9301 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9303 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9304 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9305 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9307 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9308 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9309 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9313 if(!_G.resDirect) { /* use this aopForSym feature */
9314 if(AOP_TYPE(result) == AOP_ACC) {
9315 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9317 if(AOP_TYPE(right) == AOP_ACC) {
9318 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9320 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9327 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9330 pic16_freeAsmop (right,NULL,ic,FALSE);
9331 pic16_freeAsmop (result,NULL,ic,TRUE);
9334 /*-----------------------------------------------------------------*/
9335 /* genJumpTab - generates code for jump table */
9336 /*-----------------------------------------------------------------*/
9337 static void genJumpTab (iCode *ic)
9342 pCodeOp *jt_offs_hi;
9347 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9348 /* get the condition into accumulator */
9349 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9351 /* multiply by three */
9352 pic16_emitcode("add","a,acc");
9353 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9355 jtab = newiTempLabel(NULL);
9356 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9357 pic16_emitcode("jmp","@a+dptr");
9358 pic16_emitcode("","%05d_DS_:",jtab->key+100);
9361 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9362 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9364 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9365 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9366 pic16_emitpLabel(jtab->key);
9370 jt_offs = pic16_popGetTempReg(0);
9371 jt_offs_hi = pic16_popGetTempReg(1);
9372 jt_label = pic16_popGetLabel (jtab->key);
9373 //fprintf (stderr, "Creating jump table...\n");
9375 // calculate offset into jump table (idx * sizeof (GOTO))
9376 pic16_emitpcode(POC_CLRF , jt_offs_hi);
9377 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9378 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9379 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9380 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9381 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9382 pic16_emitpcode(POC_MOVWF , jt_offs);
9384 // prepare PCLATx (set to first entry in jump table)
9385 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9386 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9387 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9388 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9389 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9391 // set PCLATx to selected entry (new PCL is stored in jt_offs)
9392 pic16_emitpcode(POC_ADDWF , jt_offs);
9393 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9394 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9396 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
9398 // release temporaries and prepare jump into table (new PCL --> WREG)
9399 pic16_emitpcode(POC_MOVFW , jt_offs);
9400 pic16_popReleaseTempReg (jt_offs_hi, 1);
9401 pic16_popReleaseTempReg (jt_offs, 0);
9403 // jump into the table
9404 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9406 pic16_emitpLabelFORCE(jtab->key);
9409 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9410 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9412 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9413 /* now generate the jump labels */
9414 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9415 jtab = setNextItem(IC_JTLABELS(ic))) {
9416 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9417 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9420 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9424 /*-----------------------------------------------------------------*/
9425 /* genMixedOperation - gen code for operators between mixed types */
9426 /*-----------------------------------------------------------------*/
9428 TSD - Written for the PIC port - but this unfortunately is buggy.
9429 This routine is good in that it is able to efficiently promote
9430 types to different (larger) sizes. Unfortunately, the temporary
9431 variables that are optimized out by this routine are sometimes
9432 used in other places. So until I know how to really parse the
9433 iCode tree, I'm going to not be using this routine :(.
9435 static int genMixedOperation (iCode *ic)
9438 operand *result = IC_RESULT(ic);
9439 sym_link *ctype = operandType(IC_LEFT(ic));
9440 operand *right = IC_RIGHT(ic);
9446 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9448 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9454 nextright = IC_RIGHT(nextic);
9455 nextleft = IC_LEFT(nextic);
9456 nextresult = IC_RESULT(nextic);
9458 pic16_aopOp(right,ic,FALSE);
9459 pic16_aopOp(result,ic,FALSE);
9460 pic16_aopOp(nextright, nextic, FALSE);
9461 pic16_aopOp(nextleft, nextic, FALSE);
9462 pic16_aopOp(nextresult, nextic, FALSE);
9464 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9470 pic16_emitcode(";remove right +","");
9472 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9478 pic16_emitcode(";remove left +","");
9482 big = AOP_SIZE(nextleft);
9483 small = AOP_SIZE(nextright);
9485 switch(nextic->op) {
9488 pic16_emitcode(";optimize a +","");
9489 /* if unsigned or not an integral type */
9490 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9491 pic16_emitcode(";add a bit to something","");
9494 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9496 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9497 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9498 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9500 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9508 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9509 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9510 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9513 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9515 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9516 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9517 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9518 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9519 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9522 pic16_emitcode("rlf","known_zero,w");
9529 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9530 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9531 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9533 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9543 pic16_freeAsmop(right,NULL,ic,TRUE);
9544 pic16_freeAsmop(result,NULL,ic,TRUE);
9545 pic16_freeAsmop(nextright,NULL,ic,TRUE);
9546 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9548 nextic->generated = 1;
9555 /*-----------------------------------------------------------------*/
9556 /* genCast - gen code for casting */
9557 /*-----------------------------------------------------------------*/
9558 static void genCast (iCode *ic)
9560 operand *result = IC_RESULT(ic);
9561 sym_link *ctype = operandType(IC_LEFT(ic));
9562 sym_link *rtype = operandType(IC_RIGHT(ic));
9563 sym_link *restype = operandType(IC_RESULT(ic));
9564 operand *right = IC_RIGHT(ic);
9570 /* if they are equivalent then do nothing */
9571 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9574 pic16_aopOp(result,ic,FALSE);
9575 pic16_aopOp(right,ic,FALSE) ;
9577 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9580 /* if the result is a bit */
9581 if (AOP_TYPE(result) == AOP_CRY) {
9583 /* if the right size is a literal then
9584 * we know what the value is */
9585 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9587 if (AOP_TYPE(right) == AOP_LIT) {
9588 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9589 pic16_popGet(AOP(result),0));
9591 if (((int) operandLitValue(right)))
9592 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9593 AOP(result)->aopu.aop_dir,
9594 AOP(result)->aopu.aop_dir);
9596 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9597 AOP(result)->aopu.aop_dir,
9598 AOP(result)->aopu.aop_dir);
9602 /* the right is also a bit variable */
9603 if (AOP_TYPE(right) == AOP_CRY) {
9605 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9607 pic16_emitcode("clrc","");
9608 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9609 AOP(right)->aopu.aop_dir,
9610 AOP(right)->aopu.aop_dir);
9611 pic16_aopPut(AOP(result),"c",0);
9616 if (AOP_TYPE(right) == AOP_REG) {
9617 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9618 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9619 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9621 pic16_toBoolean(right);
9622 pic16_aopPut(AOP(result),"a",0);
9626 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9629 size = AOP_SIZE(result);
9631 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9633 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9634 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9635 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9638 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9643 if(IS_BITFIELD(getSpec(restype))
9644 && IS_BITFIELD(getSpec(rtype))) {
9645 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9648 /* port from pic14 to cope with generic pointers */
9649 if (PIC_IS_TAGGED(restype))
9651 operand *result = IC_RESULT(ic);
9652 //operand *left = IC_LEFT(ic);
9653 operand *right = IC_RIGHT(ic);
9656 /* copy common part */
9657 int max, size = AOP_SIZE(result);
9658 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9659 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9664 pic16_mov2w (AOP(right), size);
9665 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9668 /* upcast into generic pointer type? */
9669 if (IS_GENPTR(restype)
9670 && !PIC_IS_TAGGED(rtype)
9671 && (AOP_SIZE(result) > max))
9673 /* determine appropriate tag for right */
9674 if (PIC_IS_DATA_PTR(rtype))
9675 tag = GPTR_TAG_DATA;
9676 else if (IS_CODEPTR(rtype))
9677 tag = GPTR_TAG_CODE;
9678 else if (PIC_IS_DATA_PTR(ctype)) {
9679 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9680 tag = GPTR_TAG_DATA;
9681 } else if (IS_CODEPTR(ctype)) {
9682 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9683 tag = GPTR_TAG_CODE;
9684 } else if (IS_PTR(rtype)) {
9685 PERFORM_ONCE(weirdcast,
9686 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9688 tag = GPTR_TAG_DATA;
9690 PERFORM_ONCE(weirdcast,
9691 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9693 tag = GPTR_TAG_DATA;
9696 assert (AOP_SIZE(result) == 3);
9697 /* zero-extend address... */
9698 for (size = max; size < AOP_SIZE(result)-1; size++)
9699 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9700 /* ...and add tag */
9701 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9702 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9703 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9704 for (size = max; size < AOP_SIZE(result)-1; size++)
9705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9706 /* add __code tag */
9707 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9708 } else if (AOP_SIZE(result) > max) {
9709 /* extend non-pointers */
9710 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9711 pic16_addSign(result, max, 0);
9716 /* if they are the same size : or less */
9717 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9719 /* if they are in the same place */
9720 if (pic16_sameRegs(AOP(right),AOP(result)))
9723 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9725 if (IS_PTR_CONST(rtype))
9727 if (IS_CODEPTR(rtype))
9729 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9732 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9734 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9736 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9738 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9739 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9740 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9742 if(AOP_SIZE(result) < 2) {
9743 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9745 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9746 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9749 /* if they in different places then copy */
9750 size = AOP_SIZE(result);
9753 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9754 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9761 /* if the result is of type pointer */
9762 if (IS_PTR(ctype)) {
9764 sym_link *type = operandType(right);
9765 sym_link *etype = getSpec(type);
9767 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
9769 /* pointer to generic pointer */
9770 if (IS_GENPTR(ctype)) {
9774 p_type = DCL_TYPE(type);
9776 /* we have to go by the storage class */
9777 p_type = PTR_TYPE(SPEC_OCLS(etype));
9779 /* if (SPEC_OCLS(etype)->codesp ) */
9780 /* p_type = CPOINTER ; */
9782 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9783 /* p_type = FPOINTER ; */
9785 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9786 /* p_type = PPOINTER; */
9788 /* if (SPEC_OCLS(etype) == idata ) */
9789 /* p_type = IPOINTER ; */
9791 /* p_type = POINTER ; */
9794 /* the first two bytes are known */
9795 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
9796 size = GPTRSIZE - 1;
9799 if(offset < AOP_SIZE(right)) {
9800 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9801 pic16_mov2f(AOP(result), AOP(right), offset);
9803 if ((AOP_TYPE(right) == AOP_PCODE) &&
9804 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9805 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9806 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9809 pic16_aopPut(AOP(result),
9810 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9815 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9818 /* the last byte depending on type */
9823 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9827 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9831 pic16_emitcode(";BUG!? ","%d",__LINE__);
9836 if (GPTRSIZE > AOP_SIZE(right)) {
9837 // assume __data pointer... THIS MIGHT BE WRONG!
9838 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9840 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9845 /* this should never happen */
9846 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9847 "got unknown pointer type");
9850 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9856 /* just copy the pointers */
9857 size = AOP_SIZE(result);
9860 pic16_aopPut(AOP(result),
9861 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9870 /* so we now know that the size of destination is greater
9871 than the size of the source.
9872 Now, if the next iCode is an operator then we might be
9873 able to optimize the operation without performing a cast.
9875 if(genMixedOperation(ic))
9878 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9880 /* we move to result for the size of source */
9881 size = AOP_SIZE(right);
9886 pic16_mov2f(AOP(result), AOP(right), offset);
9890 /* now depending on the sign of the destination */
9891 size = AOP_SIZE(result) - AOP_SIZE(right);
9892 /* if unsigned or not an integral type */
9893 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9895 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9897 /* we need to extend the sign :( */
9900 /* Save one instruction of casting char to int */
9901 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9902 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9903 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
9905 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9908 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9910 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9912 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9915 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
9920 pic16_freeAsmop(right,NULL,ic,TRUE);
9921 pic16_freeAsmop(result,NULL,ic,TRUE);
9925 /*-----------------------------------------------------------------*/
9926 /* genDjnz - generate decrement & jump if not zero instrucion */
9927 /*-----------------------------------------------------------------*/
9928 static int genDjnz (iCode *ic, iCode *ifx)
9931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9936 /* if the if condition has a false label
9937 then we cannot save */
9941 /* if the minus is not of the form
9943 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9944 !IS_OP_LITERAL(IC_RIGHT(ic)))
9947 if (operandLitValue(IC_RIGHT(ic)) != 1)
9950 /* if the size of this greater than one then no
9952 if (getSize(operandType(IC_RESULT(ic))) > 1)
9955 /* otherwise we can save BIG */
9956 lbl = newiTempLabel(NULL);
9957 lbl1= newiTempLabel(NULL);
9959 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9961 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9962 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9964 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9969 /*-----------------------------------------------------------------*/
9970 /* genReceive - generate code for a receive iCode */
9971 /*-----------------------------------------------------------------*/
9972 static void genReceive (iCode *ic)
9978 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
9979 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
9981 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
9983 if (isOperandInFarSpace(IC_RESULT(ic))
9984 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
9985 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9987 int size = getSize(operandType(IC_RESULT(ic)));
9988 int offset = pic16_fReturnSizePic - size;
9992 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9993 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9997 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
9999 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10000 size = AOP_SIZE(IC_RESULT(ic));
10003 pic16_emitcode ("pop","acc");
10004 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10007 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10009 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10012 /* set pseudo stack pointer to where it should be - dw*/
10013 GpsuedoStkPtr = ic->parmBytes;
10015 /* setting GpsuedoStkPtr has side effects here: */
10016 /* FIXME: What's the correct size of the return(ed) value?
10017 * For now, assuming '4' as before... */
10018 assignResultValue(IC_RESULT(ic), 4, 0);
10021 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10024 /*-----------------------------------------------------------------*/
10025 /* genDummyRead - generate code for dummy read of volatiles */
10026 /*-----------------------------------------------------------------*/
10028 genDummyRead (iCode * ic)
10033 if (op && IS_SYMOP(op)) {
10034 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10035 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10038 pic16_aopOp (op, ic, FALSE);
10039 pic16_mov2w_volatile(AOP(op));
10040 pic16_freeAsmop (op, NULL, ic, TRUE);
10042 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10046 /*-----------------------------------------------------------------*/
10047 /* genpic16Code - generate code for pic16 based controllers */
10048 /*-----------------------------------------------------------------*/
10050 * At this point, ralloc.c has gone through the iCode and attempted
10051 * to optimize in a way suitable for a PIC. Now we've got to generate
10052 * PIC instructions that correspond to the iCode.
10054 * Once the instructions are generated, we'll pass through both the
10055 * peep hole optimizer and the pCode optimizer.
10056 *-----------------------------------------------------------------*/
10058 void genpic16Code (iCode *lic)
10063 lineHead = lineCurr = NULL;
10065 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10066 pic16_addpBlock(pb);
10069 /* if debug information required */
10070 if (options.debug && currFunc) {
10072 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10077 for (ic = lic ; ic ; ic = ic->next ) {
10079 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10080 if ( cln != ic->lineno ) {
10081 if ( options.debug ) {
10082 debugFile->writeCLine (ic);
10085 if(!options.noCcodeInAsm) {
10086 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10087 printCLine(ic->filename, ic->lineno)));
10093 if(options.iCodeInAsm) {
10096 /* insert here code to print iCode as comment */
10097 iLine = printILine(ic);
10098 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10102 /* if the result is marked as
10103 * spilt and rematerializable or code for
10104 * this has already been generated then
10106 if (resultRemat(ic) || ic->generated )
10109 /* depending on the operation */
10128 /* IPOP happens only when trying to restore a
10129 * spilt live range, if there is an ifx statement
10130 * following this pop then the if statement might
10131 * be using some of the registers being popped which
10132 * would destroy the contents of the register so
10133 * we need to check for this condition and handle it */
10135 && ic->next->op == IFX
10136 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10137 genIfx (ic->next,ic);
10155 genEndFunction (ic);
10171 pic16_genPlus (ic) ;
10175 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10176 pic16_genMinus (ic);
10192 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10196 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10202 /* note these two are xlated by algebraic equivalence
10203 * during parsing SDCC.y */
10204 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10205 "got '>=' or '<=' shouldn't have come here");
10209 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10221 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10225 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10229 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10253 genRightShift (ic);
10256 case GET_VALUE_AT_ADDRESS:
10261 if (POINTER_SET(ic))
10288 addSet(&_G.sendSet,ic);
10291 case DUMMY_READ_VOLATILE:
10301 /* now we are ready to call the
10302 peep hole optimizer */
10303 if (!options.nopeep)
10304 peepHole (&lineHead);
10306 /* now do the actual printing */
10307 printLine (lineHead, codeOutBuf);
10310 DFPRINTF((stderr,"printing pBlock\n\n"));
10311 pic16_printpBlock(stdout,pb);