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)
12 Bug Fixes - Mauro Giachero <maurogiachero AT users.sourceforge.net> (2008)
14 This program is free software; you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by the
16 Free Software Foundation; either version 2, or (at your option) any
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 In other words, you are welcome to use, share and improve this program.
29 You are forbidden to forbid anyone else to use, share and improve
30 what you give them. Help stamp out software-hoarding!
33 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
34 Made everything static
35 -------------------------------------------------------------------------*/
41 #include "SDCCglobl.h"
45 #include "SDCCpeeph.h"
54 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
55 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
57 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
58 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
60 /* Wrapper to execute `code' at most once. */
61 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
63 void pic16_genMult8X8_n (operand *, operand *,operand *);
64 extern void pic16_printpBlock(FILE *of, pBlock *pb);
65 static asmop *newAsmop (short type);
66 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
67 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
68 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
69 static pCodeOp *pic16_popRegFromIdx(int rIdx);
71 int pic16_labelOffset=0;
72 extern int pic16_debug_verbose;
76 /* max_key keeps track of the largest label number used in
77 a function. This is then used to adjust the label offset
78 for the next function.
81 static int GpsuedoStkPtr=0;
83 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
92 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
94 /* set the following macro to 1 to enable passing the
95 * first byte of functions parameters via WREG */
96 #define USE_WREG_IN_FUNC_PARAMS 0
99 /* this is the down and dirty file with all kinds of
100 kludgy & hacky stuff. This is what it is all about
101 CODE GENERATION for a specific MCU . some of the
102 routines may be reusable, will have to see */
103 static char *zero = "#0x00";
104 static char *one = "#0x01";
108 * Function return value policy (MSB-->LSB):
110 * 16 bits -> PRODL:WREG
111 * 24 bits -> PRODH:PRODL:WREG
112 * 32 bits -> FSR0L:PRODH:PRODL:WREG
113 * >32 bits -> on stack, and FSR0 points to the beginning
115 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
116 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
117 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
118 static char **fReturn = fReturnpic16;
120 static char *accUse[] = {"WREG"};
130 bitVect *fregsUsed; /* registers used in function */
132 set *sregsAllocSet; /* registers used to store stack variables */
133 int stack_lat; /* stack offset latency */
135 int useWreg; /* flag when WREG is used to pass function parameter */
138 extern struct dbuf_s *codeOutBuf;
140 static lineNode *lineHead = NULL;
141 static lineNode *lineCurr = NULL;
143 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
144 0xE0, 0xC0, 0x80, 0x00};
145 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
146 0x07, 0x03, 0x01, 0x00};
150 /*-----------------------------------------------------------------*/
151 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
152 /* exponent of 2 is returned, otherwise -1 is */
154 /* note that this is similar to the function `powof2' in SDCCsymt */
158 /*-----------------------------------------------------------------*/
159 int pic16_my_powof2 (unsigned long num)
162 if( (num & (num-1)) == 0) {
175 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
177 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
179 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
180 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
181 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
182 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
183 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
184 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
185 ((result) ? AOP_SIZE(result) : 0));
188 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
191 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
193 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
194 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
195 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
196 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
197 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
198 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
202 void pic16_emitpcomment (char *fmt, ...)
205 char lb[INITIAL_INLINEASM];
206 unsigned char *lbp = (unsigned char *)lb;
211 vsprintf(lb+1,fmt,ap);
213 while (isspace(*lbp)) lbp++;
216 lineCurr = (lineCurr ?
217 connectLine(lineCurr,newLineNode(lb)) :
218 (lineHead = newLineNode(lb)));
219 lineCurr->isInline = _G.inLine;
220 lineCurr->isDebug = _G.debugLine;
221 lineCurr->isComment = 1;
223 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
226 // fprintf(stderr, "%s\n", lb);
229 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
232 char lb[INITIAL_INLINEASM];
233 unsigned char *lbp = (unsigned char *)lb;
235 if(!pic16_debug_verbose)
242 sprintf(lb,"%s\t",inst);
244 sprintf(lb,"%s",inst);
245 vsprintf(lb+(strlen(lb)),fmt,ap);
249 while (isspace(*lbp)) lbp++;
252 lineCurr = (lineCurr ?
253 connectLine(lineCurr,newLineNode(lb)) :
254 (lineHead = newLineNode(lb)));
255 lineCurr->isInline = _G.inLine;
256 lineCurr->isDebug = _G.debugLine;
258 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
261 // fprintf(stderr, "%s\n", lb);
266 void pic16_emitpLabel(int key)
271 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
274 void pic16_emitpLabelFORCE(int key)
279 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
282 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
283 * NEVER call pic16_emitpcode_real directly, please... */
284 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
288 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
290 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
293 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
296 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
298 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
301 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
304 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
310 #define pic16_emitcode DEBUGpic16_emitcode
312 /*-----------------------------------------------------------------*/
313 /* pic16_emitcode - writes the code into a file : for now it is simple */
314 /*-----------------------------------------------------------------*/
315 void pic16_emitcode (char *inst,char *fmt, ...)
318 char lb[INITIAL_INLINEASM];
319 unsigned char *lbp = lb;
325 sprintf(lb,"%s\t",inst);
327 sprintf(lb,"%s",inst);
328 vsprintf(lb+(strlen(lb)),fmt,ap);
332 while (isspace(*lbp)) lbp++;
335 lineCurr = (lineCurr ?
336 connectLine(lineCurr,newLineNode(lb)) :
337 (lineHead = newLineNode(lb)));
338 lineCurr->isInline = _G.inLine;
339 lineCurr->isDebug = _G.debugLine;
340 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
341 lineCurr->isComment = (*lbp == ';');
343 // VR fprintf(stderr, "lb = <%s>\n", lbp);
345 // if(pic16_debug_verbose)
346 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitDebuggerSymbol - associate the current code location */
355 /* with a debugger symbol */
356 /*-----------------------------------------------------------------*/
358 pic16_emitDebuggerSymbol (char * debugSym)
361 pic16_emitcode (";", "%s ==.", debugSym);
365 /*-----------------------------------------------------------------*/
366 /* newAsmop - creates a new asmOp */
367 /*-----------------------------------------------------------------*/
368 static asmop *newAsmop (short type)
372 aop = Safe_calloc(1,sizeof(asmop));
377 /*-----------------------------------------------------------------*/
378 /* resolveIfx - converts an iCode ifx into a form more useful for */
379 /* generating code */
380 /*-----------------------------------------------------------------*/
381 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
385 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
391 resIfx->condition = 1; /* assume that the ifx is true */
392 resIfx->generated = 0; /* indicate that the ifx has not been used */
395 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
398 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
399 __FUNCTION__,__LINE__,resIfx->lbl->key);
404 resIfx->lbl = IC_TRUE(ifx);
406 resIfx->lbl = IC_FALSE(ifx);
407 resIfx->condition = 0;
412 DEBUGpic16_emitcode("; +++","ifx true is non-null");
414 DEBUGpic16_emitcode("; +++","ifx true is null");
416 DEBUGpic16_emitcode("; +++","ifx false is non-null");
418 DEBUGpic16_emitcode("; +++","ifx false is null");
422 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
426 /*-----------------------------------------------------------------*/
427 /* pointerCode - returns the code for a pointer type */
428 /*-----------------------------------------------------------------*/
429 static int pointerCode (sym_link *etype)
432 return PTR_TYPE(SPEC_OCLS(etype));
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol */
439 /*-----------------------------------------------------------------*/
440 static asmop *aopForSym (iCode *ic, operand *op, bool result)
442 symbol *sym=OP_SYMBOL(op);
444 memmap *space= SPEC_OCLS(sym->etype);
448 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
450 // sym = OP_SYMBOL(op);
452 /* if already has one */
454 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
459 /* if symbol was initially placed onStack then we must re-place it
460 * to direct memory, since pic16 does not have a specific stack */
462 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
470 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
472 sym->aop = aop = newAsmop (AOP_PAGED);
473 aop->aopu.aop_dir = sym->rname ;
474 aop->size = getSize(sym->type);
475 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
476 pic16_allocDirReg( IC_LEFT(ic) );
484 /* assign depending on the storage class */
485 /* if it is on the stack or indirectly addressable */
486 /* space we need to assign either r0 or r1 to it */
487 if (sym->onStack) // || sym->iaccess)
492 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
493 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
495 /* acquire a temporary register -- it is saved in function */
497 sym->aop = aop = newAsmop(AOP_STA);
498 aop->aopu.stk.stk = sym->stack;
499 aop->size = getSize(sym->type);
502 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
503 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
504 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
505 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
507 for(i=0;i<aop->size;i++)
508 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
509 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
511 if(1 && ic->op == SEND) {
513 /* if SEND do the send here */
516 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
517 for(i=0;i<aop->size;i++) {
518 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
519 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
524 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
527 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
529 // we do not need to load the value if it is to be defined...
530 if (result) return aop;
533 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
536 for(i=0;i<aop->size;i++) {
538 /* initialise for stack access via frame pointer */
539 // operands on stack are accessible via "{FRAME POINTER} + index" with index
540 // starting at 2 for arguments and growing from 0 downwards for
541 // local variables (index == 0 is not assigned so we add one here)
543 int soffs = sym->stack;
549 if(1 && ic->op == SEND) {
550 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
551 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
552 pic16_popCopyReg( pic16_frame_plusw ),
553 pic16_popCopyReg(pic16_stack_postdec )));
555 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
556 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
557 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
563 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
570 /* now assign the address of the variable to
571 the pointer register */
572 if (aop->type != AOP_STK) {
576 pic16_emitcode("push","acc");
578 pic16_emitcode("mov","a,_bp");
579 pic16_emitcode("add","a,#0x%02x",
581 ((char)(sym->stack - _G.nRegsSaved )) :
582 ((char)sym->stack)) & 0xff);
583 pic16_emitcode("mov","%s,a",
584 aop->aopu.aop_ptr->name);
587 pic16_emitcode("pop","acc");
589 pic16_emitcode("mov","%s,#%s",
590 aop->aopu.aop_ptr->name,
592 aop->paged = space->paged;
594 aop->aopu.aop_stk = sym->stack;
602 /* special case for a function */
603 if (IS_FUNC(sym->type)) {
604 sym->aop = aop = newAsmop(AOP_PCODE);
605 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
606 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
607 PCOI(aop->aopu.pcop)->index = 0;
608 aop->size = FPTRSIZE;
609 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
616 //DEBUGpic16_emitcode(";","%d",__LINE__);
617 /* if in bit space */
618 if (IN_BITSPACE(space)) {
619 sym->aop = aop = newAsmop (AOP_CRY);
620 aop->aopu.aop_dir = sym->rname ;
621 aop->size = getSize(sym->type);
622 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
625 /* if it is in direct space */
626 if (IN_DIRSPACE(space)) {
627 if(!strcmp(sym->rname, "_WREG")) {
628 sym->aop = aop = newAsmop (AOP_ACC);
629 aop->size = getSize(sym->type); /* should always be 1 */
630 assert(aop->size == 1);
631 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
634 sym->aop = aop = newAsmop (AOP_DIR);
635 aop->aopu.aop_dir = sym->rname ;
636 aop->size = getSize(sym->type);
637 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
638 pic16_allocDirReg( IC_LEFT(ic) );
643 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
644 sym->aop = aop = newAsmop (AOP_DIR);
645 aop->aopu.aop_dir = sym->rname ;
646 aop->size = getSize(sym->type);
647 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
648 pic16_allocDirReg( IC_LEFT(ic) );
653 /* only remaining is far space */
654 sym->aop = aop = newAsmop(AOP_PCODE);
656 /* change the next if to 1 to revert to good old immediate code */
657 if(IN_CODESPACE(space)) {
658 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
659 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
660 PCOI(aop->aopu.pcop)->index = 0;
662 /* try to allocate via direct register */
663 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
664 // aop->size = getSize( sym->type );
667 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
668 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
671 if(!pic16_allocDirReg (IC_LEFT(ic)))
675 if(IN_DIRSPACE( space ))
677 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
678 aop->size = FPTRSIZE;
679 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
680 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
681 else if(sym->onStack) {
684 if(SPEC_SCLS(sym->etype) == S_PDATA) {
685 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
686 aop->size = FPTRSIZE;
691 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
693 /* if it is in code space */
694 if (IN_CODESPACE(space))
700 /*-----------------------------------------------------------------*/
701 /* aopForRemat - rematerialzes an object */
702 /*-----------------------------------------------------------------*/
703 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
705 symbol *sym = OP_SYMBOL(op);
707 iCode *ic = NULL, *oldic;
708 asmop *aop = newAsmop(AOP_PCODE);
715 ic = sym->rematiCode;
717 if(IS_OP_POINTER(op)) {
718 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
721 // if(!result) /* fixme-vr */
725 // chat *iLine = printILine(ic);
726 // pic16_emitpcomment("ic: %s\n", iLine);
730 val += (int) operandLitValue(IC_RIGHT(ic));
731 } else if (ic->op == '-') {
732 val -= (int) operandLitValue(IC_RIGHT(ic));
736 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
739 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
742 if(!op->isaddr)viaimmd++; else viaimmd=0;
744 /* set the following if to 1 to revert to good old immediate code */
745 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
748 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
750 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
753 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
755 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
758 PCOI(aop->aopu.pcop)->index = val;
760 aop->size = getSize( sym->type );
762 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
764 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
765 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
767 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
771 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
772 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
774 val, IS_PTR_CONST(operandType(op)));
776 val, IS_CODEPTR(operandType(op)));
779 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
781 pic16_allocDirReg (IC_LEFT(ic));
783 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
790 static int aopIdx (asmop *aop, int offset)
795 if(aop->type != AOP_REG)
798 return aop->aopu.aop_reg[offset]->rIdx;
803 /*-----------------------------------------------------------------*/
804 /* regsInCommon - two operands have some registers in common */
805 /*-----------------------------------------------------------------*/
806 static bool regsInCommon (operand *op1, operand *op2)
811 /* if they have registers in common */
812 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
815 sym1 = OP_SYMBOL(op1);
816 sym2 = OP_SYMBOL(op2);
818 if (sym1->nRegs == 0 || sym2->nRegs == 0)
821 for (i = 0 ; i < sym1->nRegs ; i++) {
826 for (j = 0 ; j < sym2->nRegs ;j++ ) {
830 if (sym2->regs[j] == sym1->regs[i])
838 /*-----------------------------------------------------------------*/
839 /* operandsEqu - equivalent */
840 /*-----------------------------------------------------------------*/
841 static bool operandsEqu ( operand *op1, operand *op2)
845 /* if they not symbols */
846 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
849 sym1 = OP_SYMBOL(op1);
850 sym2 = OP_SYMBOL(op2);
852 /* if both are itemps & one is spilt
853 and the other is not then false */
854 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
855 sym1->isspilt != sym2->isspilt )
858 /* if they are the same */
862 if (sym1->rname[0] && sym2->rname[0]
863 && strcmp (sym1->rname, sym2->rname) == 0)
867 /* if left is a tmp & right is not */
871 (sym1->usl.spillLoc == sym2))
878 (sym2->usl.spillLoc == sym1))
884 /*-----------------------------------------------------------------*/
885 /* pic16_sameRegs - two asmops have the same registers */
886 /*-----------------------------------------------------------------*/
887 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
894 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
895 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
897 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
899 if (aop1->type != AOP_REG ||
900 aop2->type != AOP_REG )
903 /* This is a bit too restrictive if one is a subset of the other...
904 if (aop1->size != aop2->size )
908 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
909 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
911 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
912 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
919 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
921 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
922 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
924 if(aop1 == aop2)return TRUE;
925 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
927 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
933 /*-----------------------------------------------------------------*/
934 /* pic16_aopOp - allocates an asmop for an operand : */
935 /*-----------------------------------------------------------------*/
936 void pic16_aopOp (operand *op, iCode *ic, bool result)
945 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
947 /* if this a literal */
948 if (IS_OP_LITERAL(op)) {
949 op->aop = aop = newAsmop(AOP_LIT);
950 aop->aopu.aop_lit = op->operand.valOperand;
951 aop->size = getSize(operandType(op));
956 sym_link *type = operandType(op);
958 if(IS_PTR_CONST(type))
962 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
965 /* if already has a asmop then continue */
969 /* if the underlying symbol has a aop */
970 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
971 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
972 op->aop = OP_SYMBOL(op)->aop;
976 /* if this is a true symbol */
977 if (IS_TRUE_SYMOP(op)) {
978 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
979 op->aop = aopForSym(ic, op, result);
983 /* this is a temporary : this has
989 e) can be a return use only */
993 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
994 /* if the type is a conditional */
995 if (sym->regType == REG_CND) {
996 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1001 /* if it is spilt then two situations
1003 b) has a spill location */
1004 if (sym->isspilt || sym->nRegs == 0) {
1006 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1007 DEBUGpic16_emitcode(";","%d",__LINE__);
1008 /* rematerialize it NOW */
1011 sym->aop = op->aop = aop = aopForRemat (op, result);
1018 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1019 aop->size = getSize(sym->type);
1020 for ( i = 0 ; i < 1 ; i++ ) {
1021 aop->aopu.aop_str[i] = accUse[i];
1022 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1024 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1025 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1033 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1034 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1035 //pic16_allocDirReg (IC_LEFT(ic));
1036 aop->size = getSize(sym->type);
1041 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1042 aop->size = getSize(sym->type);
1043 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1044 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1046 DEBUGpic16_emitcode(";","%d",__LINE__);
1050 /* else spill location */
1051 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1052 /* force a new aop if sizes differ */
1053 sym->usl.spillLoc->aop = NULL;
1057 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1058 __FUNCTION__,__LINE__,
1059 sym->usl.spillLoc->rname,
1060 sym->rname, sym->usl.spillLoc->offset);
1063 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1064 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1065 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1066 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1068 sym->usl.spillLoc->offset, op);
1069 } else if (getSize(sym->type) <= 1) {
1070 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1071 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1072 assert (getSize(sym->type) <= 1);
1073 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1074 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1076 /* We need some kind of dummy area for getSize(sym->type) byte,
1077 * use WREG for all storage locations.
1078 * XXX: This only works if we are implementing a `dummy read',
1079 * the stored value will not be retrievable...
1080 * See #1503234 for a case requiring this. */
1081 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1082 aop->size = getSize(sym->type);
1083 for ( i = 0 ; i < aop->size ;i++)
1084 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1086 aop->size = getSize(sym->type);
1092 sym_link *type = operandType(op);
1094 if(IS_PTR_CONST(type))
1096 if(IS_CODEPTR(type))
1098 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1101 /* must be in a register */
1102 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1103 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1104 aop->size = sym->nRegs;
1105 for ( i = 0 ; i < sym->nRegs ;i++)
1106 aop->aopu.aop_reg[i] = sym->regs[i];
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_freeAsmop - free up the asmop given to an operand */
1111 /*----------------------------------------------------------------*/
1112 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1130 switch (aop->type) {
1135 /* we must store the result on stack */
1136 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1137 // operands on stack are accessible via "FSR2 + index" with index
1138 // starting at 2 for arguments and growing from 0 downwards for
1139 // local variables (index == 0 is not assigned so we add one here)
1140 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1145 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1146 for(i=0;i<aop->size;i++) {
1147 /* initialise for stack access via frame pointer */
1148 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1149 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1150 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1153 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1157 for(i=0;i<aop->size;i++) {
1158 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1160 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1161 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1162 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1169 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1170 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1171 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1172 deleteSetItem( &_G.sregsAllocSet, sr );
1183 int stk = aop->aopu.aop_stk + aop->size;
1184 bitVectUnSetBit(ic->rUsed,R0_IDX);
1185 bitVectUnSetBit(ic->rUsed,R1_IDX);
1187 getFreePtr(ic,&aop,FALSE);
1189 if (options.stack10bit)
1191 /* I'm not sure what to do here yet... */
1194 "*** Warning: probably generating bad code for "
1195 "10 bit stack mode.\n");
1199 pic16_emitcode ("mov","a,_bp");
1200 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1201 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1203 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1207 pic16_emitcode("pop","acc");
1208 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1210 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1213 pic16_freeAsmop(op,NULL,ic,TRUE);
1215 pic16_emitcode("pop","ar0");
1220 pic16_emitcode("pop","ar1");
1230 /* all other cases just dealloc */
1234 OP_SYMBOL(op)->aop = NULL;
1235 /* if the symbol has a spill */
1237 SPIL_LOC(op)->aop = NULL;
1242 /*-----------------------------------------------------------------*/
1243 /* pic16_aopGet - for fetching value of the aop */
1244 /*-----------------------------------------------------------------*/
1245 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1250 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1252 /* offset is greater than size then zero */
1253 if (offset > (aop->size - 1) &&
1254 aop->type != AOP_LIT)
1257 /* depending on type */
1258 switch (aop->type) {
1261 sprintf(s,"(%s + %d)",
1264 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1266 sprintf(s,"%s",aop->aopu.aop_dir);
1267 rs = Safe_calloc(1,strlen(s)+1);
1272 return aop->aopu.aop_reg[offset]->name;
1275 return aop->aopu.aop_dir;
1278 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1279 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1281 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1282 rs = Safe_strdup("WREG");
1286 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1287 rs = Safe_calloc(1,strlen(s)+1);
1292 aop->coff = offset ;
1294 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1297 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1298 aop->type = AOP_ACC;
1299 return Safe_strdup("_WREG");
1301 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1303 return aop->aopu.aop_str[offset];
1307 pCodeOp *pcop = aop->aopu.pcop;
1308 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1310 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1311 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1313 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1315 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1318 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1321 rs = Safe_calloc(1,strlen(s)+1);
1327 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1329 sprintf(s,"(%s + %d)",
1333 sprintf(s,"%s",aop->aopu.aop_dir);
1334 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1335 rs = Safe_calloc(1,strlen(s)+1);
1341 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1345 // pCodeOp *pcop = aop->aop
1350 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1351 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1352 "aopget got unsupported aop->type");
1358 /* lock has the following meaning: When allocating temporary registers
1359 * for stack variables storage, the value of the temporary register is
1360 * saved on stack. Its value is restored at the end. This procedure is
1361 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1362 * a possibility that before a call to pic16_aopOp, a temporary register
1363 * is allocated for a while and it is freed after some time, this will
1364 * mess the stack and values will not be restored properly. So use lock=1
1365 * to allocate temporary registers used internally by the programmer, and
1366 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1367 * to inform the compiler developer about a possible bug. This is an internal
1368 * feature for developing the compiler -- VR */
1370 int _TempReg_lock = 0;
1371 /*-----------------------------------------------------------------*/
1372 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1373 /*-----------------------------------------------------------------*/
1374 pCodeOp *pic16_popGetTempReg(int lock)
1379 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1381 // werror(W_POSSBUG2, __FILE__, __LINE__);
1384 _TempReg_lock += lock;
1389 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1390 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1391 PCOR(pcop)->r->wasUsed=1;
1392 PCOR(pcop)->r->isFree=0;
1394 /* push value on stack */
1395 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1403 /*-----------------------------------------------------------------*/
1404 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1405 /* is not part of f, but don't save if */
1407 /*-----------------------------------------------------------------*/
1408 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1414 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1417 // werror(W_POSSBUG2, __FILE__, __LINE__);
1420 _TempReg_lock += lock;
1425 i = bitVectFirstBit(f);
1428 /* bypass registers that are used by function */
1429 if(!bitVectBitValue(f, i)) {
1431 /* bypass registers that are already allocated for stack access */
1432 if(!bitVectBitValue(v, i)) {
1434 // debugf("getting register rIdx = %d\n", i);
1435 /* ok, get the operand */
1436 pcop = pic16_newpCodeOpReg( i );
1438 /* should never by NULL */
1439 assert( pcop != NULL );
1443 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1446 PCOR(pcop)->r->wasUsed=1;
1447 PCOR(pcop)->r->isFree=0;
1453 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1455 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1456 /* already used in previous steps, break */
1463 /* caller takes care of the following */
1464 // bitVectSetBit(v, i);
1467 /* push value on stack */
1468 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1469 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1487 /*-----------------------------------------------------------------*/
1488 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1492 _TempReg_lock -= lock;
1494 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1495 PCOR(pcop)->r->isFree = 1;
1497 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLabel(int key)
1506 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1511 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1514 /*-----------------------------------------------------------------*/
1515 /* pic16_popCopyReg - copy a pcode operator */
1516 /*-----------------------------------------------------------------*/
1517 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1521 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1522 memcpy (pcor, pc, sizeof (pCodeOpReg));
1523 pcor->r->wasUsed = 1;
1525 //pcor->pcop.type = pc->pcop.type;
1527 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1528 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1530 pcor->pcop.name = NULL;
1533 //pcor->rIdx = pc->rIdx;
1534 //pcor->r->wasUsed=1;
1535 //pcor->instance = pc->instance;
1537 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1542 /*-----------------------------------------------------------------*/
1543 /* pic16_popGetLit - asm operator to pcode operator conversion */
1544 /*-----------------------------------------------------------------*/
1545 pCodeOp *pic16_popGetLit(int lit)
1547 return pic16_newpCodeOpLit(lit);
1550 /* Allow for 12 bit literals (LFSR x, <here!>). */
1551 pCodeOp *pic16_popGetLit12(int lit)
1553 return pic16_newpCodeOpLit12(lit);
1556 /*-----------------------------------------------------------------*/
1557 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1558 /*-----------------------------------------------------------------*/
1559 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1561 return pic16_newpCodeOpLit2(lit, arg2);
1565 /*-----------------------------------------------------------------*/
1566 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1567 /*-----------------------------------------------------------------*/
1568 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1570 return pic16_newpCodeOpImmd(name, offset,index, 0);
1574 /*-----------------------------------------------------------------*/
1575 /* pic16_popGet - asm operator to pcode operator conversion */
1576 /*-----------------------------------------------------------------*/
1577 pCodeOp *pic16_popGetWithString(char *str)
1583 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1587 pcop = pic16_newpCodeOp(str,PO_STR);
1592 /*-----------------------------------------------------------------*/
1593 /* pic16_popRegFromString - */
1594 /*-----------------------------------------------------------------*/
1595 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1598 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599 pcop->type = PO_DIR;
1601 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1602 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1607 pcop->name = Safe_calloc(1,strlen(str)+1);
1608 strcpy(pcop->name,str);
1610 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1612 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1613 // PCOR(pcop)->r->wasUsed = 1;
1615 /* make sure that register doesn't exist,
1616 * and operand isn't NULL
1617 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1618 if((PCOR(pcop)->r == NULL)
1620 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1621 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1622 // __FUNCTION__, __LINE__, str, size, offset);
1624 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1625 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1628 PCOR(pcop)->instance = offset;
1633 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1637 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1638 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1640 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1641 PCOR(pcop)->rIdx = rIdx;
1642 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1644 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1646 PCOR(pcop)->r->isFree = 0;
1647 PCOR(pcop)->r->wasUsed = 1;
1649 pcop->type = PCOR(pcop)->r->pc_type;
1654 /*---------------------------------------------------------------------------------*/
1655 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1657 /*---------------------------------------------------------------------------------*/
1658 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1660 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1661 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1667 /*--------------------------------------------------------------------------------.-*/
1668 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1669 /* VR 030601 , adapted by Hans Dorn */
1670 /*--------------------------------------------------------------------------------.-*/
1671 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1674 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1678 /*---------------------------------------------------------------------------------*/
1679 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1680 /* movff instruction */
1681 /*---------------------------------------------------------------------------------*/
1682 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1684 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1685 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGet - asm operator to pcode operator conversion */
1693 /*-----------------------------------------------------------------*/
1694 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1696 // char *s = buffer ;
1702 /* offset is greater than size then zero */
1704 // if (offset > (aop->size - 1) &&
1705 // aop->type != AOP_LIT)
1706 // return NULL; //zero;
1708 /* depending on type */
1709 switch (aop->type) {
1711 /* pCodeOp is already allocated from aopForSym */
1712 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1713 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1718 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1720 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1722 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1724 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1725 PCOR(pcop)->rIdx = rIdx;
1726 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1727 PCOR(pcop)->r->wasUsed=1;
1728 PCOR(pcop)->r->isFree=0;
1730 PCOR(pcop)->instance = offset;
1731 pcop->type = PCOR(pcop)->r->pc_type;
1732 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1736 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1737 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1743 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1744 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1748 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1749 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1756 // debugf2("aop = %p\toffset = %d\n", aop, offset);
1757 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
1758 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1760 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1762 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1763 // pcop->type = PO_GPR_REGISTER;
1764 PCOR(pcop)->rIdx = rIdx;
1765 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1766 PCOR(pcop)->r->wasUsed=1;
1767 PCOR(pcop)->r->isFree=0;
1769 PCOR(pcop)->instance = offset;
1770 pcop->type = PCOR(pcop)->r->pc_type;
1772 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1773 // rs = aop->aopu.aop_reg[offset]->name;
1774 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1779 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1781 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1782 PCOR(pcop)->instance = offset;
1783 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1784 //if(PCOR(pcop)->r == NULL)
1785 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1789 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1790 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1793 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1794 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1797 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1798 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1799 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1800 pcop->type = PCOR(pcop)->r->pc_type;
1801 pcop->name = PCOR(pcop)->r->name;
1807 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1809 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1810 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1811 switch( aop->aopu.pcop->type ) {
1812 case PO_DIR: PCOR(pcop)->instance += offset; break;
1813 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1818 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1819 assert( 0 ); /* should never reach here */;
1824 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1825 "pic16_popGet got unsupported aop->type");
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_aopPut - puts a string for a aop */
1830 /*-----------------------------------------------------------------*/
1831 void pic16_aopPut (asmop *aop, char *s, int offset)
1838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1840 if (aop->size && offset > ( aop->size - 1)) {
1841 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1842 "pic16_aopPut got offset > aop->size");
1846 /* will assign value to value */
1847 /* depending on where it is ofcourse */
1848 switch (aop->type) {
1851 sprintf(d,"(%s + %d)",
1852 aop->aopu.aop_dir,offset);
1853 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1856 sprintf(d,"%s",aop->aopu.aop_dir);
1859 DEBUGpic16_emitcode(";","%d",__LINE__);
1861 pic16_emitcode("movf","%s,w",s);
1862 pic16_emitcode("movwf","%s",d);
1865 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1866 if(offset >= aop->size) {
1867 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1870 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1873 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1880 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1881 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1884 strcmp(s,"r0") == 0 ||
1885 strcmp(s,"r1") == 0 ||
1886 strcmp(s,"r2") == 0 ||
1887 strcmp(s,"r3") == 0 ||
1888 strcmp(s,"r4") == 0 ||
1889 strcmp(s,"r5") == 0 ||
1890 strcmp(s,"r6") == 0 ||
1891 strcmp(s,"r7") == 0 )
1892 pic16_emitcode("mov","%s,%s ; %d",
1893 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1897 if(strcmp(s,"W")==0 )
1898 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1900 pic16_emitcode("movwf","%s",
1901 aop->aopu.aop_reg[offset]->name);
1903 if(strcmp(s,zero)==0) {
1904 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1906 } else if(strcmp(s,"W")==0) {
1907 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1908 pcop->type = PO_GPR_REGISTER;
1910 PCOR(pcop)->rIdx = -1;
1911 PCOR(pcop)->r = NULL;
1913 DEBUGpic16_emitcode(";","%d",__LINE__);
1914 pcop->name = Safe_strdup(s);
1915 pic16_emitpcode(POC_MOVFW,pcop);
1916 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1917 } else if(strcmp(s,one)==0) {
1918 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1919 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1921 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1927 if (strcmp(s,"a") == 0)
1928 pic16_emitcode("push","acc");
1930 pic16_emitcode("push","%s",s);
1935 /* if bit variable */
1936 if (!aop->aopu.aop_dir) {
1937 pic16_emitcode("clr","a");
1938 pic16_emitcode("rlc","a");
1941 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1944 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1947 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1949 lbl = newiTempLabel(NULL);
1951 if (strcmp(s,"a")) {
1954 pic16_emitcode("clr","c");
1955 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1956 pic16_emitcode("cpl","c");
1957 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1958 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1965 if (strcmp(aop->aopu.aop_str[offset],s))
1966 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1971 if (!offset && (strcmp(s,"acc") == 0))
1974 if (strcmp(aop->aopu.aop_str[offset],s))
1975 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1979 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1980 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1981 // "pic16_aopPut got unsupported aop->type");
1987 /*-----------------------------------------------------------------*/
1988 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
1989 /*-----------------------------------------------------------------*/
1990 void pic16_mov2w (asmop *aop, int offset)
1992 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1994 if(pic16_isLitAop(aop))
1995 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1997 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2000 void pic16_mov2w_volatile (asmop *aop)
2004 if(!pic16_isLitAop(aop)) {
2005 // may need to protect this from the peepholer -- this is not nice but works...
2006 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2007 for (i = 0; i < aop->size; i++) {
2009 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2011 pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2013 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2017 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2019 if(pic16_isLitAop(src)) {
2020 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2021 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2023 if(pic16_sameRegsOfs(src, dst, offset))return;
2024 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2025 pic16_popGet(dst, offset)));
2029 static void pic16_movLit2f(pCodeOp *pc, int lit)
2031 if (0 == (lit & 0x00ff))
2033 pic16_emitpcode (POC_CLRF, pc);
2034 } else if (0xff == (lit & 0x00ff))
2036 pic16_emitpcode (POC_SETF, pc);
2038 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2039 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2043 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2045 if(pic16_isLitAop(src)) {
2046 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2047 pic16_emitpcode(POC_MOVWF, dst);
2049 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2053 void pic16_testStackOverflow(void)
2055 #define GSTACK_TEST_NAME "_gstack_test"
2057 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2062 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2063 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2064 // strcpy(sym->rname, GSTACK_TEST_NAME);
2065 checkAddSym(&externs, sym);
2070 /* push pcop into stack */
2071 void pic16_pushpCodeOp(pCodeOp *pcop)
2073 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2074 if (pcop->type == PO_LITERAL) {
2075 pic16_emitpcode(POC_MOVLW, pcop);
2076 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2078 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2080 if(pic16_options.gstack)
2081 pic16_testStackOverflow();
2085 /* pop pcop from stack */
2086 void pic16_poppCodeOp(pCodeOp *pcop)
2088 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2089 if(pic16_options.gstack)
2090 pic16_testStackOverflow();
2094 /*-----------------------------------------------------------------*/
2095 /* pushw - pushes wreg to stack */
2096 /*-----------------------------------------------------------------*/
2099 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2100 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2101 if(pic16_options.gstack)
2102 pic16_testStackOverflow();
2106 /*-----------------------------------------------------------------*/
2107 /* pushaop - pushes aop to stack */
2108 /*-----------------------------------------------------------------*/
2109 void pushaop(asmop *aop, int offset)
2111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2113 if(_G.resDirect)return;
2115 if(pic16_isLitAop(aop)) {
2116 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2117 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2119 pic16_emitpcode(POC_MOVFF,
2120 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2123 if(pic16_options.gstack)
2124 pic16_testStackOverflow();
2127 /*-----------------------------------------------------------------*/
2128 /* popaop - pops aop from stack */
2129 /*-----------------------------------------------------------------*/
2130 void popaop(asmop *aop, int offset)
2132 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2133 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2134 if(pic16_options.gstack)
2135 pic16_testStackOverflow();
2138 void popaopidx(asmop *aop, int offset, int index)
2142 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2144 if(STACK_MODEL_LARGE)ofs++;
2146 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2147 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2148 if(pic16_options.gstack)
2149 pic16_testStackOverflow();
2152 /*-----------------------------------------------------------------*/
2153 /* pic16_getDataSize - get the operand data size */
2154 /*-----------------------------------------------------------------*/
2155 int pic16_getDataSize(operand *op)
2157 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2160 return AOP_SIZE(op);
2162 // tsd- in the pic port, the genptr size is 1, so this code here
2163 // fails. ( in the 8051 port, the size was 4).
2166 size = AOP_SIZE(op);
2167 if (size == GPTRSIZE)
2169 sym_link *type = operandType(op);
2170 if (IS_GENPTR(type))
2172 /* generic pointer; arithmetic operations
2173 * should ignore the high byte (pointer type).
2176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2183 /*-----------------------------------------------------------------*/
2184 /* pic16_outAcc - output Acc */
2185 /*-----------------------------------------------------------------*/
2186 void pic16_outAcc(operand *result)
2189 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2190 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2193 size = pic16_getDataSize(result);
2195 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2198 /* unsigned or positive */
2200 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2205 /*-----------------------------------------------------------------*/
2206 /* pic16_outBitC - output a bit C */
2207 /* Move to result the value of Carry flag -- VR */
2208 /*-----------------------------------------------------------------*/
2209 void pic16_outBitC(operand *result)
2213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2215 /* if the result is bit */
2216 if (AOP_TYPE(result) == AOP_CRY) {
2217 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2218 pic16_aopPut(AOP(result),"c",0);
2221 i = AOP_SIZE(result);
2223 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2225 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2229 /*-----------------------------------------------------------------*/
2230 /* pic16_outBitOp - output a bit from Op */
2231 /* Move to result the value of set/clr op -- VR */
2232 /*-----------------------------------------------------------------*/
2233 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2239 /* if the result is bit */
2240 if (AOP_TYPE(result) == AOP_CRY) {
2241 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2242 pic16_aopPut(AOP(result),"c",0);
2245 i = AOP_SIZE(result);
2247 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2249 pic16_emitpcode(POC_RRCF, pcop);
2250 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2254 /*-----------------------------------------------------------------*/
2255 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2256 /*-----------------------------------------------------------------*/
2257 void pic16_toBoolean(operand *oper)
2259 int size = AOP_SIZE(oper) - 1;
2262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2264 if ( AOP_TYPE(oper) != AOP_ACC) {
2265 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2268 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2272 /*-----------------------------------------------------------------*/
2273 /* genUminusFloat - unary minus for floating points */
2274 /*-----------------------------------------------------------------*/
2275 static void genUminusFloat(operand *op,operand *result)
2277 int size ,offset =0 ;
2280 /* for this we just need to flip the
2281 first it then copy the rest in place */
2282 size = AOP_SIZE(op);
2283 assert( size == AOP_SIZE(result) );
2286 pic16_mov2f(AOP(result), AOP(op), offset);
2290 /* toggle the MSB's highest bit */
2291 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2294 /*-----------------------------------------------------------------*/
2295 /* genUminus - unary minus code generation */
2296 /*-----------------------------------------------------------------*/
2297 static void genUminus (iCode *ic)
2300 sym_link *optype, *rtype;
2307 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2308 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2310 /* if both in bit space then special case */
2311 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2312 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2314 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2315 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2316 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2320 optype = operandType(IC_LEFT(ic));
2321 rtype = operandType(IC_RESULT(ic));
2324 /* if float then do float stuff */
2325 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2326 if(IS_FIXED(optype))
2327 debugf("implement fixed16x16 type\n", 0);
2329 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2333 /* otherwise subtract from zero by taking the 2's complement */
2334 size = AOP_SIZE(IC_LEFT(ic));
2335 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2336 label = newiTempLabel ( NULL );
2338 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2339 for (i=size-1; i > 0; i--) {
2340 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2342 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2343 for (i=1; i < size; i++) {
2344 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2345 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2348 for (i=size-1; i >= 0; i--) {
2349 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2350 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2353 for (i=0; i < size-2; i++) {
2354 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2355 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2357 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2359 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2362 pic16_emitpLabel (label->key);
2365 /* release the aops */
2366 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2367 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2370 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2372 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2373 pic16_emitpcode(POC_MOVFW, src);
2374 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2376 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2377 src, pic16_popGet(AOP(op), offset)));
2382 /*-----------------------------------------------------------------*/
2383 /* assignResultValue - assign results to oper, rescall==1 is */
2384 /* called from genCall() or genPcall() */
2385 /*-----------------------------------------------------------------*/
2386 static void assignResultValue(operand * oper, int res_size, int rescall)
2388 int size = AOP_SIZE(oper);
2392 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2393 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2396 /* assign result from a call/pcall function() */
2398 /* function results are stored in a special order,
2399 * see top of file with Function return policy, or manual */
2402 /* 8-bits, result in WREG */
2403 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2405 if(size > 1 && res_size > 1) {
2406 /* 16-bits, result in PRODL:WREG */
2407 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2410 if(size > 2 && res_size > 2) {
2411 /* 24-bits, result in PRODH:PRODL:WREG */
2412 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2415 if(size > 3 && res_size > 3) {
2416 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2417 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2420 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2423 /* >32-bits, result on stack, and FSR0 points to beginning.
2424 * Fix stack when done */
2426 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2428 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2429 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2431 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2437 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2438 if(STACK_MODEL_LARGE) {
2440 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2444 int areg = 0; /* matching argument register */
2446 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2447 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2450 /* its called from genReceive (probably) -- VR */
2451 /* I hope this code will not be called from somewhere else in the future!
2452 * We manually set the pseudo stack pointer in genReceive. - dw
2454 if(!GpsuedoStkPtr && _G.useWreg) {
2455 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2457 /* The last byte in the assignment is in W */
2458 if(areg <= GpsuedoStkPtr) {
2460 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2462 // debugf("receive from WREG\n", 0);
2464 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2467 _G.stack_lat = AOP_SIZE(oper)-1;
2472 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2473 // debugf("receive from STACK\n", 0);
2480 /*-----------------------------------------------------------------*/
2481 /* genIpush - generate code for pushing this gets a little complex */
2482 /*-----------------------------------------------------------------*/
2483 static void genIpush (iCode *ic)
2485 // int size, offset=0;
2488 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2491 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2493 /* send to stack as normal */
2494 addSet(&_G.sendSet,ic);
2495 // addSetHead(&_G.sendSet,ic);
2496 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2501 int size, offset = 0 ;
2505 /* if this is not a parm push : ie. it is spill push
2506 and spill push is always done on the local stack */
2507 if (!ic->parmPush) {
2509 /* and the item is spilt then do nothing */
2510 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2513 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2514 size = AOP_SIZE(IC_LEFT(ic));
2515 /* push it on the stack */
2517 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2522 pic16_emitcode("push","%s",l);
2527 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2531 /*-----------------------------------------------------------------*/
2532 /* genIpop - recover the registers: can happen only for spilling */
2533 /*-----------------------------------------------------------------*/
2534 static void genIpop (iCode *ic)
2537 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2542 /* if the temp was not pushed then */
2543 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2546 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2547 size = AOP_SIZE(IC_LEFT(ic));
2550 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2553 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2557 static int wparamCmp(void *p1, void *p2)
2559 return (!strcmp((char *)p1, (char *)p2));
2562 int inWparamList(char *s)
2564 return isinSetWith(wparamList, s, wparamCmp);
2568 /*-----------------------------------------------------------------*/
2569 /* genCall - generates a call statement */
2570 /*-----------------------------------------------------------------*/
2571 static void genCall (iCode *ic)
2581 ftype = OP_SYM_TYPE(IC_LEFT(ic));
2582 /* if caller saves & we have not saved then */
2583 // if (!ic->regsSaved)
2584 // saveRegisters(ic);
2586 /* initialise stackParms for IPUSH pushes */
2587 // stackParms = psuedoStkPtr;
2588 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2589 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2590 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2593 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2596 /* if send set is not empty the assign */
2599 int psuedoStkPtr=-1;
2600 int firstTimeThruLoop = 1;
2603 /* reverse sendSet if function is not reentrant */
2604 if(!IFFUNC_ISREENT(ftype))
2605 _G.sendSet = reverseSet(_G.sendSet);
2607 /* First figure how many parameters are getting passed */
2611 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2615 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2616 size = AOP_SIZE(IC_LEFT(sic));
2620 /* pass the last byte through WREG */
2624 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2625 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2626 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2628 if(!firstTimeThruLoop) {
2629 /* If this is not the first time we've been through the loop
2630 * then we need to save the parameter in a temporary
2631 * register. The last byte of the last parameter is
2635 // --psuedoStkPtr; // sanity check
2639 firstTimeThruLoop=0;
2641 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2646 /* all arguments are passed via stack */
2650 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2651 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2652 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2654 // pushaop(AOP(IC_LEFT(sic)), size);
2655 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2662 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2666 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2667 pushw(); /* save last parameter to stack if functions has varargs */
2671 } else use_wreg = 0;
2673 _G.stackRegSet = _G.sendSet;
2678 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2682 /* if we need to assign a result value */
2683 if ((IS_ITEMP(IC_RESULT(ic))
2684 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2685 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2686 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2689 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2692 /* Must not assign an 8-bit result to a 16-bit variable;
2693 * this would use (used...) the uninitialized PRODL! */
2694 /* FIXME: Need a proper way to obtain size of function result type,
2695 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2696 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2698 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2699 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2701 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2704 if(!stackParms && ic->parmBytes) {
2705 stackParms = ic->parmBytes;
2708 stackParms -= use_wreg;
2711 if(stackParms == 1) {
2712 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
2714 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2715 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2717 if(STACK_MODEL_LARGE) {
2719 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2724 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2727 /* adjust the stack for parameters if required */
2728 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2731 /* if register bank was saved then pop them */
2733 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2735 /* if we hade saved some registers then unsave them */
2736 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2737 unsaveRegisters (ic);
2743 /*-----------------------------------------------------------------*/
2744 /* genPcall - generates a call by pointer statement */
2745 /* new version, created from genCall - HJD */
2746 /*-----------------------------------------------------------------*/
2747 static void genPcall (iCode *ic)
2751 symbol *retlbl = newiTempLabel(NULL);
2752 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2756 fntype = operandType( IC_LEFT(ic) )->next;
2758 /* if send set is not empty the assign */
2761 int psuedoStkPtr=-1;
2763 /* reverse sendSet if function is not reentrant */
2764 if(!IFFUNC_ISREENT(fntype))
2765 _G.sendSet = reverseSet(_G.sendSet);
2769 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2772 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2773 size = AOP_SIZE(IC_LEFT(sic));
2776 /* all parameters are passed via stack, since WREG is clobbered
2777 * by the calling sequence */
2779 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2780 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2781 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2783 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2787 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2790 _G.stackRegSet = _G.sendSet;
2794 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2796 // push return address
2797 // push $ on return stack, then replace with retlbl
2799 /* Thanks to Thorsten Klose for pointing out that the following
2800 * snippet should be interrupt safe */
2801 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2802 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2804 pic16_emitpcodeNULLop(POC_PUSH);
2806 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2807 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2808 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2809 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2810 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2811 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2814 /* restore interrupt control register */
2815 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2816 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2818 /* make the call by writing the pointer into pc */
2819 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2820 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2822 // note: MOVFF to PCL not allowed
2823 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2824 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2827 /* return address is here: (X) */
2828 pic16_emitpLabelFORCE(retlbl->key);
2830 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2833 /* if we need assign a result value */
2834 if ((IS_ITEMP(IC_RESULT(ic))
2835 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2836 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2837 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2840 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2843 /* FIXME: Need proper way to obtain the function result's type.
2844 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2845 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2847 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2848 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2850 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2853 // stackParms -= use_wreg;
2856 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2857 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2858 if(STACK_MODEL_LARGE) {
2860 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2865 /*-----------------------------------------------------------------*/
2866 /* resultRemat - result is rematerializable */
2867 /*-----------------------------------------------------------------*/
2868 static int resultRemat (iCode *ic)
2870 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2871 if (SKIP_IC(ic) || ic->op == IFX)
2874 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2875 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2876 if (sym->remat && !POINTER_SET(ic))
2884 /*-----------------------------------------------------------------*/
2885 /* inExcludeList - return 1 if the string is in exclude Reg list */
2886 /*-----------------------------------------------------------------*/
2887 static bool inExcludeList(char *s)
2889 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2893 if (options.excludeRegs[i] &&
2894 STRCASECMP(options.excludeRegs[i],"none") == 0)
2897 for ( i = 0 ; options.excludeRegs[i]; i++) {
2898 if (options.excludeRegs[i] &&
2899 STRCASECMP(s,options.excludeRegs[i]) == 0)
2906 /*-----------------------------------------------------------------*/
2907 /* genFunction - generated code for function entry */
2908 /*-----------------------------------------------------------------*/
2909 static void genFunction (iCode *ic)
2915 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2917 pic16_labelOffset += (max_key+4);
2922 ftype = operandType(IC_LEFT(ic));
2923 sym = OP_SYMBOL(IC_LEFT(ic));
2925 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2926 /* create an absolute section at the interrupt vector:
2927 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2932 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2934 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2935 sprintf(asymname, "ivec_%s", sym->name);
2937 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2939 /* when an interrupt is declared as naked, do not emit the special
2940 * wrapper segment at vector address. The user should take care for
2941 * this instead. -- VR */
2943 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2944 asym = newSymbol(asymname, 0);
2945 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2946 pic16_addpBlock( apb );
2948 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2949 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2950 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2951 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2952 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2954 /* mark the end of this tiny function */
2955 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2957 sprintf(asymname, "%s", sym->rname);
2963 abSym = Safe_calloc(1, sizeof(absSym));
2964 strcpy(abSym->name, asymname);
2966 switch( FUNC_INTNO(sym->type) ) {
2967 case 0: abSym->address = 0x000000; break;
2968 case 1: abSym->address = 0x000008; break;
2969 case 2: abSym->address = 0x000018; break;
2972 // fprintf(stderr, "no interrupt number is given\n");
2973 abSym->address = -1; break;
2976 /* relocate interrupt vectors if needed */
2977 if(abSym->address != -1)
2978 abSym->address += pic16_options.ivt_loc;
2980 addSet(&absSymSet, abSym);
2984 /* create the function header */
2985 pic16_emitcode(";","-----------------------------------------");
2986 pic16_emitcode(";"," function %s",sym->name);
2987 pic16_emitcode(";","-----------------------------------------");
2989 /* prevent this symbol from being emitted as 'extern' */
2990 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2992 pic16_emitcode("","%s:",sym->rname);
2993 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2998 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2999 if(!strcmp(ab->name, sym->rname)) {
3000 pic16_pBlockConvert2Absolute(pb);
3006 if(IFFUNC_ISNAKED(ftype)) {
3007 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3011 /* if critical function then turn interrupts off */
3012 if (IFFUNC_ISCRITICAL(ftype)) {
3013 //pic16_emitcode("clr","ea");
3016 currFunc = sym; /* update the currFunc symbol */
3017 _G.fregsUsed = sym->regsUsed;
3018 _G.sregsAlloc = newBitVect(128);
3021 /* if this is an interrupt service routine then
3022 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3023 if (IFFUNC_ISISR(sym->type)) {
3024 _G.usefastretfie = 1; /* use shadow registers by default */
3026 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3027 if(!FUNC_ISSHADOWREGS(sym->type)) {
3028 /* do not save WREG,STATUS,BSR for high priority interrupts
3029 * because they are stored in the hardware shadow registers already */
3030 _G.usefastretfie = 0;
3031 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3032 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3033 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3036 /* these should really be optimized somehow, because not all
3037 * interrupt handlers modify them */
3038 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3039 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3040 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3041 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3042 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3043 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3045 // pic16_pBlockConvert2ISR(pb);
3048 /* emit code to setup stack frame if user enabled,
3049 * and function is not main() */
3051 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3052 if(strcmp(sym->name, "main")) {
3054 || !options.ommitFramePtr
3056 || IFFUNC_ARGS(sym->type)
3057 || FUNC_HASSTACKPARM(sym->etype)
3059 /* setup the stack frame */
3060 if(STACK_MODEL_LARGE)
3061 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3062 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3064 if(STACK_MODEL_LARGE)
3065 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3066 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3070 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3073 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3075 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3076 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3078 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3081 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3082 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3089 /* if callee-save to be used for this function
3090 * then save the registers being used in this function */
3091 // if (IFFUNC_CALLEESAVES(sym->type))
3092 if(strcmp(sym->name, "main")) {
3095 /* if any registers used */
3096 if (sym->regsUsed) {
3097 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3099 if(!pic16_options.xinst) {
3100 /* save the registers used */
3101 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3102 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3103 if (bitVectBitValue(sym->regsUsed,i)) {
3105 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3107 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3110 if(!pic16_regWithIdx(i)->wasUsed) {
3111 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3112 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3113 pic16_regWithIdx(i)->wasUsed = 1;
3120 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3121 for(i=0;i<sym->regsUsed->size;i++) {
3122 if(bitVectBitValue(sym->regsUsed, i)) {
3127 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3130 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3135 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3136 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3139 /*-----------------------------------------------------------------*/
3140 /* genEndFunction - generates epilogue for functions */
3141 /*-----------------------------------------------------------------*/
3142 static void genEndFunction (iCode *ic)
3144 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3148 if(IFFUNC_ISNAKED(sym->type)) {
3149 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3155 /* add code for ISCRITICAL */
3156 if(IFFUNC_ISCRITICAL(sym->type)) {
3157 /* if critical function, turn on interrupts */
3159 /* TODO: add code here -- VR */
3162 // sym->regsUsed = _G.fregsUsed;
3164 /* now we need to restore the registers */
3165 /* if any registers used */
3167 /* first restore registers that might be used for stack access */
3168 if(_G.sregsAllocSet) {
3171 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3172 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3173 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3177 if (strcmp(sym->name, "main") && sym->regsUsed) {
3180 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3181 /* restore registers used */
3182 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3183 for ( i = sym->regsUsed->size; i >= 0; i--) {
3184 if (bitVectBitValue(sym->regsUsed,i)) {
3185 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3189 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3194 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3196 if (sym->stack == 1) {
3197 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3198 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3200 // we have to add more than one...
3201 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3202 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3203 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3205 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3206 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3207 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3211 if(strcmp(sym->name, "main")) {
3213 || !options.ommitFramePtr
3215 || IFFUNC_ARGS(sym->type)
3216 || FUNC_HASSTACKPARM(sym->etype)
3218 /* restore stack frame */
3219 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3220 if(STACK_MODEL_LARGE)
3221 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3227 if (IFFUNC_ISISR(sym->type)) {
3228 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3229 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3230 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3231 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3232 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3233 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3235 if(!FUNC_ISSHADOWREGS(sym->type)) {
3236 /* do not restore interrupt vector for WREG,STATUS,BSR
3237 * for high priority interrupt, see genFunction */
3238 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3239 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3240 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3242 // _G.interruptvector = 0; /* sanity check */
3245 /* if debug then send end of function */
3246 /* if (options.debug && currFunc) */
3248 debugFile->writeEndFunction (currFunc, ic, 1);
3251 if(_G.usefastretfie)
3252 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3254 pic16_emitpcodeNULLop(POC_RETFIE);
3256 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3258 _G.usefastretfie = 0;
3262 if (IFFUNC_ISCRITICAL(sym->type)) {
3263 pic16_emitcode("setb","ea");
3266 /* if debug then send end of function */
3268 debugFile->writeEndFunction (currFunc, ic, 1);
3271 /* insert code to restore stack frame, if user enabled it
3272 * and function is not main() */
3275 pic16_emitpcodeNULLop(POC_RETURN);
3277 /* Mark the end of a function */
3278 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3282 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3284 unsigned long lit=1;
3289 // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3290 if(AOP_TYPE(op) == AOP_LIT) {
3291 if(!IS_FLOAT(operandType( op ))) {
3292 lit = ulFromVal (AOP(op)->aopu.aop_lit);
3295 unsigned long lit_int;
3299 /* take care if literal is a float */
3300 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3305 if (AOP_TYPE(op) == AOP_LIT) {
3306 /* FIXME: broken for
3307 * char __at(0x456) foo;
3309 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3310 pic16_movLit2f(dest, (lit >> (8ul*offset)));
3311 } else if (AOP_TYPE(op) == AOP_PCODE
3312 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3313 /* char *s= "aaa"; return s; */
3314 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3315 * that the generic pointer is interpreted correctly
3316 * as referring to __code space, but this is fragile! */
3317 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3318 /* XXX: should check that dest != WREG */
3319 pic16_emitpcode(POC_MOVWF, dest);
3321 if(dest->type == PO_WREG && (offset == 0)) {
3322 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3325 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3329 /*-----------------------------------------------------------------*/
3330 /* genRet - generate code for return statement */
3331 /*-----------------------------------------------------------------*/
3332 static void genRet (iCode *ic)
3338 /* if we have no return value then
3339 * just generate the "ret" */
3344 /* we have something to return then
3345 * move the return value into place */
3346 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3347 size = AOP_SIZE(IC_LEFT(ic));
3351 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3354 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3357 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3359 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3362 /* >32-bits, setup stack and FSR0 */
3364 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3365 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3367 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3369 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3374 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3375 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3377 if(STACK_MODEL_LARGE) {
3378 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3379 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3381 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3385 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3388 /* generate a jump to the return label
3389 * if the next is not the return statement */
3390 if (!(ic->next && ic->next->op == LABEL
3391 && IC_LABEL(ic->next) == returnLabel)) {
3393 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3394 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3398 /*-----------------------------------------------------------------*/
3399 /* genLabel - generates a label */
3400 /*-----------------------------------------------------------------*/
3401 static void genLabel (iCode *ic)
3405 /* special case never generate */
3406 if (IC_LABEL(ic) == entryLabel)
3409 pic16_emitpLabel(IC_LABEL(ic)->key);
3410 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3413 /*-----------------------------------------------------------------*/
3414 /* genGoto - generates a goto */
3415 /*-----------------------------------------------------------------*/
3417 static void genGoto (iCode *ic)
3420 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3421 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3425 /*-----------------------------------------------------------------*/
3426 /* genMultbits :- multiplication of bits */
3427 /*-----------------------------------------------------------------*/
3428 static void genMultbits (operand *left,
3434 if(!pic16_sameRegs(AOP(result),AOP(right)))
3435 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3437 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3438 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3439 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3444 /*-----------------------------------------------------------------*/
3445 /* genMultOneByte : 8 bit multiplication & division */
3446 /*-----------------------------------------------------------------*/
3447 static void genMultOneByte (operand *left,
3453 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3454 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3456 /* (if two literals, the value is computed before) */
3457 /* if one literal, literal on the right */
3458 if (AOP_TYPE(left) == AOP_LIT){
3464 /* size is already checked in genMult == 1 */
3465 // size = AOP_SIZE(result);
3467 if (AOP_TYPE(right) == AOP_LIT){
3468 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3469 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3470 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3471 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3473 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3474 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3475 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3476 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3479 pic16_genMult8X8_n (left, right,result);
3483 /*-----------------------------------------------------------------*/
3484 /* genMultOneWord : 16 bit multiplication */
3485 /*-----------------------------------------------------------------*/
3486 static void genMultOneWord (operand *left,
3491 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3492 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3494 /* (if two literals, the value is computed before)
3495 * if one literal, literal on the right */
3496 if (AOP_TYPE(left) == AOP_LIT){
3502 /* size is checked already == 2 */
3503 // size = AOP_SIZE(result);
3505 if (AOP_TYPE(right) == AOP_LIT) {
3506 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3507 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3508 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3509 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3511 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3512 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3513 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3514 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3517 pic16_genMult16X16_16(left, right,result);
3522 /*-----------------------------------------------------------------*/
3523 /* genMultOneLong : 32 bit multiplication */
3524 /*-----------------------------------------------------------------*/
3525 static void genMultOneLong (operand *left,
3530 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3531 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3533 /* (if two literals, the value is computed before)
3534 * if one literal, literal on the right */
3535 if (AOP_TYPE(left) == AOP_LIT){
3541 /* size is checked already == 4 */
3542 // size = AOP_SIZE(result);
3544 if (AOP_TYPE(right) == AOP_LIT) {
3545 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3546 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3547 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3548 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3550 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3551 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3552 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3553 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3556 pic16_genMult32X32_32(left, right,result);
3562 /*-----------------------------------------------------------------*/
3563 /* genMult - generates code for multiplication */
3564 /*-----------------------------------------------------------------*/
3565 static void genMult (iCode *ic)
3567 operand *left = IC_LEFT(ic);
3568 operand *right = IC_RIGHT(ic);
3569 operand *result= IC_RESULT(ic);
3572 /* assign the amsops */
3573 pic16_aopOp (left,ic,FALSE);
3574 pic16_aopOp (right,ic,FALSE);
3575 pic16_aopOp (result,ic,TRUE);
3577 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3579 /* special cases first *
3581 if (AOP_TYPE(left) == AOP_CRY
3582 && AOP_TYPE(right)== AOP_CRY) {
3583 genMultbits(left,right,result);
3587 /* if both are of size == 1 */
3588 if(AOP_SIZE(left) == 1
3589 && AOP_SIZE(right) == 1) {
3590 genMultOneByte(left,right,result);
3595 /* if both are of size == 2 */
3596 if(AOP_SIZE(left) == 2
3597 && AOP_SIZE(right) == 2) {
3598 genMultOneWord(left, right, result);
3602 /* if both are of size == 4 */
3603 if(AOP_SIZE(left) == 4
3604 && AOP_SIZE(right) == 4) {
3605 genMultOneLong(left, right, result);
3610 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3611 assert( !"Multiplication should have been transformed into function call!" );
3613 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3616 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3617 /* should have been converted to function call */
3621 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3622 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3623 pic16_freeAsmop(result,NULL,ic,TRUE);
3627 /*-----------------------------------------------------------------*/
3628 /* genDivbits :- division of bits */
3629 /*-----------------------------------------------------------------*/
3630 static void genDivbits (operand *left,
3637 /* the result must be bit */
3638 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3639 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3643 pic16_emitcode("div","ab");
3644 pic16_emitcode("rrc","a");
3645 pic16_aopPut(AOP(result),"c",0);
3648 /*-----------------------------------------------------------------*/
3649 /* genDivOneByte : 8 bit division */
3650 /*-----------------------------------------------------------------*/
3651 static void genDivOneByte (operand *left,
3655 sym_link *opetype = operandType(result);
3660 /* result = divident / divisor
3661 * - divident may be a register or a literal,
3662 * - divisor may be a register or a literal,
3663 * so there are 3 cases (literal / literal is optimized
3664 * by the front-end) to handle.
3665 * In addition we must handle signed and unsigned, which
3666 * result in 6 final different cases -- VR */
3670 size = AOP_SIZE(result) - 1;
3672 /* signed or unsigned */
3673 if (SPEC_USIGN(opetype)) {
3674 pCodeOp *pct1, /* count */
3677 symbol *label1, *label2, *label3;;
3680 /* unsigned is easy */
3682 pct1 = pic16_popGetTempReg(1);
3683 pct2 = pic16_popGetTempReg(1);
3684 pct3 = pic16_popGetTempReg(1);
3686 label1 = newiTempLabel(NULL);
3687 label2 = newiTempLabel(NULL);
3688 label3 = newiTempLabel(NULL);
3690 /* the following algorithm is extracted from divuint.c */
3692 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3693 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3695 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3697 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3699 pic16_emitpLabel(label1->key);
3702 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3706 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3710 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3712 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3713 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3715 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3716 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3717 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3719 pic16_emitpLabel( label3->key );
3720 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3721 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3725 pic16_emitpLabel(label2->key);
3726 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3727 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3728 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3730 /* result is in wreg */
3731 if(AOP_TYPE(result) != AOP_ACC)
3732 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3734 pic16_popReleaseTempReg( pct3, 1);
3735 pic16_popReleaseTempReg( pct2, 1);
3736 pic16_popReleaseTempReg( pct1, 1);
3741 /* signed is a little bit more difficult */
3743 /* save the signs of the operands */
3744 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3746 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3747 pic16_emitcode("push","acc"); /* save it on the stack */
3749 /* now sign adjust for both left & right */
3750 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3752 lbl = newiTempLabel(NULL);
3753 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3754 pic16_emitcode("cpl","a");
3755 pic16_emitcode("inc","a");
3756 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3757 pic16_emitcode("mov","b,a");
3759 /* sign adjust left side */
3760 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3763 lbl = newiTempLabel(NULL);
3764 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3765 pic16_emitcode("cpl","a");
3766 pic16_emitcode("inc","a");
3767 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3769 /* now the division */
3770 pic16_emitcode("div","ab");
3771 /* we are interested in the lower order
3773 pic16_emitcode("mov","b,a");
3774 lbl = newiTempLabel(NULL);
3775 pic16_emitcode("pop","acc");
3776 /* if there was an over flow we don't
3777 adjust the sign of the result */
3778 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3779 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3781 pic16_emitcode("clr","a");
3782 pic16_emitcode("subb","a,b");
3783 pic16_emitcode("mov","b,a");
3784 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3786 /* now we are done */
3787 pic16_aopPut(AOP(result),"b",0);
3789 pic16_emitcode("mov","c,b.7");
3790 pic16_emitcode("subb","a,acc");
3793 pic16_aopPut(AOP(result),"a",offset++);
3798 /*-----------------------------------------------------------------*/
3799 /* genDiv - generates code for division */
3800 /*-----------------------------------------------------------------*/
3801 static void genDiv (iCode *ic)
3803 operand *left = IC_LEFT(ic);
3804 operand *right = IC_RIGHT(ic);
3805 operand *result= IC_RESULT(ic);
3807 int leftVal = 0, rightVal = 0;
3809 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3812 /* Division is a very lengthy algorithm, so it is better
3813 * to call support routines than inlining algorithm.
3814 * Division functions written here just in case someone
3815 * wants to inline and not use the support libraries -- VR */
3819 /* assign the amsops */
3820 pic16_aopOp (left,ic,FALSE);
3821 pic16_aopOp (right,ic,FALSE);
3822 pic16_aopOp (result,ic,TRUE);
3826 else if (ic->op == '%')
3829 assert( !"invalid operation requested in genDivMod" );
3831 /* get literal values */
3832 if (IS_VALOP(left)) {
3833 leftVal = (int) ulFromVal ( OP_VALUE(left) );
3834 assert( leftVal >= -128 && leftVal < 256 );
3835 if (leftVal < 0) { signedLits++; }
3837 if (IS_VALOP(right)) {
3838 rightVal = (int) ulFromVal ( OP_VALUE(right) );
3839 assert( rightVal >= -128 && rightVal < 256 );
3840 if (rightVal < 0) { signedLits++; }
3843 /* We should only come here to convert all
3844 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3845 * with exactly one operand being s8_t into
3846 * u8_t x u8_t -> u8_t. All other cases should have been
3847 * turned into calls to support routines beforehand... */
3848 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3849 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3851 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3852 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3854 /* Both operands are signed or negative, use _divschar
3855 * instead of _divuchar */
3856 pushaop(AOP(right), 0);
3857 pushaop(AOP(left), 0);
3859 /* call _divschar */
3860 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3864 sym = newSymbol( functions[op][0], 0 );
3866 strcpy(sym->rname, functions[op][0]);
3867 checkAddSym(&externs, sym);
3871 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3872 if (AOP_SIZE(result) > 1)
3874 pic16_emitpcode(POC_MOVFF,
3875 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3876 pic16_popGet(AOP(result), 1)));
3878 pic16_addSign(result, 2, 1);
3881 /* clean up stack */
3882 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3883 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3888 /* push right operand */
3889 if (IS_VALOP(right)) {
3891 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3894 pushaop(AOP(right), 0);
3896 } else if (!IS_UNSIGNED(operandType(right))) {
3897 pic16_mov2w(AOP(right), 0);
3898 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3899 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3900 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3903 pushaop(AOP(right), 0);
3906 /* push left operand */
3907 if (IS_VALOP(left)) {
3909 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3912 pushaop(AOP(left), 0);
3914 } else if (!IS_UNSIGNED(operandType(left))) {
3915 pic16_mov2w(AOP(left),0);
3916 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3917 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3918 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3921 pushaop(AOP(left), 0);
3924 /* call _divuchar */
3925 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3929 sym = newSymbol( functions[op][1], 0 );
3931 strcpy(sym->rname, functions[op][1]);
3932 checkAddSym(&externs, sym);
3935 /* Revert negation(s) from above.
3936 * This is inefficient: if both operands are negative, this
3937 * should not touch WREG. However, determining that exactly
3938 * one operand was negated costs at least 3 instructions,
3939 * so there is nothing to be gained here, is there?
3941 * I negate WREG because either operand might share registers with
3942 * result, so assigning first might destroy an operand. */
3944 /* For the modulus operator, (a/b)*b == a shall hold.
3945 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3946 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
3947 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
3948 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
3949 * Only invert the result if the left operand is negative (sigh).
3951 if (AOP_SIZE(result) <= 1 || !negated)
3955 if (IS_VALOP(right)) {
3957 /* we negated this operand above */
3958 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3960 } else if (!IS_UNSIGNED(operandType(right))) {
3961 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3962 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3966 if (IS_VALOP(left)) {
3968 /* we negated this operand above */
3969 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3971 } else if (!IS_UNSIGNED(operandType(left))) {
3972 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3973 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3976 /* Move result to destination. */
3977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3979 /* Zero-extend: no operand was signed (or result is just a byte). */
3980 pic16_addSign(result, 1, 0);
3982 assert( AOP_SIZE(result) > 1 );
3983 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3986 if (IS_VALOP(right)) {
3988 /* we negated this operand above */
3989 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3991 } else if (!IS_UNSIGNED(operandType(right))) {
3992 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3993 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3997 if (IS_VALOP(left)) {
3999 /* we negated this operand above */
4000 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4002 } else if (!IS_UNSIGNED(operandType(left))) {
4003 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4004 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4007 /* Move result to destination. */
4008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4010 /* Negate result if required. */
4011 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4012 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4015 pic16_addSign(result, 2, 1);
4018 /* clean up stack */
4019 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4020 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4025 /* special cases first */
4027 if (AOP_TYPE(left) == AOP_CRY &&
4028 AOP_TYPE(right)== AOP_CRY) {
4029 genDivbits(left,right,result);
4033 /* if both are of size == 1 */
4034 if (AOP_SIZE(left) == 1 &&
4035 AOP_SIZE(right) == 1 ) {
4036 genDivOneByte(left,right,result);
4041 /* should have been converted to function call */
4044 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4045 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4046 pic16_freeAsmop(result,NULL,ic,TRUE);
4050 /*-----------------------------------------------------------------*/
4051 /* genModbits :- modulus of bits */
4052 /*-----------------------------------------------------------------*/
4053 static void genModbits (operand *left,
4061 werror(W_POSSBUG2, __FILE__, __LINE__);
4062 /* the result must be bit */
4063 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4064 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4068 pic16_emitcode("div","ab");
4069 pic16_emitcode("mov","a,b");
4070 pic16_emitcode("rrc","a");
4071 pic16_aopPut(AOP(result),"c",0);
4074 /*-----------------------------------------------------------------*/
4075 /* genModOneByte : 8 bit modulus */
4076 /*-----------------------------------------------------------------*/
4077 static void genModOneByte (operand *left,
4081 sym_link *opetype = operandType(result);
4086 werror(W_POSSBUG2, __FILE__, __LINE__);
4088 /* signed or unsigned */
4089 if (SPEC_USIGN(opetype)) {
4090 /* unsigned is easy */
4091 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4092 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4094 pic16_emitcode("div","ab");
4095 pic16_aopPut(AOP(result),"b",0);
4099 /* signed is a little bit more difficult */
4101 /* save the signs of the operands */
4102 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4105 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4106 pic16_emitcode("push","acc"); /* save it on the stack */
4108 /* now sign adjust for both left & right */
4109 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4112 lbl = newiTempLabel(NULL);
4113 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4114 pic16_emitcode("cpl","a");
4115 pic16_emitcode("inc","a");
4116 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4117 pic16_emitcode("mov","b,a");
4119 /* sign adjust left side */
4120 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4123 lbl = newiTempLabel(NULL);
4124 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4125 pic16_emitcode("cpl","a");
4126 pic16_emitcode("inc","a");
4127 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4129 /* now the multiplication */
4130 pic16_emitcode("div","ab");
4131 /* we are interested in the lower order
4133 lbl = newiTempLabel(NULL);
4134 pic16_emitcode("pop","acc");
4135 /* if there was an over flow we don't
4136 adjust the sign of the result */
4137 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4138 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4140 pic16_emitcode("clr","a");
4141 pic16_emitcode("subb","a,b");
4142 pic16_emitcode("mov","b,a");
4143 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4145 /* now we are done */
4146 pic16_aopPut(AOP(result),"b",0);
4151 /*-----------------------------------------------------------------*/
4152 /* genMod - generates code for division */
4153 /*-----------------------------------------------------------------*/
4154 static void genMod (iCode *ic)
4156 /* Task deferred to genDiv */
4159 operand *left = IC_LEFT(ic);
4160 operand *right = IC_RIGHT(ic);
4161 operand *result= IC_RESULT(ic);
4165 /* assign the amsops */
4166 pic16_aopOp (left,ic,FALSE);
4167 pic16_aopOp (right,ic,FALSE);
4168 pic16_aopOp (result,ic,TRUE);
4170 /* special cases first */
4172 if (AOP_TYPE(left) == AOP_CRY &&
4173 AOP_TYPE(right)== AOP_CRY) {
4174 genModbits(left,right,result);
4178 /* if both are of size == 1 */
4179 if (AOP_SIZE(left) == 1 &&
4180 AOP_SIZE(right) == 1 ) {
4181 genModOneByte(left,right,result);
4185 /* should have been converted to function call */
4189 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4190 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4191 pic16_freeAsmop(result,NULL,ic,TRUE);
4195 /*-----------------------------------------------------------------*/
4196 /* genIfxJump :- will create a jump depending on the ifx */
4197 /*-----------------------------------------------------------------*/
4199 note: May need to add parameter to indicate when a variable is in bit space.
4201 static void genIfxJump (iCode *ic, char *jval)
4205 /* if true label then we jump if condition
4207 if ( IC_TRUE(ic) ) {
4209 if(strcmp(jval,"a") == 0)
4211 else if (strcmp(jval,"c") == 0)
4214 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4215 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4218 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4219 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4223 /* false label is present */
4224 if(strcmp(jval,"a") == 0)
4226 else if (strcmp(jval,"c") == 0)
4229 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4230 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4233 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4234 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4239 /* mark the icode as generated */
4243 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4247 /* if true label then we jump if condition
4249 if ( IC_TRUE(ic) ) {
4250 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4251 pic16_emitpcode(POC_BTFSC, jop);
4253 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4254 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4257 /* false label is present */
4258 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4259 pic16_emitpcode(POC_BTFSS, jop);
4261 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4262 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4266 /* mark the icode as generated */
4273 /*-----------------------------------------------------------------*/
4275 /*-----------------------------------------------------------------*/
4276 static void genSkip(iCode *ifx,int status_bit)
4278 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4282 if ( IC_TRUE(ifx) ) {
4283 switch(status_bit) {
4298 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4299 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4303 switch(status_bit) {
4317 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4318 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4325 /*-----------------------------------------------------------------*/
4327 /*-----------------------------------------------------------------*/
4328 static void genSkipc(resolvedIfx *rifx)
4330 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4340 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4341 rifx->generated = 1;
4344 /*-----------------------------------------------------------------*/
4345 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4346 /* aop (if it's NOT a literal) or from lit (if */
4347 /* aop is a literal) */
4348 /*-----------------------------------------------------------------*/
4349 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4350 if (aop->type == AOP_LIT) {
4351 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4353 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4357 /*-----------------------------------------------------------------*/
4358 /* genCmp :- greater or less than comparison */
4359 /*-----------------------------------------------------------------*/
4361 /* genCmp performs a left < right comparison, stores
4362 * the outcome in result (if != NULL) and generates
4363 * control flow code for the ifx (if != NULL).
4365 * This version leaves in sequences like
4366 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4367 * which should be optmized by the peephole
4368 * optimizer - RN 2005-01-01 */
4369 static void genCmp (operand *left,operand *right,
4370 operand *result, iCode *ifx, int sign)
4383 assert (left && right);
4384 assert (AOP_SIZE(left) == AOP_SIZE(right));
4386 size = AOP_SIZE(right) - 1;
4387 mask = (0x100UL << (size*8)) - 1;
4388 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4393 resolveIfx (&rIfx, ifx);
4395 /* handle for special cases */
4396 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4399 /**********************************************************************
4400 * handle bits - bit compares are promoted to int compares seemingly! *
4401 **********************************************************************/
4403 // THIS IS COMPLETELY UNTESTED!
4404 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4405 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4406 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4407 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4410 // 1 < {0,1} is false --> clear C by skipping the next instruction
4411 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4412 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4413 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4414 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4415 emitCLRC; // only skipped for left=0 && right=1
4417 goto correct_result_in_carry;
4421 /*************************************************
4422 * make sure that left is register (or the like) *
4423 *************************************************/
4424 if (!isAOP_REGlike(left)) {
4425 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4426 assert (isAOP_LIT(left));
4427 assert (isAOP_REGlike(right));
4428 // swap left and right
4429 // left < right <==> right > left <==> (right >= left + 1)
4430 lit = ulFromVal (AOP(left)->aopu.aop_lit);
4432 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4433 // MAXVALUE < right? always false
4434 if (performedLt) emitCLRC; else emitSETC;
4435 goto correct_result_in_carry;
4438 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4439 // that's why we handled it above.
4446 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4447 } else if (isAOP_LIT(right)) {
4448 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4451 assert (isAOP_REGlike(left)); // left must be register or the like
4452 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4454 /*************************************************
4455 * special cases go here *
4456 *************************************************/
4458 if (isAOP_LIT(right)) {
4460 // unsigned comparison to a literal
4461 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4463 // unsigned left < 0? always false
4464 if (performedLt) emitCLRC; else emitSETC;
4465 goto correct_result_in_carry;
4468 // signed comparison to a literal
4469 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4470 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4471 // signed left < 0x80000000? always false
4472 if (performedLt) emitCLRC; else emitSETC;
4473 goto correct_result_in_carry;
4474 } else if (lit == 0) {
4475 // compare left < 0; set CARRY if SIGNBIT(left) is set
4476 if (performedLt) emitSETC; else emitCLRC;
4477 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4478 if (performedLt) emitCLRC; else emitSETC;
4479 goto correct_result_in_carry;
4482 } // right is literal
4484 /*************************************************
4485 * perform a general case comparison *
4486 * make sure we get CARRY==1 <==> left >= right *
4487 *************************************************/
4488 // compare most significant bytes
4489 //DEBUGpc ("comparing bytes at offset %d", size);
4491 // unsigned comparison
4492 mov2w_regOrLit (AOP(right), lit, size);
4493 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4495 // signed comparison
4496 // (add 2^n to both operands then perform an unsigned comparison)
4497 if (isAOP_LIT(right)) {
4498 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4499 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4501 if (litbyte == 0x80) {
4502 // left >= 0x80 -- always true, but more bytes to come
4503 pic16_mov2w (AOP(left), size);
4504 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4507 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4508 pic16_mov2w (AOP(left), size);
4509 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4510 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4513 /* using PRODL as a temporary register here */
4514 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4515 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4516 pic16_mov2w (AOP(left), size);
4517 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4518 pic16_emitpcode (POC_MOVWF, pctemp);
4519 pic16_mov2w (AOP(right), size);
4520 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4521 pic16_emitpcode (POC_SUBFW, pctemp);
4522 //pic16_popReleaseTempReg(pctemp, 1);
4526 // compare remaining bytes (treat as unsigned case from above)
4527 templbl = newiTempLabel ( NULL );
4530 //DEBUGpc ("comparing bytes at offset %d", offs);
4531 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4532 mov2w_regOrLit (AOP(right), lit, offs);
4533 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4535 pic16_emitpLabel (templbl->key);
4536 goto result_in_carry;
4540 /****************************************************
4541 * now CARRY contains the result of the comparison: *
4542 * SUBWF sets CARRY iff *
4543 * F-W >= 0 <==> F >= W <==> !(F < W) *
4544 * (F=left, W=right) *
4545 ****************************************************/
4548 if (result && AOP_TYPE(result) != AOP_CRY) {
4549 // value will be stored
4552 // value wil only be used in the following genSkipc()
4553 rIfx.condition ^= 1;
4557 correct_result_in_carry:
4559 // assign result to variable (if neccessary)
4560 if (result && AOP_TYPE(result) != AOP_CRY) {
4561 //DEBUGpc ("assign result");
4562 size = AOP_SIZE(result);
4564 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4566 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4569 // perform conditional jump
4571 //DEBUGpc ("generate control flow");
4577 /*-----------------------------------------------------------------*/
4578 /* genCmpGt :- greater than comparison */
4579 /*-----------------------------------------------------------------*/
4580 static void genCmpGt (iCode *ic, iCode *ifx)
4582 operand *left, *right, *result;
4583 sym_link *letype , *retype;
4589 right= IC_RIGHT(ic);
4590 result = IC_RESULT(ic);
4592 letype = getSpec(operandType(left));
4593 retype =getSpec(operandType(right));
4594 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4595 /* assign the amsops */
4596 pic16_aopOp (left,ic,FALSE);
4597 pic16_aopOp (right,ic,FALSE);
4598 pic16_aopOp (result,ic,TRUE);
4600 genCmp(right, left, result, ifx, sign);
4602 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4603 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4604 pic16_freeAsmop(result,NULL,ic,TRUE);
4607 /*-----------------------------------------------------------------*/
4608 /* genCmpLt - less than comparisons */
4609 /*-----------------------------------------------------------------*/
4610 static void genCmpLt (iCode *ic, iCode *ifx)
4612 operand *left, *right, *result;
4613 sym_link *letype , *retype;
4619 right= IC_RIGHT(ic);
4620 result = IC_RESULT(ic);
4622 letype = getSpec(operandType(left));
4623 retype =getSpec(operandType(right));
4624 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4626 /* assign the amsops */
4627 pic16_aopOp (left,ic,FALSE);
4628 pic16_aopOp (right,ic,FALSE);
4629 pic16_aopOp (result,ic,TRUE);
4631 genCmp(left, right, result, ifx, sign);
4633 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4634 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4635 pic16_freeAsmop(result,NULL,ic,TRUE);
4638 /*-----------------------------------------------------------------*/
4639 /* pic16_isLitOp - check if operand has to be treated as literal */
4640 /*-----------------------------------------------------------------*/
4641 bool pic16_isLitOp(operand *op)
4643 return ((AOP_TYPE(op) == AOP_LIT)
4644 || ( (AOP_TYPE(op) == AOP_PCODE)
4645 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4646 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4649 /*-----------------------------------------------------------------*/
4650 /* pic16_isLitAop - check if operand has to be treated as literal */
4651 /*-----------------------------------------------------------------*/
4652 bool pic16_isLitAop(asmop *aop)
4654 return ((aop->type == AOP_LIT)
4655 || ( (aop->type == AOP_PCODE)
4656 && ( (aop->aopu.pcop->type == PO_LITERAL)
4657 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4662 /*-----------------------------------------------------------------*/
4663 /* genCmpEq - generates code for equal to */
4664 /*-----------------------------------------------------------------*/
4665 static void genCmpEq (iCode *ic, iCode *ifx)
4667 operand *left, *right, *result;
4668 symbol *falselbl = newiTempLabel(NULL);
4669 symbol *donelbl = newiTempLabel(NULL);
4671 int preserve_result = 0;
4672 int generate_result = 0;
4674 unsigned long lit = -1;
4678 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4679 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4680 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4682 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4684 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4686 werror(W_POSSBUG2, __FILE__, __LINE__);
4687 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4688 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4692 if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4694 operand *tmp = right ;
4699 if (AOP_TYPE(right) == AOP_LIT) {
4700 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4703 if ( regsInCommon(left, result) || regsInCommon(right, result) )
4704 preserve_result = 1;
4706 if(result && AOP_SIZE(result))
4707 generate_result = 1;
4709 if(generate_result && !preserve_result)
4711 for(i = 0; i < AOP_SIZE(result); i++)
4712 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4715 assert( AOP_SIZE(left) == AOP_SIZE(right) );
4716 for(i=0; i < AOP_SIZE(left); i++)
4718 if(AOP_TYPE(left) != AOP_ACC)
4720 if(pic16_isLitOp(left))
4721 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4723 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4725 if(pic16_isLitOp(right)) {
4726 if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4727 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4730 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4732 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4737 if(generate_result && preserve_result)
4739 for(i = 0; i < AOP_SIZE(result); i++)
4740 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4744 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4746 if(generate_result && preserve_result)
4747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4749 if(ifx && IC_TRUE(ifx))
4750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4752 if(ifx && IC_FALSE(ifx))
4753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4755 pic16_emitpLabel(falselbl->key);
4759 if(ifx && IC_FALSE(ifx))
4760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4762 if(generate_result && preserve_result)
4764 for(i = 0; i < AOP_SIZE(result); i++)
4765 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4768 pic16_emitpLabel(donelbl->key);
4774 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4775 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4776 pic16_freeAsmop(result,NULL,ic,TRUE);
4782 // old version kept for reference
4784 /*-----------------------------------------------------------------*/
4785 /* genCmpEq - generates code for equal to */
4786 /*-----------------------------------------------------------------*/
4787 static void genCmpEq (iCode *ic, iCode *ifx)
4789 operand *left, *right, *result;
4790 unsigned long lit = 0L;
4792 symbol *falselbl = newiTempLabel(NULL);
4795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4798 DEBUGpic16_emitcode ("; ifx is non-null","");
4800 DEBUGpic16_emitcode ("; ifx is null","");
4802 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4803 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4804 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4806 size = max(AOP_SIZE(left),AOP_SIZE(right));
4808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4810 /* if literal, literal on the right or
4811 if the right is in a pointer register and left
4813 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4814 operand *tmp = right ;
4820 if(ifx && !AOP_SIZE(result)){
4822 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
4823 /* if they are both bit variables */
4824 if (AOP_TYPE(left) == AOP_CRY &&
4825 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4826 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
4827 if(AOP_TYPE(right) == AOP_LIT){
4828 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4830 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4831 pic16_emitcode("cpl","c");
4832 } else if(lit == 1L) {
4833 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4835 pic16_emitcode("clr","c");
4837 /* AOP_TYPE(right) == AOP_CRY */
4839 symbol *lbl = newiTempLabel(NULL);
4840 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4841 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4842 pic16_emitcode("cpl","c");
4843 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4845 /* if true label then we jump if condition
4847 tlbl = newiTempLabel(NULL);
4848 if ( IC_TRUE(ifx) ) {
4849 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4850 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4852 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4853 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4855 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4858 /* left and right are both bit variables, result is carry */
4861 resolveIfx(&rIfx,ifx);
4863 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4864 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4865 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4866 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4871 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
4873 /* They're not both bit variables. Is the right a literal? */
4874 if(AOP_TYPE(right) == AOP_LIT) {
4875 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4880 switch(lit & 0xff) {
4882 if ( IC_TRUE(ifx) ) {
4883 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4885 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4887 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4888 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4892 if ( IC_TRUE(ifx) ) {
4893 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4897 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4902 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4904 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4909 /* end of size == 1 */
4913 genc16bit2lit(left,lit,offset);
4916 /* end of size == 2 */
4921 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4922 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4923 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4924 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4927 /* search for patterns that can be optimized */
4929 genc16bit2lit(left,lit,0);
4933 emitSKPZ; // if hi word unequal
4935 emitSKPNZ; // if hi word equal
4937 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4938 genc16bit2lit(left,lit,2);
4941 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4942 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4946 pic16_emitpLabel(falselbl->key);
4955 } else if(AOP_TYPE(right) == AOP_CRY ) {
4956 /* we know the left is not a bit, but that the right is */
4957 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4958 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4959 pic16_popGet(AOP(right),offset));
4960 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4962 /* if the two are equal, then W will be 0 and the Z bit is set
4963 * we could test Z now, or go ahead and check the high order bytes if
4964 * the variable we're comparing is larger than a byte. */
4967 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4969 if ( IC_TRUE(ifx) ) {
4971 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4972 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4975 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4976 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4980 /* They're both variables that are larger than bits */
4983 tlbl = newiTempLabel(NULL);
4986 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4987 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4989 if ( IC_TRUE(ifx) ) {
4993 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4995 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4996 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5000 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5003 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5004 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5009 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5011 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5012 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5016 if(s>1 && IC_TRUE(ifx)) {
5017 pic16_emitpLabel(tlbl->key);
5018 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5022 /* mark the icode as generated */
5027 /* if they are both bit variables */
5028 if (AOP_TYPE(left) == AOP_CRY &&
5029 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5030 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5031 if(AOP_TYPE(right) == AOP_LIT){
5032 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5034 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5035 pic16_emitcode("cpl","c");
5036 } else if(lit == 1L) {
5037 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5039 pic16_emitcode("clr","c");
5041 /* AOP_TYPE(right) == AOP_CRY */
5043 symbol *lbl = newiTempLabel(NULL);
5044 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5045 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5046 pic16_emitcode("cpl","c");
5047 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5050 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5051 pic16_outBitC(result);
5055 genIfxJump (ifx,"c");
5058 /* if the result is used in an arithmetic operation
5059 then put the result in place */
5060 pic16_outBitC(result);
5063 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5064 gencjne(left,right,result,ifx);
5067 gencjne(left,right,newiTempLabel(NULL));
5069 if(IC_TRUE(ifx)->key)
5070 gencjne(left,right,IC_TRUE(ifx)->key);
5072 gencjne(left,right,IC_FALSE(ifx)->key);
5076 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5077 pic16_aopPut(AOP(result),"a",0);
5082 genIfxJump (ifx,"a");
5086 /* if the result is used in an arithmetic operation
5087 then put the result in place */
5089 if (AOP_TYPE(result) != AOP_CRY)
5090 pic16_outAcc(result);
5092 /* leave the result in acc */
5096 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5097 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5098 pic16_freeAsmop(result,NULL,ic,TRUE);
5102 /*-----------------------------------------------------------------*/
5103 /* ifxForOp - returns the icode containing the ifx for operand */
5104 /*-----------------------------------------------------------------*/
5105 static iCode *ifxForOp ( operand *op, iCode *ic )
5109 /* if true symbol then needs to be assigned */
5110 if (IS_TRUE_SYMOP(op))
5113 /* if this has register type condition and
5114 the next instruction is ifx with the same operand
5115 and live to of the operand is upto the ifx only then */
5117 && ic->next->op == IFX
5118 && IC_COND(ic->next)->key == op->key
5119 && OP_SYMBOL(op)->liveTo <= ic->next->seq
5121 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5127 ic->next->op == IFX &&
5128 IC_COND(ic->next)->key == op->key) {
5129 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5134 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5136 ic->next->op == IFX)
5137 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5140 ic->next->op == IFX &&
5141 IC_COND(ic->next)->key == op->key) {
5142 DEBUGpic16_emitcode ("; "," key is okay");
5143 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5144 OP_SYMBOL(op)->liveTo,
5149 /* the code below is completely untested
5150 * it just allows ulong2fs.c compile -- VR */
5153 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5154 __FILE__, __FUNCTION__, __LINE__);
5156 /* if this has register type condition and
5157 the next instruction is ifx with the same operand
5158 and live to of the operand is upto the ifx only then */
5160 ic->next->op == IFX &&
5161 IC_COND(ic->next)->key == op->key &&
5162 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5166 ic->next->op == IFX &&
5167 IC_COND(ic->next)->key == op->key) {
5168 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5172 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5173 __FILE__, __FUNCTION__, __LINE__);
5175 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
5180 /*-----------------------------------------------------------------*/
5181 /* genAndOp - for && operation */
5182 /*-----------------------------------------------------------------*/
5183 static void genAndOp (iCode *ic)
5185 operand *left,*right, *result;
5190 /* note here that && operations that are in an
5191 if statement are taken away by backPatchLabels
5192 only those used in arthmetic operations remain */
5193 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5194 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5195 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5197 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5199 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5200 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5201 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5203 /* if both are bit variables */
5204 /* if (AOP_TYPE(left) == AOP_CRY && */
5205 /* AOP_TYPE(right) == AOP_CRY ) { */
5206 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5207 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5208 /* pic16_outBitC(result); */
5210 /* tlbl = newiTempLabel(NULL); */
5211 /* pic16_toBoolean(left); */
5212 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5213 /* pic16_toBoolean(right); */
5214 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5215 /* pic16_outBitAcc(result); */
5218 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5219 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5220 pic16_freeAsmop(result,NULL,ic,TRUE);
5224 /*-----------------------------------------------------------------*/
5225 /* genOrOp - for || operation */
5226 /*-----------------------------------------------------------------*/
5229 modified this code, but it doesn't appear to ever get called
5232 static void genOrOp (iCode *ic)
5234 operand *left,*right, *result;
5239 /* note here that || operations that are in an
5240 if statement are taken away by backPatchLabels
5241 only those used in arthmetic operations remain */
5242 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5243 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5244 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5246 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5248 /* if both are bit variables */
5249 if (AOP_TYPE(left) == AOP_CRY &&
5250 AOP_TYPE(right) == AOP_CRY ) {
5251 pic16_emitcode("clrc","");
5252 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5253 AOP(left)->aopu.aop_dir,
5254 AOP(left)->aopu.aop_dir);
5255 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5256 AOP(right)->aopu.aop_dir,
5257 AOP(right)->aopu.aop_dir);
5258 pic16_emitcode("setc","");
5261 tlbl = newiTempLabel(NULL);
5262 pic16_toBoolean(left);
5264 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5265 pic16_toBoolean(right);
5266 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5268 pic16_outBitAcc(result);
5271 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5272 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5273 pic16_freeAsmop(result,NULL,ic,TRUE);
5276 /*-----------------------------------------------------------------*/
5277 /* isLiteralBit - test if lit == 2^n */
5278 /*-----------------------------------------------------------------*/
5279 static int isLiteralBit(unsigned long lit)
5281 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5282 0x100L,0x200L,0x400L,0x800L,
5283 0x1000L,0x2000L,0x4000L,0x8000L,
5284 0x10000L,0x20000L,0x40000L,0x80000L,
5285 0x100000L,0x200000L,0x400000L,0x800000L,
5286 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5287 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5290 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5291 for(idx = 0; idx < 32; idx++)
5297 /*-----------------------------------------------------------------*/
5298 /* continueIfTrue - */
5299 /*-----------------------------------------------------------------*/
5300 static void continueIfTrue (iCode *ic)
5304 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5308 /*-----------------------------------------------------------------*/
5310 /*-----------------------------------------------------------------*/
5311 static void jumpIfTrue (iCode *ic)
5315 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5319 /*-----------------------------------------------------------------*/
5320 /* jmpTrueOrFalse - */
5321 /*-----------------------------------------------------------------*/
5322 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5324 // ugly but optimized by peephole
5327 symbol *nlbl = newiTempLabel(NULL);
5328 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5329 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5330 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5331 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5333 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5334 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5339 /*-----------------------------------------------------------------*/
5340 /* genAnd - code for and */
5341 /*-----------------------------------------------------------------*/
5342 static void genAnd (iCode *ic, iCode *ifx)
5344 operand *left, *right, *result;
5345 int size, offset = 0;
5346 unsigned long lit = 0L;
5351 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5352 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5353 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5355 resolveIfx (&rIfx, ifx);
5357 /* if left is a literal & right is not then exchange them */
5358 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5359 AOP_NEEDSACC (left))
5361 operand *tmp = right;
5366 /* if result = right then exchange them */
5367 if (pic16_sameRegs (AOP (result), AOP (right)))
5369 operand *tmp = right;
5374 /* if right is bit then exchange them */
5375 if (AOP_TYPE (right) == AOP_CRY &&
5376 AOP_TYPE (left) != AOP_CRY)
5378 operand *tmp = right;
5383 if (AOP_TYPE (right) == AOP_LIT)
5384 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5386 size = AOP_SIZE (result);
5388 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5391 // result = bit & yy;
5392 if (AOP_TYPE(left) == AOP_CRY){
5393 // c = bit & literal;
5394 if(AOP_TYPE(right) == AOP_LIT){
5396 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5399 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5402 if(size && (AOP_TYPE(result) == AOP_CRY)){
5403 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5406 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5410 pic16_emitcode("clr","c");
5413 if (AOP_TYPE(right) == AOP_CRY){
5415 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5416 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5419 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5421 pic16_emitcode("rrc","a");
5422 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5428 pic16_outBitC(result);
5430 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5431 genIfxJump(ifx, "c");
5435 // if (val & 0xZZ) - size = 0, ifx != FALSE -
5436 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5437 if ((AOP_TYPE (right) == AOP_LIT) &&
5438 (AOP_TYPE (result) == AOP_CRY) &&
5439 (AOP_TYPE (left) != AOP_CRY))
5441 symbol *tlbl = newiTempLabel (NULL);
5442 int sizel = AOP_SIZE (left);
5449 /* get number of non null bytes in literal */
5452 if (lit & (0xff << (sizel * 8)))
5456 emitBra = nonnull || rIfx.condition;
5458 for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5460 unsigned char bytelit = lit;
5468 /* patch provided by Aaron Colwell */
5469 if ((posbit = isLiteralBit (bytelit)) != 0)
5473 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5474 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5478 pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5483 if (bytelit == 0xff)
5485 /* Aaron had a MOVF instruction here, changed to MOVFW cause
5486 * a peephole could optimize it out -- VR */
5487 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5491 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5492 pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5499 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5503 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5508 /* last non null byte */
5518 // bit = left & literal
5522 pic16_emitpLabel (tlbl->key);
5525 // if(left & literal)
5531 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
5534 pic16_emitpLabel (tlbl->key);
5537 pic16_outBitC (result);
5541 /* if left is same as result */
5542 if(pic16_sameRegs(AOP(result),AOP(left))){
5544 for(;size--; offset++,lit>>=8) {
5545 if(AOP_TYPE(right) == AOP_LIT){
5546 switch(lit & 0xff) {
5548 /* and'ing with 0 has clears the result */
5549 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5550 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5553 /* and'ing with 0xff is a nop when the result and left are the same */
5558 int p = pic16_my_powof2( (~lit) & 0xff );
5560 /* only one bit is set in the literal, so use a bcf instruction */
5561 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5562 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5565 pic16_emitcode("movlw","0x%x", (lit & 0xff));
5566 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5567 if(know_W != (lit&0xff))
5568 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5570 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5575 if (AOP_TYPE(left) == AOP_ACC) {
5576 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5578 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5579 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5586 // left & result in different registers
5587 if(AOP_TYPE(result) == AOP_CRY){
5589 // if(size), result in bit
5590 // if(!size && ifx), conditional oper: if(left & right)
5591 symbol *tlbl = newiTempLabel(NULL);
5592 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5594 pic16_emitcode("setb","c");
5596 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5597 pic16_emitcode("anl","a,%s",
5598 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5599 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5604 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5605 pic16_outBitC(result);
5607 jmpTrueOrFalse(ifx, tlbl);
5609 for(;(size--);offset++) {
5611 // result = left & right
5612 if(AOP_TYPE(right) == AOP_LIT){
5613 int t = (lit >> (offset*8)) & 0x0FFL;
5616 pic16_emitcode("clrf","%s",
5617 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5618 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5621 pic16_emitcode("movf","%s,w",
5622 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5623 pic16_emitcode("movwf","%s",
5624 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5625 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5626 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5629 pic16_emitcode("movlw","0x%x",t);
5630 pic16_emitcode("andwf","%s,w",
5631 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5632 pic16_emitcode("movwf","%s",
5633 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5635 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5636 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5637 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5642 if (AOP_TYPE(left) == AOP_ACC) {
5643 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5644 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5646 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5647 pic16_emitcode("andwf","%s,w",
5648 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5649 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5650 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5652 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5653 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5659 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5660 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5661 pic16_freeAsmop(result,NULL,ic,TRUE);
5664 /*-----------------------------------------------------------------*/
5665 /* genOr - code for or */
5666 /*-----------------------------------------------------------------*/
5667 static void genOr (iCode *ic, iCode *ifx)
5669 operand *left, *right, *result;
5670 int size, offset = 0;
5671 unsigned long lit = 0L;
5676 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5677 pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5678 pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5680 resolveIfx (&rIfx, ifx);
5682 /* if left is a literal & right is not then exchange them */
5683 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5684 AOP_NEEDSACC (left))
5686 operand *tmp = right;
5691 /* if result = right then exchange them */
5692 if (pic16_sameRegs (AOP (result), AOP (right)))
5694 operand *tmp = right;
5699 /* if right is bit then exchange them */
5700 if (AOP_TYPE (right) == AOP_CRY &&
5701 AOP_TYPE (left) != AOP_CRY)
5703 operand *tmp = right;
5708 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5710 if (AOP_TYPE (right) == AOP_LIT)
5711 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5713 size = AOP_SIZE (result);
5717 if (AOP_TYPE(left) == AOP_CRY){
5718 if(AOP_TYPE(right) == AOP_LIT){
5719 // c = bit & literal;
5721 // lit != 0 => result = 1
5722 if(AOP_TYPE(result) == AOP_CRY){
5724 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5725 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5726 // AOP(result)->aopu.aop_dir,
5727 // AOP(result)->aopu.aop_dir);
5729 continueIfTrue(ifx);
5733 // lit == 0 => result = left
5734 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5736 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5739 if (AOP_TYPE(right) == AOP_CRY){
5740 if(pic16_sameRegs(AOP(result),AOP(left))){
5742 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5743 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5744 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5747 if( AOP_TYPE(result) == AOP_ACC) {
5748 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(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_MOVLW, pic16_popGetLit(1));
5755 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5756 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5757 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5758 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5764 symbol *tlbl = newiTempLabel(NULL);
5765 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5768 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5769 if( AOP_TYPE(right) == AOP_ACC) {
5770 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5772 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5773 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5778 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5779 pic16_emitcode(";XXX setb","c");
5780 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5781 AOP(left)->aopu.aop_dir,tlbl->key+100);
5782 pic16_toBoolean(right);
5783 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5784 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5785 jmpTrueOrFalse(ifx, tlbl);
5789 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5796 pic16_outBitC(result);
5798 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5799 genIfxJump(ifx, "c");
5803 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5804 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5805 if ((AOP_TYPE (right) == AOP_LIT) &&
5806 (AOP_TYPE (result) == AOP_CRY) &&
5807 (AOP_TYPE (left) != AOP_CRY))
5809 if (IS_OP_VOLATILE(left)) {
5810 pic16_mov2w_volatile(AOP(left));
5815 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5824 /* if left is same as result */
5825 if(pic16_sameRegs(AOP(result),AOP(left))){
5827 for(;size--; offset++,lit>>=8) {
5828 if(AOP_TYPE(right) == AOP_LIT){
5829 if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5830 /* or'ing with 0 has no effect */
5833 int p = pic16_my_powof2(lit & 0xff);
5835 /* only one bit is set in the literal, so use a bsf instruction */
5836 pic16_emitpcode(POC_BSF,
5837 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5839 if(know_W != (lit & 0xff))
5840 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5841 know_W = lit & 0xff;
5842 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5847 if (AOP_TYPE(left) == AOP_ACC) {
5848 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
5850 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5851 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5856 // left & result in different registers
5857 if(AOP_TYPE(result) == AOP_CRY){
5859 // if(size), result in bit
5860 // if(!size && ifx), conditional oper: if(left | right)
5861 symbol *tlbl = newiTempLabel(NULL);
5862 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5863 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5867 pic16_emitcode(";XXX setb","c");
5869 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5870 pic16_emitcode(";XXX orl","a,%s",
5871 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5872 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5877 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5878 pic16_outBitC(result);
5880 jmpTrueOrFalse(ifx, tlbl);
5881 } else for(;(size--);offset++){
5883 // result = left & right
5884 if(AOP_TYPE(right) == AOP_LIT){
5885 int t = (lit >> (offset*8)) & 0x0FFL;
5888 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
5889 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5892 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5893 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5894 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5899 // faster than result <- left, anl result,right
5900 // and better if result is SFR
5901 if (AOP_TYPE(left) == AOP_ACC) {
5902 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
5904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5905 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5907 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5912 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5913 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5914 pic16_freeAsmop(result,NULL,ic,TRUE);
5917 /*-----------------------------------------------------------------*/
5918 /* genXor - code for xclusive or */
5919 /*-----------------------------------------------------------------*/
5920 static void genXor (iCode *ic, iCode *ifx)
5922 operand *left, *right, *result;
5923 int size, offset = 0;
5924 unsigned long lit = 0L;
5929 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5930 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5931 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5933 resolveIfx (&rIfx,ifx);
5935 /* if left is a literal & right is not ||
5936 if left needs acc & right does not */
5937 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5938 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5940 operand *tmp = right;
5945 /* if result = right then exchange them */
5946 if (pic16_sameRegs (AOP (result), AOP (right)))
5948 operand *tmp = right ;
5953 /* if right is bit then exchange them */
5954 if (AOP_TYPE (right) == AOP_CRY &&
5955 AOP_TYPE (left) != AOP_CRY)
5957 operand *tmp = right ;
5962 if (AOP_TYPE (right) == AOP_LIT)
5963 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5965 size = AOP_SIZE (result);
5969 if (AOP_TYPE(left) == AOP_CRY)
5971 if (AOP_TYPE(right) == AOP_LIT)
5973 // c = bit & literal;
5976 // lit>>1 != 0 => result = 1
5977 if (AOP_TYPE(result) == AOP_CRY)
5981 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
5984 continueIfTrue(ifx);
5987 pic16_emitcode("setb", "c");
5994 // lit == 0, result = left
5995 if (size && pic16_sameRegs(AOP(result), AOP(left)))
5997 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6001 // lit == 1, result = not(left)
6002 if (size && pic16_sameRegs(AOP(result), AOP(left)))
6004 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6005 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6006 pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6011 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6012 pic16_emitcode("cpl", "c");
6020 symbol *tlbl = newiTempLabel(NULL);
6021 if (AOP_TYPE(right) == AOP_CRY)
6024 pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6028 int sizer = AOP_SIZE(right);
6030 // if val>>1 != 0, result = 1
6031 pic16_emitcode("setb", "c");
6034 MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6036 // test the msb of the lsb
6037 pic16_emitcode("anl", "a,#0xfe");
6038 pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6042 pic16_emitcode("rrc", "a");
6044 pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6045 pic16_emitcode("cpl", "c");
6046 pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6051 pic16_outBitC(result);
6053 else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6054 genIfxJump(ifx, "c");
6058 // if(val ^ 0xZZ) - size = 0, ifx != FALSE -
6059 // bit = val ^ 0xZZ - size = 1, ifx = FALSE -
6060 if ((AOP_TYPE (right) == AOP_LIT) &&
6061 (AOP_TYPE (result) == AOP_CRY) &&
6062 (AOP_TYPE (left) != AOP_CRY))
6064 symbol *tlbl = newiTempLabel (NULL);
6070 for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6072 unsigned char bytelit = lit;
6077 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6081 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6085 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6086 pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6093 /* rIfx.lbl might be far away... */
6095 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6099 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6104 /* last non null byte */
6112 // bit = left ^ literal
6116 pic16_emitpLabel (tlbl->key);
6118 // if (left ^ literal)
6123 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
6126 pic16_emitpLabel (tlbl->key);
6130 pic16_outBitC (result);
6134 if (pic16_sameRegs(AOP(result), AOP(left)))
6136 /* if left is same as result */
6137 for (; size--; offset++)
6139 if (AOP_TYPE(right) == AOP_LIT)
6141 int t = (lit >> (offset * 8)) & 0x0FFL;
6146 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6147 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6152 if (AOP_TYPE(left) == AOP_ACC)
6153 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6156 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6157 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6164 // left ^ result in different registers
6165 if (AOP_TYPE(result) == AOP_CRY)
6168 // if(size), result in bit
6169 // if(!size && ifx), conditional oper: if(left ^ right)
6170 symbol *tlbl = newiTempLabel(NULL);
6171 int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6173 pic16_emitcode("setb", "c");
6176 if ((AOP_TYPE(right) == AOP_LIT) &&
6177 (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6179 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6183 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6184 pic16_emitcode("xrl", "a,%s",
6185 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6187 pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6193 pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6194 pic16_outBitC(result);
6197 jmpTrueOrFalse(ifx, tlbl);
6201 for (; (size--); offset++)
6204 // result = left ^ right
6205 if (AOP_TYPE(right) == AOP_LIT)
6207 int t = (lit >> (offset * 8)) & 0x0FFL;
6211 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6212 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6216 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6217 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6221 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6222 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6223 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6228 // faster than result <- left, anl result,right
6229 // and better if result is SFR
6230 if (AOP_TYPE(left) == AOP_ACC)
6232 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6237 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6239 if ( AOP_TYPE(result) != AOP_ACC)
6241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6248 pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6249 pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6250 pic16_freeAsmop(result, NULL, ic, TRUE);
6253 /*-----------------------------------------------------------------*/
6254 /* genInline - write the inline code out */
6255 /*-----------------------------------------------------------------*/
6256 static void genInline (iCode *ic)
6258 char *buffer, *bp, *bp1;
6259 bool inComment = FALSE;
6261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6263 _G.inLine += (!options.asmpeep);
6265 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6267 while((bp1=strstr(bp, "\\n"))) {
6275 /* This is an experimental code for #pragma inline
6276 and is temporarily disabled for 2.5.0 release */
6284 cbuf = Safe_strdup(buffer);
6285 cblen = strlen(buffer)+1;
6286 memset(cbuf, 0, cblen);
6291 if(*bp != '%')*bp1++ = *bp++;
6297 if(i>elementsInSet(asmInlineMap))break;
6300 s = indexSet(asmInlineMap, i);
6301 DEBUGpc("searching symbol s = `%s'", s);
6302 sym = findSym(SymbolTab, NULL, s);
6305 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6307 strcat(bp1, sym->rname);
6313 if(strlen(bp1) > cblen - 16) {
6314 int i = strlen(cbuf);
6316 cbuf = realloc(cbuf, cblen);
6317 memset(cbuf+i, 0, 50);
6323 buffer = Safe_strdup( cbuf );
6330 /* emit each line as a code */
6344 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6349 /* Add \n for labels, not dirs such as c:\mydir */
6350 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6355 /* print label, use this special format with NULL directive
6356 * to denote that the argument should not be indented with tab */
6357 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6366 if ((bp1 != bp) && *bp1)
6367 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6371 _G.inLine -= (!options.asmpeep);
6374 /*-----------------------------------------------------------------*/
6375 /* genRRC - rotate right with carry */
6376 /*-----------------------------------------------------------------*/
6377 static void genRRC (iCode *ic)
6379 operand *left , *result ;
6382 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6384 /* rotate right with carry */
6386 result=IC_RESULT(ic);
6387 pic16_aopOp (left,ic,FALSE);
6388 pic16_aopOp (result,ic,TRUE);
6390 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6392 same = pic16_sameRegs(AOP(result),AOP(left));
6394 size = AOP_SIZE(result);
6396 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6398 /* get the lsb and put it into the carry */
6399 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
6404 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),size));
6406 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size));
6407 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
6411 pic16_freeAsmop(left,NULL,ic,TRUE);
6412 pic16_freeAsmop(result,NULL,ic,TRUE);
6415 /*-----------------------------------------------------------------*/
6416 /* genRLC - generate code for rotate left with carry */
6417 /*-----------------------------------------------------------------*/
6418 static void genRLC (iCode *ic)
6420 operand *left , *result ;
6421 int size, offset = 0;
6424 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6425 /* rotate right with carry */
6427 result=IC_RESULT(ic);
6428 pic16_aopOp (left,ic,FALSE);
6429 pic16_aopOp (result,ic,TRUE);
6431 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6433 same = pic16_sameRegs(AOP(result),AOP(left));
6435 /* move it to the result */
6436 size = AOP_SIZE(result);
6438 /* get the msb and put it into the carry */
6439 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6446 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6448 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6456 pic16_freeAsmop(left,NULL,ic,TRUE);
6457 pic16_freeAsmop(result,NULL,ic,TRUE);
6461 /* gpasm can get the highest order bit with HIGH/UPPER
6462 * so the following probably is not needed -- VR */
6464 /*-----------------------------------------------------------------*/
6465 /* genGetHbit - generates code get highest order bit */
6466 /*-----------------------------------------------------------------*/
6467 static void genGetHbit (iCode *ic)
6469 operand *left, *result;
6471 result=IC_RESULT(ic);
6472 pic16_aopOp (left,ic,FALSE);
6473 pic16_aopOp (result,ic,FALSE);
6475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6476 /* get the highest order byte into a */
6477 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6478 if(AOP_TYPE(result) == AOP_CRY){
6479 pic16_emitcode("rlc","a");
6480 pic16_outBitC(result);
6483 pic16_emitcode("rl","a");
6484 pic16_emitcode("anl","a,#0x01");
6485 pic16_outAcc(result);
6489 pic16_freeAsmop(left,NULL,ic,TRUE);
6490 pic16_freeAsmop(result,NULL,ic,TRUE);
6494 /*-----------------------------------------------------------------*/
6495 /* AccRol - rotate left accumulator by known count */
6496 /*-----------------------------------------------------------------*/
6497 static void AccRol (int shCount)
6499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6500 shCount &= 0x0007; // shCount : 0..7
6505 pic16_emitcode("rl","a");
6508 pic16_emitcode("rl","a");
6509 pic16_emitcode("rl","a");
6512 pic16_emitcode("swap","a");
6513 pic16_emitcode("rr","a");
6516 pic16_emitcode("swap","a");
6519 pic16_emitcode("swap","a");
6520 pic16_emitcode("rl","a");
6523 pic16_emitcode("rr","a");
6524 pic16_emitcode("rr","a");
6527 pic16_emitcode("rr","a");
6533 /*-----------------------------------------------------------------*/
6534 /* AccLsh - left shift accumulator by known count */
6535 /*-----------------------------------------------------------------*/
6536 static void AccLsh (int shCount, int doMask)
6538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6544 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6547 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6548 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6551 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6555 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6558 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6559 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6562 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6563 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6566 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6570 /* no masking is required in genPackBits */
6571 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6575 /*-----------------------------------------------------------------*/
6576 /* AccRsh - right shift accumulator by known count */
6577 /*-----------------------------------------------------------------*/
6578 static void AccRsh (int shCount, int andmask)
6580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6581 assert ((shCount >= 0) && (shCount <= 8));
6586 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6589 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6593 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6594 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6597 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6600 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6601 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6604 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6611 // Rotating by 8 is a NOP.
6616 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6618 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6621 /*-----------------------------------------------------------------*/
6622 /* shiftR1Left2Result - shift right one byte from left to result */
6623 /*-----------------------------------------------------------------*/
6624 static void shiftR1Left2ResultSigned (operand *left, int offl,
6625 operand *result, int offr,
6630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6631 assert ((shCount >= 0) && (shCount <= 8));
6633 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6635 /* Do NOT use result for intermediate results, it might be an SFR!. */
6639 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6640 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6645 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6647 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6649 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6650 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6655 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6656 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6657 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6658 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6659 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6660 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6664 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6665 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6666 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6667 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6668 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6673 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6674 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6675 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6676 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6681 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6682 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6684 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6685 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6690 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6691 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6693 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6694 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6700 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6702 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6706 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6711 /*-----------------------------------------------------------------*/
6712 /* shiftR1Left2Result - shift right one byte from left to result */
6713 /*-----------------------------------------------------------------*/
6714 static void shiftR1Left2Result (operand *left, int offl,
6715 operand *result, int offr,
6716 int shCount, int sign)
6720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6721 assert ((shCount >= 0) && (shCount <= 8));
6723 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6725 /* Copy the msb into the carry if signed. */
6727 shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6731 /* Do NOT use result for intermediate results, it might be an SFR!. */
6735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6736 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6743 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6745 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6746 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6752 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6753 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6754 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6759 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6760 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6766 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6767 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6772 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6773 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6774 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6779 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6780 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6781 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6782 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6786 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6787 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6792 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6797 /*-----------------------------------------------------------------*/
6798 /* shiftL1Left2Result - shift left one byte from left to result */
6799 /*-----------------------------------------------------------------*/
6800 static void shiftL1Left2Result (operand *left, int offl,
6801 operand *result, int offr, int shCount)
6805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6806 assert ((shCount >= 0) && (shCount <= 8));
6808 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6810 /* Do NOT use result for intermediate results, it might be an SFR!. */
6814 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6815 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6822 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6824 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6825 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6826 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6831 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6832 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6833 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6834 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6838 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6839 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6840 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6841 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6845 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6846 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6847 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6851 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6852 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6858 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6859 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6860 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6861 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6865 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6866 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6867 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6871 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6876 /*-----------------------------------------------------------------*/
6877 /* movLeft2Result - move byte from left to result */
6878 /*-----------------------------------------------------------------*/
6879 static void movLeft2Result (operand *left, int offl,
6880 operand *result, int offr)
6882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6883 if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6884 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6885 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6889 /*-----------------------------------------------------------------*/
6890 /* shiftL2Left2Result - shift left two bytes from left to result */
6891 /*-----------------------------------------------------------------*/
6892 static void shiftL2Left2Result (operand *left, int offl,
6893 operand *result, int offr, int shCount)
6895 int same = pic16_sameRegs(AOP(result), AOP(left));
6898 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6900 if (same && (offl != offr)) { // shift bytes
6903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6904 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6906 } else { // just treat as different later on
6919 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6920 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6921 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6925 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6926 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6932 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6933 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6934 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6935 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6936 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6937 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6938 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6940 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6941 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6945 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6947 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6948 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6950 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6951 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6952 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6953 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6954 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6958 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6959 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6960 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6971 /* note, use a mov/add for the shift since the mov has a
6972 chance of getting optimized out */
6973 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6974 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6975 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6976 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6981 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6982 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6988 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6989 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6991 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6993 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
6994 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6995 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6999 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7000 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7004 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl));
7005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7006 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
7007 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl+MSB16));
7008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7009 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr+MSB16));
7010 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xc0));
7011 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7012 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7013 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(result),offr));
7014 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(result),offr+MSB16));
7015 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7018 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7019 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7020 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7021 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7027 /*-----------------------------------------------------------------*/
7028 /* shiftR2Left2Result - shift right two bytes from left to result */
7029 /*-----------------------------------------------------------------*/
7030 static void shiftR2Left2Result (operand *left, int offl,
7031 operand *result, int offr,
7032 int shCount, int sign)
7034 int same = pic16_sameRegs(AOP(result), AOP(left));
7036 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7038 if (same && (offl != offr)) { // shift right bytes
7041 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7042 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7044 } else { // just treat as different later on
7055 /* obtain sign from left operand */
7057 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7062 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7063 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7065 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7066 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7067 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7068 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7073 /* now get sign from already assigned result (avoid BANKSEL) */
7074 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7077 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7078 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7085 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7086 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7087 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7089 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7090 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7091 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7092 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7094 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7095 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7096 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7098 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7099 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7100 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7101 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7102 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7106 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7107 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7111 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7112 pic16_emitpcode(POC_BTFSC,
7113 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7114 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7122 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7123 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7125 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7126 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7127 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7128 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7130 pic16_emitpcode(POC_BTFSC,
7131 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7132 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7134 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7135 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7136 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7137 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7139 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7140 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7141 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7142 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7143 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7144 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7145 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7146 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7148 pic16_emitpcode(POC_BTFSC,
7149 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7150 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7152 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7153 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7160 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7161 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7163 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7166 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7173 /*-----------------------------------------------------------------*/
7174 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7175 /*-----------------------------------------------------------------*/
7176 static void shiftLLeftOrResult (operand *left, int offl,
7177 operand *result, int offr, int shCount)
7179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7181 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7182 /* shift left accumulator */
7184 /* or with result */
7185 /* back to result */
7186 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7189 /*-----------------------------------------------------------------*/
7190 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7191 /*-----------------------------------------------------------------*/
7192 static void shiftRLeftOrResult (operand *left, int offl,
7193 operand *result, int offr, int shCount)
7195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7197 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7198 /* shift right accumulator */
7200 /* or with result */
7201 /* back to result */
7202 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7205 /*-----------------------------------------------------------------*/
7206 /* genlshOne - left shift a one byte quantity by known count */
7207 /*-----------------------------------------------------------------*/
7208 static void genlshOne (operand *result, operand *left, int shCount)
7210 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7211 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7214 /*-----------------------------------------------------------------*/
7215 /* genlshTwo - left shift two bytes by known amount != 0 */
7216 /*-----------------------------------------------------------------*/
7217 static void genlshTwo (operand *result,operand *left, int shCount)
7221 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7222 size = pic16_getDataSize(result);
7224 /* if shCount >= 8 */
7230 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7232 movLeft2Result(left, LSB, result, MSB16);
7234 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7237 /* 1 <= shCount <= 7 */
7240 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7242 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7246 /*-----------------------------------------------------------------*/
7247 /* shiftLLong - shift left one long from left to result */
7248 /* offr = LSB or MSB16 */
7249 /*-----------------------------------------------------------------*/
7250 static void shiftLLong (operand *left, operand *result, int offr )
7252 int size = AOP_SIZE(result);
7253 int same = pic16_sameRegs(AOP(left),AOP(result));
7256 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7258 if (same && (offr == MSB16)) { //shift one byte
7259 for(i=size-1;i>=MSB16;i--) {
7260 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7261 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7264 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB));
7267 if (size > LSB+offr ){
7269 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7271 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7272 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7276 if(size > MSB16+offr){
7278 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7280 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7281 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7285 if(size > MSB24+offr){
7287 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7289 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7290 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7294 if(size > MSB32+offr){
7296 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7298 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7299 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7303 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7307 /*-----------------------------------------------------------------*/
7308 /* genlshFour - shift four byte by a known amount != 0 */
7309 /*-----------------------------------------------------------------*/
7310 static void genlshFour (operand *result, operand *left, int shCount)
7314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7315 size = AOP_SIZE(result);
7317 /* if shifting more that 3 bytes */
7318 if (shCount >= 24 ) {
7321 /* lowest order of left goes to the highest
7322 order of the destination */
7323 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7325 movLeft2Result(left, LSB, result, MSB32);
7327 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7328 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7329 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7334 /* more than two bytes */
7335 else if ( shCount >= 16 ) {
7336 /* lower order two bytes goes to higher order two bytes */
7338 /* if some more remaining */
7340 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7342 movLeft2Result(left, MSB16, result, MSB32);
7343 movLeft2Result(left, LSB, result, MSB24);
7345 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7346 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7350 /* if more than 1 byte */
7351 else if ( shCount >= 8 ) {
7352 /* lower order three bytes goes to higher order three bytes */
7356 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7358 movLeft2Result(left, LSB, result, MSB16);
7360 else{ /* size = 4 */
7362 movLeft2Result(left, MSB24, result, MSB32);
7363 movLeft2Result(left, MSB16, result, MSB24);
7364 movLeft2Result(left, LSB, result, MSB16);
7365 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7367 else if(shCount == 1)
7368 shiftLLong(left, result, MSB16);
7370 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7371 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7372 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7373 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7378 /* 1 <= shCount <= 7 */
7379 else if(shCount <= 3)
7381 shiftLLong(left, result, LSB);
7382 while(--shCount >= 1)
7383 shiftLLong(result, result, LSB);
7385 /* 3 <= shCount <= 7, optimize */
7387 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7388 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7389 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7393 /*-----------------------------------------------------------------*/
7394 /* genLeftShiftLiteral - left shifting by known count */
7395 /*-----------------------------------------------------------------*/
7396 void pic16_genLeftShiftLiteral (operand *left,
7401 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7405 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7406 pic16_freeAsmop(right,NULL,ic,TRUE);
7408 pic16_aopOp(left,ic,FALSE);
7409 pic16_aopOp(result,ic,TRUE);
7411 size = getSize(operandType(result));
7414 pic16_emitcode("; shift left ","result %d, left %d",size,
7418 /* I suppose that the left size >= result size */
7421 movLeft2Result(left, size, result, size);
7425 else if(shCount >= (size * 8))
7427 pic16_aopPut(AOP(result),zero,size);
7431 genlshOne (result,left,shCount);
7436 genlshTwo (result,left,shCount);
7440 genlshFour (result,left,shCount);
7444 pic16_freeAsmop(left,NULL,ic,TRUE);
7445 pic16_freeAsmop(result,NULL,ic,TRUE);
7448 /*-----------------------------------------------------------------*
7449 * genMultiAsm - repeat assembly instruction for size of register.
7450 * if endian == 1, then the high byte (i.e base address + size of
7451 * register) is used first else the low byte is used first;
7452 *-----------------------------------------------------------------*/
7453 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7458 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7471 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7477 /*-----------------------------------------------------------------*/
7478 /* genrshOne - right shift a one byte quantity by known count */
7479 /*-----------------------------------------------------------------*/
7480 static void genrshOne (operand *result, operand *left,
7481 int shCount, int sign)
7483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7484 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7487 /*-----------------------------------------------------------------*/
7488 /* genrshTwo - right shift two bytes by known amount != 0 */
7489 /*-----------------------------------------------------------------*/
7490 static void genrshTwo (operand *result,operand *left,
7491 int shCount, int sign)
7493 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7494 /* if shCount >= 8 */
7498 shiftR1Left2Result(left, MSB16, result, LSB,
7501 movLeft2Result(left, MSB16, result, LSB);
7503 pic16_addSign (result, 1, sign);
7506 /* 1 <= shCount <= 7 */
7508 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7511 /*-----------------------------------------------------------------*/
7512 /* shiftRLong - shift right one long from left to result */
7513 /* offl = LSB or MSB16 */
7514 /*-----------------------------------------------------------------*/
7515 static void shiftRLong (operand *left, int offl,
7516 operand *result, int sign)
7518 int size = AOP_SIZE(result);
7519 int same = pic16_sameRegs(AOP(left),AOP(result));
7521 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7523 if (same && (offl == MSB16)) { //shift one byte right
7524 for(i=MSB16;i<size;i++) {
7525 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7526 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7531 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7537 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7539 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7540 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7544 /* add sign of "a" */
7545 pic16_addSign(result, MSB32, sign);
7549 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7551 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7552 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7556 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7558 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7559 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7563 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7566 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7572 /*-----------------------------------------------------------------*/
7573 /* genrshFour - shift four byte by a known amount != 0 */
7574 /*-----------------------------------------------------------------*/
7575 static void genrshFour (operand *result, operand *left,
7576 int shCount, int sign)
7578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7579 /* if shifting more that 3 bytes */
7580 if(shCount >= 24 ) {
7583 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7585 movLeft2Result(left, MSB32, result, LSB);
7587 pic16_addSign(result, MSB16, sign);
7589 else if(shCount >= 16){
7592 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7594 movLeft2Result(left, MSB24, result, LSB);
7595 movLeft2Result(left, MSB32, result, MSB16);
7597 pic16_addSign(result, MSB24, sign);
7599 else if(shCount >= 8){
7602 shiftRLong(left, MSB16, result, sign);
7603 else if(shCount == 0){
7604 movLeft2Result(left, MSB16, result, LSB);
7605 movLeft2Result(left, MSB24, result, MSB16);
7606 movLeft2Result(left, MSB32, result, MSB24);
7607 pic16_addSign(result, MSB32, sign);
7609 else{ //shcount >= 2
7610 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7611 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7612 /* the last shift is signed */
7613 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7614 pic16_addSign(result, MSB32, sign);
7617 else{ /* 1 <= shCount <= 7 */
7619 shiftRLong(left, LSB, result, sign);
7621 shiftRLong(result, LSB, result, sign);
7624 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7625 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7626 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7631 /*-----------------------------------------------------------------*/
7632 /* genRightShiftLiteral - right shifting by known count */
7633 /*-----------------------------------------------------------------*/
7634 static void genRightShiftLiteral (operand *left,
7640 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7643 pic16_freeAsmop(right,NULL,ic,TRUE);
7645 pic16_aopOp(left,ic,FALSE);
7646 pic16_aopOp(result,ic,TRUE);
7648 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7651 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7655 lsize = pic16_getDataSize(left);
7656 res_size = pic16_getDataSize(result);
7657 /* test the LEFT size !!! */
7659 /* I suppose that the left size >= result size */
7661 assert (res_size <= lsize);
7662 while (res_size--) {
7663 pic16_mov2f (AOP(result), AOP(left), res_size);
7665 } else if (shCount >= (lsize * 8)) {
7672 * even for 8-bit operands; result might be an SFR.
7674 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7675 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7676 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7677 while (res_size--) {
7678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7680 } else { // unsigned
7681 while (res_size--) {
7682 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7685 } else { // 0 < shCount < 8*lsize
7688 genrshOne (result,left,shCount,sign);
7692 genrshTwo (result,left,shCount,sign);
7696 genrshFour (result,left,shCount,sign);
7703 pic16_freeAsmop(left,NULL,ic,TRUE);
7704 pic16_freeAsmop(result,NULL,ic,TRUE);
7707 /*-----------------------------------------------------------------*/
7708 /* genGenericShift - generates code for left or right shifting */
7709 /*-----------------------------------------------------------------*/
7710 static void genGenericShift (iCode *ic, int isShiftLeft)
7712 operand *left,*right, *result;
7714 int sign, signedCount;
7715 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7716 PIC_OPCODE pos_shift, neg_shift;
7720 right = IC_RIGHT(ic);
7722 result = IC_RESULT(ic);
7724 pic16_aopOp(right,ic,FALSE);
7725 pic16_aopOp(left,ic,FALSE);
7726 pic16_aopOp(result,ic,TRUE);
7728 sign = !SPEC_USIGN(operandType (left));
7729 signedCount = !SPEC_USIGN(operandType (right));
7731 /* if the shift count is known then do it
7732 as efficiently as possible */
7733 if (AOP_TYPE(right) == AOP_LIT) {
7734 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7735 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7736 // we should modify right->aopu.aop_lit here!
7737 // Instead we use abs(shCount) in genXXXShiftLiteral()...
7738 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7740 pic16_genLeftShiftLiteral (left,right,result,ic);
7742 genRightShiftLiteral (left,right,result,ic, sign);
7745 } // if (right is literal)
7747 /* shift count is unknown then we have to form a loop.
7748 * Note: we take only the lower order byte since shifting
7749 * more than 32 bits make no sense anyway, ( the
7750 * largest size of an object can be only 32 bits )
7751 * Note: we perform arithmetic shifts if the left operand is
7752 * signed and we do an (effective) right shift, i. e. we
7753 * shift in the sign bit from the left. */
7755 label_complete = newiTempLabel ( NULL );
7756 label_loop_pos = newiTempLabel ( NULL );
7757 label_loop_neg = NULL;
7758 label_negative = NULL;
7759 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7760 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7763 // additional labels needed
7764 label_loop_neg = newiTempLabel ( NULL );
7765 label_negative = newiTempLabel ( NULL );
7768 // copy source to result -- this will effectively truncate the left operand to the size of result!
7769 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7770 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7771 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7772 pic16_mov2f (AOP(result),AOP(left), offset);
7775 // if result is longer than left, fill with zeros (or sign)
7776 if (AOP_SIZE(left) < AOP_SIZE(result)) {
7777 if (sign && AOP_SIZE(left) > 0) {
7778 // shift signed operand -- fill with sign
7779 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7780 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7781 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7782 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7783 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7786 // shift unsigned operand -- fill result with zeros
7787 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7788 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7791 } // if (size mismatch)
7793 pic16_mov2w (AOP(right), 0);
7794 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7795 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7798 // perform a shift by one (shift count is positive)
7799 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7800 // 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])
7801 pic16_emitpLabel (label_loop_pos->key);
7803 if (sign && (pos_shift == POC_RRCF)) {
7804 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7807 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7808 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7809 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7811 // perform a shift by one (shift count is positive)
7812 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7813 // 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])
7814 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7815 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7817 pic16_emitpLabel (label_loop_pos->key);
7818 if (sign && (pos_shift == POC_RRCF)) {
7819 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7822 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7823 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7824 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7825 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7829 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7831 pic16_emitpLabel (label_negative->key);
7832 // perform a shift by -1 (shift count is negative)
7833 // 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)
7835 pic16_emitpLabel (label_loop_neg->key);
7836 if (sign && (neg_shift == POC_RRCF)) {
7837 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7840 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7841 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7842 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7843 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7844 } // if (signedCount)
7846 pic16_emitpLabel (label_complete->key);
7849 pic16_freeAsmop (right,NULL,ic,TRUE);
7850 pic16_freeAsmop(left,NULL,ic,TRUE);
7851 pic16_freeAsmop(result,NULL,ic,TRUE);
7854 static void genLeftShift (iCode *ic) {
7855 genGenericShift (ic, 1);
7858 static void genRightShift (iCode *ic) {
7859 genGenericShift (ic, 0);
7863 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7864 void pic16_loadFSR0(operand *op, int lit)
7866 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7867 if (AOP_TYPE(op) == AOP_LIT) {
7868 /* handle 12 bit integers correctly */
7869 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7870 if ((val & 0x0fff) != val) {
7871 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7872 val, (val & 0x0fff) );
7875 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7877 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7880 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7881 // set up FSR0 with address of result
7882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7883 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7887 /*----------------------------------------------------------------*/
7888 /* pic16_derefPtr - move one byte from the location ptr points to */
7889 /* to WREG (doWrite == 0) or one byte from WREG */
7890 /* to the location ptr points to (doWrite != 0) */
7891 /*----------------------------------------------------------------*/
7892 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7894 if (!IS_PTR(operandType(ptr)))
7896 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7897 else pic16_mov2w (AOP(ptr), 0);
7901 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7902 /* We might determine pointer type right here: */
7903 p_type = DCL_TYPE(operandType(ptr));
7908 if (!fsr0_setup || !*fsr0_setup)
7910 pic16_loadFSR0( ptr, 0 );
7911 if (fsr0_setup) *fsr0_setup = 1;
7914 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7916 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7920 if (AOP(ptr)->aopu.aop_reg[2]) {
7921 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7922 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7923 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7924 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7925 pic16_mov2w(AOP(ptr), 2);
7926 pic16_callGenericPointerRW(doWrite, 1);
7928 // data pointer (just 2 byte given)
7929 if (!fsr0_setup || !*fsr0_setup)
7931 pic16_loadFSR0( ptr, 0 );
7932 if (fsr0_setup) *fsr0_setup = 1;
7935 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7937 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7942 assert (0 && "invalid pointer type specified");
7947 /*-----------------------------------------------------------------*/
7948 /* genUnpackBits - generates code for unpacking bits */
7949 /*-----------------------------------------------------------------*/
7950 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7953 sym_link *etype, *letype;
7959 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7960 etype = getSpec(operandType(result));
7961 letype = getSpec(operandType(left));
7963 // if(IS_BITFIELD(etype)) {
7964 blen = SPEC_BLEN(etype);
7965 bstr = SPEC_BSTR(etype);
7968 lbstr = SPEC_BSTR( letype );
7970 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7971 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7974 if((blen == 1) && (bstr < 8)
7975 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
7976 /* it is a single bit, so use the appropriate bit instructions */
7977 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
7979 same = pic16_sameRegs(AOP(left),AOP(result));
7980 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
7981 pic16_emitpcode(POC_CLRF, op);
7983 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
7984 /* workaround to reduce the extra lfsr instruction */
7985 pic16_emitpcode(POC_BTFSC,
7986 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
7988 assert (PIC_IS_DATA_PTR (operandType(left)));
7989 pic16_loadFSR0 (left, 0);
7990 pic16_emitpcode(POC_BTFSC,
7991 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
7994 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7995 /* unsigned bitfields result in either 0 or 1 */
7996 pic16_emitpcode(POC_INCF, op);
7998 /* signed bitfields result in either 0 or -1 */
7999 pic16_emitpcode(POC_DECF, op);
8002 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8005 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8011 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8012 // access symbol directly
8013 pic16_mov2w (AOP(left), 0);
8015 pic16_derefPtr (left, ptype, 0, NULL);
8018 /* if we have bitdisplacement then it fits */
8019 /* into this byte completely or if length is */
8020 /* less than a byte */
8021 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
8023 /* shift right acc */
8026 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8027 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8029 /* VR -- normally I would use the following, but since we use the hack,
8030 * to avoid the masking from AccRsh, why not mask it right now? */
8033 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8036 /* extend signed bitfields to 8 bits */
8037 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8039 assert (blen + bstr > 0);
8040 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8041 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8044 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8046 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8050 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8051 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8058 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8060 int size, offset = 0, leoffset=0 ;
8062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8063 pic16_aopOp(result, ic, TRUE);
8067 size = AOP_SIZE(result);
8068 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8072 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8073 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8074 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8079 if(AOP(left)->aopu.pcop->type == PO_DIR)
8080 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8082 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8085 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8087 // pic16_DumpOp("(result)",result);
8088 if(pic16_isLitAop(AOP(result))) {
8089 pic16_mov2w(AOP(left), offset); // patch 8
8090 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8092 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8093 pic16_popGet(AOP(left), offset), //patch 8
8094 pic16_popGet(AOP(result), offset)));
8102 pic16_freeAsmop(result,NULL,ic,TRUE);
8107 /*-----------------------------------------------------------------*/
8108 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8109 /*-----------------------------------------------------------------*/
8110 static void genNearPointerGet (operand *left,
8114 // asmop *aop = NULL;
8115 //regs *preg = NULL ;
8116 sym_link *rtype, *retype;
8117 sym_link *ltype, *letype;
8121 rtype = operandType(result);
8122 retype= getSpec(rtype);
8123 ltype = operandType(left);
8124 letype= getSpec(ltype);
8126 pic16_aopOp(left,ic,FALSE);
8128 // pic16_DumpOp("(left)",left);
8129 // pic16_DumpOp("(result)",result);
8131 /* if left is rematerialisable and
8132 * result is not bit variable type and
8133 * the left is pointer to data space i.e
8134 * lower 128 bytes of space */
8136 if (AOP_TYPE(left) == AOP_PCODE
8137 && !IS_BITFIELD(retype)
8138 && DCL_TYPE(ltype) == POINTER) {
8140 genDataPointerGet (left,result,ic);
8141 pic16_freeAsmop(left, NULL, ic, TRUE);
8145 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8146 pic16_aopOp (result,ic,TRUE);
8148 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8151 if(IS_BITFIELD( retype )
8152 && (SPEC_BLEN(operandType(result))==1)
8156 int bitstrt, bytestrt;
8158 /* if this is bitfield of size 1, see if we are checking the value
8159 * of a single bit in an if-statement,
8160 * if yes, then don't generate usual code, but execute the
8161 * genIfx directly -- VR */
8165 /* CHECK: if next iCode is IFX
8166 * and current result operand is nextic's conditional operand
8167 * and current result operand live ranges ends at nextic's key number
8169 if((nextic->op == IFX)
8170 && (result == IC_COND(nextic))
8171 && (OP_LIVETO(result) == nextic->seq)
8172 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
8174 /* everything is ok then */
8175 /* find a way to optimize the genIfx iCode */
8177 bytestrt = SPEC_BSTR(operandType(result))/8;
8178 bitstrt = SPEC_BSTR(operandType(result))%8;
8180 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8182 genIfxpCOpJump(nextic, jop);
8184 pic16_freeAsmop(left, NULL, ic, TRUE);
8185 pic16_freeAsmop(result, NULL, ic, TRUE);
8191 /* if bitfield then unpack the bits */
8192 if (IS_BITFIELD(letype))
8193 genUnpackBits (result, left, NULL, POINTER);
8195 /* we have can just get the values */
8196 int size = AOP_SIZE(result);
8199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8201 pic16_loadFSR0( left, 0 );
8205 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8206 pic16_popGet(AOP(result), offset++)));
8208 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8209 pic16_popGet(AOP(result), offset++)));
8215 /* now some housekeeping stuff */
8217 /* we had to allocate for this iCode */
8218 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8219 pic16_freeAsmop(NULL,aop,ic,TRUE);
8221 /* we did not allocate which means left
8222 * already in a pointer register, then
8223 * if size > 0 && this could be used again
8224 * we have to point it back to where it
8226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8227 if (AOP_SIZE(result) > 1
8228 && !OP_SYMBOL(left)->remat
8229 && ( OP_SYMBOL(left)->liveTo > ic->seq
8231 // int size = AOP_SIZE(result) - 1;
8233 // pic16_emitcode("dec","%s",rname);
8239 pic16_freeAsmop(left,NULL,ic,TRUE);
8240 pic16_freeAsmop(result,NULL,ic,TRUE);
8243 /*-----------------------------------------------------------------*/
8244 /* genGenPointerGet - gget value from generic pointer space */
8245 /*-----------------------------------------------------------------*/
8246 static void genGenPointerGet (operand *left,
8247 operand *result, iCode *ic)
8250 sym_link *letype = getSpec(operandType(left));
8252 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8253 pic16_aopOp(left,ic,FALSE);
8254 pic16_aopOp(result,ic,TRUE);
8255 size = AOP_SIZE(result);
8257 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8259 /* if bit then unpack */
8260 if (IS_BITFIELD(letype)) {
8261 genUnpackBits(result,left,"BAD",GPOINTER);
8265 /* set up WREG:PRODL:FSR0L with address from left */
8266 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8267 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8268 pic16_mov2w(AOP(left), 2);
8269 pic16_callGenericPointerRW(0, size);
8271 assignResultValue(result, size, 1);
8274 pic16_freeAsmop(left,NULL,ic,TRUE);
8275 pic16_freeAsmop(result,NULL,ic,TRUE);
8278 /*-----------------------------------------------------------------*/
8279 /* genConstPointerGet - get value from const generic pointer space */
8280 /*-----------------------------------------------------------------*/
8281 static void genConstPointerGet (operand *left,
8282 operand *result, iCode *ic)
8284 //sym_link *retype = getSpec(operandType(result));
8285 // symbol *albl = newiTempLabel(NULL); // patch 15
8286 // symbol *blbl = newiTempLabel(NULL); //
8287 // PIC_OPCODE poc; // patch 15
8291 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8292 pic16_aopOp(left,ic,FALSE);
8293 pic16_aopOp(result,ic,TRUE);
8294 size = AOP_SIZE(result);
8296 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8298 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8300 // set up table pointer
8301 if( (AOP_TYPE(left) == AOP_PCODE)
8302 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8303 || (AOP(left)->aopu.pcop->type == PO_DIR)))
8305 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8306 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8307 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8308 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8309 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8310 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8312 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8313 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8314 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8318 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8319 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8323 pic16_freeAsmop(left,NULL,ic,TRUE);
8324 pic16_freeAsmop(result,NULL,ic,TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genPointerGet - generate code for pointer get */
8330 /*-----------------------------------------------------------------*/
8331 static void genPointerGet (iCode *ic)
8333 operand *left, *result ;
8334 sym_link *type, *etype;
8340 result = IC_RESULT(ic) ;
8342 /* depending on the type of pointer we need to
8343 move it to the correct pointer register */
8344 type = operandType(left);
8345 etype = getSpec(type);
8348 if (IS_PTR_CONST(type))
8350 if (IS_CODEPTR(type))
8352 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8354 /* if left is of type of pointer then it is simple */
8355 if (IS_PTR(type) && !IS_FUNC(type->next))
8356 p_type = DCL_TYPE(type);
8358 /* we have to go by the storage class */
8359 p_type = PTR_TYPE(SPEC_OCLS(etype));
8361 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8363 if (SPEC_OCLS(etype)->codesp ) {
8364 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8365 //p_type = CPOINTER ;
8367 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8368 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8369 /*p_type = FPOINTER ;*/
8371 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8372 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8373 /* p_type = PPOINTER; */
8375 if (SPEC_OCLS(etype) == idata ) {
8376 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8377 /* p_type = IPOINTER; */
8379 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8380 /* p_type = POINTER ; */
8384 /* now that we have the pointer type we assign
8385 the pointer values */
8390 genNearPointerGet (left,result,ic);
8394 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8396 genPagedPointerGet(left,result,ic);
8400 genFarPointerGet (left,result,ic);
8405 genConstPointerGet (left,result,ic);
8406 //pic16_emitcodePointerGet (left,result,ic);
8411 if (IS_PTR_CONST(type))
8412 genConstPointerGet (left,result,ic);
8415 genGenPointerGet (left,result,ic);
8419 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8420 "genPointerGet: illegal pointer type");
8425 /*-----------------------------------------------------------------*/
8426 /* genPackBits - generates code for packed bit storage */
8427 /*-----------------------------------------------------------------*/
8428 static void genPackBits (sym_link *etype , operand *result,
8430 char *rname, int p_type)
8436 int shifted_and_masked = 0;
8437 unsigned long lit = (unsigned long)-1;
8440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8441 blen = SPEC_BLEN(etype);
8442 bstr = SPEC_BSTR(etype);
8444 retype = getSpec(operandType(right));
8446 if(AOP_TYPE(right) == AOP_LIT) {
8447 lit = ulFromVal (AOP(right)->aopu.aop_lit);
8449 if((blen == 1) && (bstr < 8)) {
8450 /* it is a single bit, so use the appropriate bit instructions */
8452 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8454 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8455 /* workaround to reduce the extra lfsr instruction */
8457 pic16_emitpcode(POC_BSF,
8458 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8460 pic16_emitpcode(POC_BCF,
8461 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8464 if (PIC_IS_DATA_PTR(operandType(result))) {
8465 pic16_loadFSR0(result, 0);
8466 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8467 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8470 pic16_derefPtr (result, p_type, 0, NULL);
8471 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8472 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8473 /* write back new value */
8474 pic16_derefPtr (result, p_type, 1, NULL);
8480 /* IORLW below is more efficient */
8481 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8482 lit = (lit & ((1UL << blen) - 1)) << bstr;
8483 shifted_and_masked = 1;
8486 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8487 && IS_BITFIELD(retype)
8488 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8492 rblen = SPEC_BLEN( retype );
8493 rbstr = SPEC_BSTR( retype );
8495 if(IS_BITFIELD(etype)) {
8496 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8497 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8499 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8502 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8504 if(IS_BITFIELD(etype)) {
8505 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8507 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8510 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8514 /* move right to W */
8515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8518 /* if the bit length is less than or */
8519 /* it exactly fits a byte then */
8520 if((shCnt=SPEC_BSTR(etype))
8521 || SPEC_BLEN(etype) <= 8 ) {
8524 if (blen != 8 || (bstr % 8) != 0) {
8525 // we need to combine the value with the old value
8526 if(!shifted_and_masked)
8528 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8530 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8531 SPEC_BSTR(etype), SPEC_BLEN(etype));
8533 /* shift left acc, do NOT mask the result again */
8536 /* using PRODH as a temporary register here */
8537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8540 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8541 || IS_DIRECT(result)) {
8542 /* access symbol directly */
8543 pic16_mov2w (AOP(result), 0);
8546 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8549 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8550 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8551 (unsigned char)(0xff >> (8-bstr))) ));
8552 if (!shifted_and_masked) {
8553 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8555 /* We have the shifted and masked (literal) right value in `lit' */
8557 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8559 } else { // if (blen == 8 && (bstr % 8) == 0)
8560 if (shifted_and_masked) {
8561 // move right (literal) to WREG (only case where right is not yet in WREG)
8562 pic16_mov2w(AOP(right), (bstr / 8));
8566 /* write new value back */
8567 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8568 || IS_DIRECT(result)) {
8569 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8571 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8580 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8581 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8586 pic16_loadFSR0(result, 0); // load FSR0 with address of result
8587 rLen = SPEC_BLEN(etype)-8;
8589 /* now generate for lengths greater than one byte */
8593 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8599 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8605 pic16_emitcode("movx","@dptr,a");
8610 DEBUGpic16_emitcode(";lcall","__gptrput");
8618 pic16_mov2w(AOP(right), offset++);
8621 /* last last was not complete */
8623 /* save the byte & read byte */
8626 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8627 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8632 pic16_emitcode ("mov","b,a");
8633 pic16_emitcode("movx","a,@dptr");
8637 pic16_emitcode ("push","b");
8638 pic16_emitcode ("push","acc");
8639 pic16_emitcode ("lcall","__gptrget");
8640 pic16_emitcode ("pop","b");
8646 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8647 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8648 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8649 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8650 // pic16_emitcode ("orl","a,b");
8653 // if (p_type == GPOINTER)
8654 // pic16_emitcode("pop","b");
8659 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8660 // pic16_emitcode("mov","@%s,a",rname);
8664 pic16_emitcode("movx","@dptr,a");
8668 DEBUGpic16_emitcode(";lcall","__gptrput");
8675 // pic16_freeAsmop(right, NULL, ic, TRUE);
8678 /*-----------------------------------------------------------------*/
8679 /* genDataPointerSet - remat pointer to data space */
8680 /*-----------------------------------------------------------------*/
8681 static void genDataPointerSet(operand *right,
8685 int size, offset = 0, resoffset=0 ;
8687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8688 pic16_aopOp(right,ic,FALSE);
8690 size = AOP_SIZE(right);
8692 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8695 if ( AOP_TYPE(result) == AOP_PCODE) {
8696 fprintf(stderr,"genDataPointerSet %s, %d\n",
8697 AOP(result)->aopu.pcop->name,
8698 (AOP(result)->aopu.pcop->type == PO_DIR)?
8699 PCOR(AOP(result)->aopu.pcop)->instance:
8700 PCOI(AOP(result)->aopu.pcop)->offset);
8704 if(AOP(result)->aopu.pcop->type == PO_DIR)
8705 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8708 if (AOP_TYPE(right) == AOP_LIT) {
8709 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8710 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8712 pic16_mov2w(AOP(right), offset);
8713 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8719 pic16_freeAsmop(right,NULL,ic,TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genNearPointerSet - pic16_emitcode for near pointer put */
8726 /*-----------------------------------------------------------------*/
8727 static void genNearPointerSet (operand *right,
8733 sym_link *ptype = operandType(result);
8736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8737 retype= getSpec(operandType(right));
8738 resetype = getSpec(operandType(result));
8740 pic16_aopOp(result,ic,FALSE);
8742 /* if the result is rematerializable &
8743 * in data space & not a bit variable */
8745 /* and result is not a bit variable */
8746 if (AOP_TYPE(result) == AOP_PCODE
8747 && DCL_TYPE(ptype) == POINTER
8748 && !IS_BITFIELD(retype)
8749 && !IS_BITFIELD(resetype)) {
8751 genDataPointerSet (right,result,ic);
8752 pic16_freeAsmop(result,NULL,ic,TRUE);
8756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8757 pic16_aopOp(right,ic,FALSE);
8758 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8760 /* if bitfield then unpack the bits */
8761 if (IS_BITFIELD(resetype)) {
8762 genPackBits (resetype, result, right, NULL, POINTER);
8764 /* we have can just get the values */
8765 int size = AOP_SIZE(right);
8768 pic16_loadFSR0(result, 0);
8770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8772 if (pic16_isLitOp(right)) {
8773 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8775 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8777 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8779 } else { // no literal
8781 pic16_emitpcode(POC_MOVFF,
8782 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8783 pic16_popCopyReg(&pic16_pc_postinc0)));
8785 pic16_emitpcode(POC_MOVFF,
8786 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8787 pic16_popCopyReg(&pic16_pc_indf0)));
8795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8796 /* now some housekeeping stuff */
8798 /* we had to allocate for this iCode */
8799 pic16_freeAsmop(NULL,aop,ic,TRUE);
8801 /* we did not allocate which means left
8802 * already in a pointer register, then
8803 * if size > 0 && this could be used again
8804 * we have to point it back to where it
8806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8807 if (AOP_SIZE(right) > 1
8808 && !OP_SYMBOL(result)->remat
8809 && ( OP_SYMBOL(result)->liveTo > ic->seq
8812 int size = AOP_SIZE(right) - 1;
8815 pic16_emitcode("decf","fsr0,f");
8816 //pic16_emitcode("dec","%s",rname);
8820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8823 pic16_freeAsmop(right,NULL,ic,TRUE);
8824 pic16_freeAsmop(result,NULL,ic,TRUE);
8827 /*-----------------------------------------------------------------*/
8828 /* genGenPointerSet - set value from generic pointer space */
8829 /*-----------------------------------------------------------------*/
8830 static void genGenPointerSet (operand *right,
8831 operand *result, iCode *ic)
8834 sym_link *retype = getSpec(operandType(result));
8836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8838 pic16_aopOp(result,ic,FALSE);
8839 pic16_aopOp(right,ic,FALSE);
8840 size = AOP_SIZE(right);
8842 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8845 /* if bit then unpack */
8846 if (IS_BITFIELD(retype)) {
8847 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8848 genPackBits(retype,result,right,"dptr",GPOINTER);
8852 size = AOP_SIZE(right);
8854 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
8857 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8859 /* value of right+0 is placed on stack, which will be retrieved
8860 * by the support function thus restoring the stack. The important
8861 * thing is that there is no need to manually restore stack pointer
8863 pushaop(AOP(right), 0);
8864 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8865 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8866 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8867 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8869 /* load address to write to in WREG:FSR0H:FSR0L */
8870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8871 pic16_popCopyReg(&pic16_pc_fsr0l)));
8872 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8873 pic16_popCopyReg(&pic16_pc_prodl)));
8874 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8876 pic16_callGenericPointerRW(1, size);
8879 pic16_freeAsmop(right,NULL,ic,TRUE);
8880 pic16_freeAsmop(result,NULL,ic,TRUE);
8883 /*-----------------------------------------------------------------*/
8884 /* genPointerSet - stores the value into a pointer location */
8885 /*-----------------------------------------------------------------*/
8886 static void genPointerSet (iCode *ic)
8888 operand *right, *result ;
8889 sym_link *type, *etype;
8894 right = IC_RIGHT(ic);
8895 result = IC_RESULT(ic) ;
8897 /* depending on the type of pointer we need to
8898 move it to the correct pointer register */
8899 type = operandType(result);
8900 etype = getSpec(type);
8902 /* if left is of type of pointer then it is simple */
8903 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8904 p_type = DCL_TYPE(type);
8907 /* we have to go by the storage class */
8908 p_type = PTR_TYPE(SPEC_OCLS(etype));
8910 /* if (SPEC_OCLS(etype)->codesp ) { */
8911 /* p_type = CPOINTER ; */
8914 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8915 /* p_type = FPOINTER ; */
8917 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8918 /* p_type = PPOINTER ; */
8920 /* if (SPEC_OCLS(etype) == idata ) */
8921 /* p_type = IPOINTER ; */
8923 /* p_type = POINTER ; */
8926 /* now that we have the pointer type we assign
8927 the pointer values */
8932 genNearPointerSet (right,result,ic);
8936 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8938 genPagedPointerSet (right,result,ic);
8942 genFarPointerSet (right,result,ic);
8947 genGenPointerSet (right,result,ic);
8951 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8952 "genPointerSet: illegal pointer type");
8956 /*-----------------------------------------------------------------*/
8957 /* genIfx - generate code for Ifx statement */
8958 /*-----------------------------------------------------------------*/
8959 static void genIfx (iCode *ic, iCode *popIc)
8961 operand *cond = IC_COND(ic);
8966 pic16_aopOp(cond,ic,FALSE);
8968 /* get the value into acc */
8969 if (AOP_TYPE(cond) != AOP_CRY)
8970 pic16_toBoolean(cond);
8973 /* the result is now in the accumulator */
8974 pic16_freeAsmop(cond,NULL,ic,TRUE);
8976 /* if there was something to be popped then do it */
8980 /* if the condition is a bit variable */
8981 if (isbit && IS_ITEMP(cond) &&
8984 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8986 if (isbit && !IS_ITEMP(cond))
8987 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8994 /*-----------------------------------------------------------------*/
8995 /* genAddrOf - generates code for address of */
8996 /*-----------------------------------------------------------------*/
8997 static void genAddrOf (iCode *ic)
8999 operand *result, *left;
9001 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
9002 pCodeOp *pcop0, *pcop1, *pcop2;
9006 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9008 sym = OP_SYMBOL( IC_LEFT(ic) );
9011 /* get address of symbol on stack */
9012 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9014 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9015 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9018 // operands on stack are accessible via "FSR2 + index" with index
9019 // starting at 2 for arguments and growing from 0 downwards for
9020 // local variables (index == 0 is not assigned so we add one here)
9022 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9029 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9030 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9031 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9032 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9033 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9034 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9035 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9041 // if(pic16_debug_verbose) {
9042 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9043 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9046 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9047 size = AOP_SIZE(IC_RESULT(ic));
9049 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9050 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9051 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9054 pic16_emitpcode(POC_MOVLW, pcop0);
9055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9056 pic16_emitpcode(POC_MOVLW, pcop1);
9057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9058 pic16_emitpcode(POC_MOVLW, pcop2);
9059 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9062 pic16_emitpcode(POC_MOVLW, pcop0);
9063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9064 pic16_emitpcode(POC_MOVLW, pcop1);
9065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9067 pic16_emitpcode(POC_MOVLW, pcop0);
9068 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9071 pic16_freeAsmop(left, NULL, ic, FALSE);
9073 pic16_freeAsmop(result,NULL,ic,TRUE);
9077 /*-----------------------------------------------------------------*/
9078 /* genAssign - generate code for assignment */
9079 /*-----------------------------------------------------------------*/
9080 static void genAssign (iCode *ic)
9082 operand *result, *right;
9083 sym_link *restype, *rtype;
9084 int size, offset,know_W;
9085 unsigned long lit = 0L;
9087 result = IC_RESULT(ic);
9088 right = IC_RIGHT(ic) ;
9092 /* if they are the same */
9093 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9096 /* reversed order operands are aopOp'ed so that result operand
9097 * is effective in case right is a stack symbol. This maneauver
9098 * allows to use the _G.resDirect flag later */
9099 pic16_aopOp(result,ic,TRUE);
9100 pic16_aopOp(right,ic,FALSE);
9102 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9104 /* if they are the same registers */
9105 if (pic16_sameRegs(AOP(right),AOP(result)))
9108 /* if the result is a bit */
9109 if (AOP_TYPE(result) == AOP_CRY) {
9110 /* if the right size is a literal then
9111 we know what the value is */
9112 if (AOP_TYPE(right) == AOP_LIT) {
9114 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9115 pic16_popGet(AOP(result),0));
9117 if (((int) operandLitValue(right)))
9118 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9119 AOP(result)->aopu.aop_dir,
9120 AOP(result)->aopu.aop_dir);
9122 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9123 AOP(result)->aopu.aop_dir,
9124 AOP(result)->aopu.aop_dir);
9129 /* the right is also a bit variable */
9130 if (AOP_TYPE(right) == AOP_CRY) {
9131 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9132 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9133 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9139 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9140 pic16_toBoolean(right);
9142 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9143 //pic16_aopPut(AOP(result),"a",0);
9147 /* bit variables done */
9149 size = AOP_SIZE(result);
9152 /* bit variables done */
9154 size = AOP_SIZE(result);
9155 restype = operandType(result);
9156 rtype = operandType(right);
9159 if(AOP_TYPE(right) == AOP_LIT) {
9160 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9162 lit = ulFromVal (AOP(right)->aopu.aop_lit);
9164 /* patch tag for literals that are cast to pointers */
9165 if (IS_CODEPTR(restype)) {
9166 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9167 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9169 if (IS_GENPTR(restype))
9171 if (IS_CODEPTR(rtype)) {
9172 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9173 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9174 } else if (PIC_IS_DATA_PTR(rtype)) {
9175 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9176 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9177 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9178 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9179 } else if (IS_PTR(rtype)) {
9180 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9181 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9187 unsigned long lit_int;
9192 if(IS_FIXED16X16(operandType(right))) {
9193 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9195 /* take care if literal is a float */
9196 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9202 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9203 // sizeof(unsigned long int), sizeof(float));
9206 if (AOP_TYPE(right) == AOP_REG) {
9207 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9209 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9214 /* when do we have to read the program memory?
9215 * - if right itself is a symbol in code space
9216 * (we don't care what it points to if it's a pointer)
9217 * - AND right is not a function (we would want its address)
9219 if(AOP_TYPE(right) != AOP_LIT
9220 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9221 && !IS_FUNC(OP_SYM_TYPE(right))
9222 && !IS_ITEMP(right)) {
9224 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9225 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9227 // set up table pointer
9228 if(pic16_isLitOp(right)) {
9229 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9230 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9231 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9232 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9233 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9234 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9235 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9237 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9238 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9239 pic16_popCopyReg(&pic16_pc_tblptrl)));
9240 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9241 pic16_popCopyReg(&pic16_pc_tblptrh)));
9242 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9243 pic16_popCopyReg(&pic16_pc_tblptru)));
9246 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9247 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9249 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9250 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9251 pic16_popGet(AOP(result),offset)));
9255 /* FIXME: for pointers we need to extend differently (according
9256 * to pointer type DATA/CODE/EEPROM/... :*/
9257 size = getSize(OP_SYM_TYPE(right));
9258 if(AOP_SIZE(result) > size) {
9259 size = AOP_SIZE(result) - size;
9261 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9269 /* VR - What is this?! */
9270 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9273 if(aopIdx(AOP(result),0) == 4) {
9274 /* this is a workaround to save value of right into wreg too,
9275 * value of wreg is going to be used later */
9276 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9277 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9282 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9286 size = AOP_SIZE(right);
9287 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9290 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
9291 if(AOP_TYPE(right) == AOP_LIT) {
9293 if(know_W != (lit&0xff))
9294 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9296 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9298 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9302 } else if (AOP_TYPE(right) == AOP_CRY) {
9303 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9305 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9306 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9307 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9309 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9310 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9311 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9315 if(!_G.resDirect) { /* use this aopForSym feature */
9316 if(AOP_TYPE(result) == AOP_ACC) {
9317 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9319 if(AOP_TYPE(right) == AOP_ACC) {
9320 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9322 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9329 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9332 pic16_freeAsmop (right,NULL,ic,FALSE);
9333 pic16_freeAsmop (result,NULL,ic,TRUE);
9336 /*-----------------------------------------------------------------*/
9337 /* genJumpTab - generates code for jump table */
9338 /*-----------------------------------------------------------------*/
9339 static void genJumpTab (iCode *ic)
9344 pCodeOp *jt_offs_hi;
9349 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9350 /* get the condition into accumulator */
9351 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9353 /* multiply by three */
9354 pic16_emitcode("add","a,acc");
9355 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9357 jtab = newiTempLabel(NULL);
9358 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9359 pic16_emitcode("jmp","@a+dptr");
9360 pic16_emitcode("","%05d_DS_:",jtab->key+100);
9363 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9364 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9366 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9367 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9368 pic16_emitpLabel(jtab->key);
9372 jt_offs = pic16_popGetTempReg(0);
9373 jt_offs_hi = pic16_popGetTempReg(1);
9374 jt_label = pic16_popGetLabel (jtab->key);
9375 //fprintf (stderr, "Creating jump table...\n");
9377 // calculate offset into jump table (idx * sizeof (GOTO))
9378 pic16_emitpcode(POC_CLRF , jt_offs_hi);
9379 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9380 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9381 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9382 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9383 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9384 pic16_emitpcode(POC_MOVWF , jt_offs);
9386 // prepare PCLATx (set to first entry in jump table)
9387 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9388 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9389 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9390 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9391 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9393 // set PCLATx to selected entry (new PCL is stored in jt_offs)
9394 pic16_emitpcode(POC_ADDWF , jt_offs);
9395 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9396 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9398 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
9400 // release temporaries and prepare jump into table (new PCL --> WREG)
9401 pic16_emitpcode(POC_MOVFW , jt_offs);
9402 pic16_popReleaseTempReg (jt_offs_hi, 1);
9403 pic16_popReleaseTempReg (jt_offs, 0);
9405 // jump into the table
9406 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9408 pic16_emitpLabelFORCE(jtab->key);
9411 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9412 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9414 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9415 /* now generate the jump labels */
9416 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9417 jtab = setNextItem(IC_JTLABELS(ic))) {
9418 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9419 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9422 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9426 /*-----------------------------------------------------------------*/
9427 /* genMixedOperation - gen code for operators between mixed types */
9428 /*-----------------------------------------------------------------*/
9430 TSD - Written for the PIC port - but this unfortunately is buggy.
9431 This routine is good in that it is able to efficiently promote
9432 types to different (larger) sizes. Unfortunately, the temporary
9433 variables that are optimized out by this routine are sometimes
9434 used in other places. So until I know how to really parse the
9435 iCode tree, I'm going to not be using this routine :(.
9437 static int genMixedOperation (iCode *ic)
9440 operand *result = IC_RESULT(ic);
9441 sym_link *ctype = operandType(IC_LEFT(ic));
9442 operand *right = IC_RIGHT(ic);
9448 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9450 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9456 nextright = IC_RIGHT(nextic);
9457 nextleft = IC_LEFT(nextic);
9458 nextresult = IC_RESULT(nextic);
9460 pic16_aopOp(right,ic,FALSE);
9461 pic16_aopOp(result,ic,FALSE);
9462 pic16_aopOp(nextright, nextic, FALSE);
9463 pic16_aopOp(nextleft, nextic, FALSE);
9464 pic16_aopOp(nextresult, nextic, FALSE);
9466 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9472 pic16_emitcode(";remove right +","");
9474 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9480 pic16_emitcode(";remove left +","");
9484 big = AOP_SIZE(nextleft);
9485 small = AOP_SIZE(nextright);
9487 switch(nextic->op) {
9490 pic16_emitcode(";optimize a +","");
9491 /* if unsigned or not an integral type */
9492 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9493 pic16_emitcode(";add a bit to something","");
9496 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9498 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9499 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9500 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9502 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9510 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9511 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9512 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9515 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9517 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9518 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9519 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9520 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9521 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9524 pic16_emitcode("rlf","known_zero,w");
9531 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9532 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9533 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9535 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9545 pic16_freeAsmop(right,NULL,ic,TRUE);
9546 pic16_freeAsmop(result,NULL,ic,TRUE);
9547 pic16_freeAsmop(nextright,NULL,ic,TRUE);
9548 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9550 nextic->generated = 1;
9557 /*-----------------------------------------------------------------*/
9558 /* genCast - gen code for casting */
9559 /*-----------------------------------------------------------------*/
9560 static void genCast (iCode *ic)
9562 operand *result = IC_RESULT(ic);
9563 sym_link *ctype = operandType(IC_LEFT(ic));
9564 sym_link *rtype = operandType(IC_RIGHT(ic));
9565 sym_link *restype = operandType(IC_RESULT(ic));
9566 operand *right = IC_RIGHT(ic);
9572 /* if they are equivalent then do nothing */
9573 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9576 pic16_aopOp(result,ic,FALSE);
9577 pic16_aopOp(right,ic,FALSE) ;
9579 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9582 /* if the result is a bit */
9583 if (AOP_TYPE(result) == AOP_CRY) {
9585 /* if the right size is a literal then
9586 * we know what the value is */
9587 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9589 if (AOP_TYPE(right) == AOP_LIT) {
9590 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9591 pic16_popGet(AOP(result),0));
9593 if (((int) operandLitValue(right)))
9594 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9595 AOP(result)->aopu.aop_dir,
9596 AOP(result)->aopu.aop_dir);
9598 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9599 AOP(result)->aopu.aop_dir,
9600 AOP(result)->aopu.aop_dir);
9604 /* the right is also a bit variable */
9605 if (AOP_TYPE(right) == AOP_CRY) {
9607 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9609 pic16_emitcode("clrc","");
9610 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9611 AOP(right)->aopu.aop_dir,
9612 AOP(right)->aopu.aop_dir);
9613 pic16_aopPut(AOP(result),"c",0);
9618 if (AOP_TYPE(right) == AOP_REG) {
9619 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9620 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9621 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9623 pic16_toBoolean(right);
9624 pic16_aopPut(AOP(result),"a",0);
9628 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9631 size = AOP_SIZE(result);
9633 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9635 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9636 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9637 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9640 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9645 if(IS_BITFIELD(getSpec(restype))
9646 && IS_BITFIELD(getSpec(rtype))) {
9647 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9650 /* port from pic14 to cope with generic pointers */
9651 if (PIC_IS_TAGGED(restype))
9653 operand *result = IC_RESULT(ic);
9654 //operand *left = IC_LEFT(ic);
9655 operand *right = IC_RIGHT(ic);
9658 /* copy common part */
9659 int max, size = AOP_SIZE(result);
9660 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9661 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9666 pic16_mov2w (AOP(right), size);
9667 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9670 /* upcast into generic pointer type? */
9671 if (IS_GENPTR(restype)
9672 && !PIC_IS_TAGGED(rtype)
9673 && (AOP_SIZE(result) > max))
9675 /* determine appropriate tag for right */
9676 if (PIC_IS_DATA_PTR(rtype))
9677 tag = GPTR_TAG_DATA;
9678 else if (IS_CODEPTR(rtype))
9679 tag = GPTR_TAG_CODE;
9680 else if (PIC_IS_DATA_PTR(ctype)) {
9681 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9682 tag = GPTR_TAG_DATA;
9683 } else if (IS_CODEPTR(ctype)) {
9684 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9685 tag = GPTR_TAG_CODE;
9686 } else if (IS_PTR(rtype)) {
9687 PERFORM_ONCE(weirdcast,
9688 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9690 tag = GPTR_TAG_DATA;
9692 PERFORM_ONCE(weirdcast,
9693 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9695 tag = GPTR_TAG_DATA;
9698 assert (AOP_SIZE(result) == 3);
9699 /* zero-extend address... */
9700 for (size = max; size < AOP_SIZE(result)-1; size++)
9701 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9702 /* ...and add tag */
9703 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9704 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9705 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9706 for (size = max; size < AOP_SIZE(result)-1; size++)
9707 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9708 /* add __code tag */
9709 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9710 } else if (AOP_SIZE(result) > max) {
9711 /* extend non-pointers */
9712 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9713 pic16_addSign(result, max, 0);
9718 /* if they are the same size : or less */
9719 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9721 /* if they are in the same place */
9722 if (pic16_sameRegs(AOP(right),AOP(result)))
9725 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9727 if (IS_PTR_CONST(rtype))
9729 if (IS_CODEPTR(rtype))
9731 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9734 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9736 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9738 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9740 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9741 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9744 if(AOP_SIZE(result) < 2) {
9745 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9747 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9748 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9751 /* if they in different places then copy */
9752 size = AOP_SIZE(result);
9755 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9756 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9763 /* if the result is of type pointer */
9764 if (IS_PTR(ctype)) {
9766 sym_link *type = operandType(right);
9767 sym_link *etype = getSpec(type);
9769 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
9771 /* pointer to generic pointer */
9772 if (IS_GENPTR(ctype)) {
9776 p_type = DCL_TYPE(type);
9778 /* we have to go by the storage class */
9779 p_type = PTR_TYPE(SPEC_OCLS(etype));
9781 /* if (SPEC_OCLS(etype)->codesp ) */
9782 /* p_type = CPOINTER ; */
9784 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9785 /* p_type = FPOINTER ; */
9787 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9788 /* p_type = PPOINTER; */
9790 /* if (SPEC_OCLS(etype) == idata ) */
9791 /* p_type = IPOINTER ; */
9793 /* p_type = POINTER ; */
9796 /* the first two bytes are known */
9797 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
9798 size = GPTRSIZE - 1;
9801 if(offset < AOP_SIZE(right)) {
9802 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9803 pic16_mov2f(AOP(result), AOP(right), offset);
9805 if ((AOP_TYPE(right) == AOP_PCODE) &&
9806 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9807 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9808 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9811 pic16_aopPut(AOP(result),
9812 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9817 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9820 /* the last byte depending on type */
9825 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9829 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9833 pic16_emitcode(";BUG!? ","%d",__LINE__);
9838 if (GPTRSIZE > AOP_SIZE(right)) {
9839 // assume __data pointer... THIS MIGHT BE WRONG!
9840 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9842 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9847 /* this should never happen */
9848 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9849 "got unknown pointer type");
9852 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9858 /* just copy the pointers */
9859 size = AOP_SIZE(result);
9862 pic16_aopPut(AOP(result),
9863 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9872 /* so we now know that the size of destination is greater
9873 than the size of the source.
9874 Now, if the next iCode is an operator then we might be
9875 able to optimize the operation without performing a cast.
9877 if(genMixedOperation(ic))
9880 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9882 /* we move to result for the size of source */
9883 size = AOP_SIZE(right);
9888 pic16_mov2f(AOP(result), AOP(right), offset);
9892 /* now depending on the sign of the destination */
9893 size = AOP_SIZE(result) - AOP_SIZE(right);
9894 /* if unsigned or not an integral type */
9895 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9897 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9899 /* we need to extend the sign :( */
9902 /* Save one instruction of casting char to int */
9903 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9904 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9905 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
9907 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9910 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9912 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9914 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
9922 pic16_freeAsmop(right,NULL,ic,TRUE);
9923 pic16_freeAsmop(result,NULL,ic,TRUE);
9927 /*-----------------------------------------------------------------*/
9928 /* genDjnz - generate decrement & jump if not zero instrucion */
9929 /*-----------------------------------------------------------------*/
9930 static int genDjnz (iCode *ic, iCode *ifx)
9933 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9938 /* if the if condition has a false label
9939 then we cannot save */
9943 /* if the minus is not of the form
9945 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9946 !IS_OP_LITERAL(IC_RIGHT(ic)))
9949 if (operandLitValue(IC_RIGHT(ic)) != 1)
9952 /* if the size of this greater than one then no
9954 if (getSize(operandType(IC_RESULT(ic))) > 1)
9957 /* otherwise we can save BIG */
9958 lbl = newiTempLabel(NULL);
9959 lbl1= newiTempLabel(NULL);
9961 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9963 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9964 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9966 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genReceive - generate code for a receive iCode */
9973 /*-----------------------------------------------------------------*/
9974 static void genReceive (iCode *ic)
9980 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
9981 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
9983 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
9985 if (isOperandInFarSpace(IC_RESULT(ic))
9986 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
9987 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9989 int size = getSize(operandType(IC_RESULT(ic)));
9990 int offset = pic16_fReturnSizePic - size;
9994 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9995 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9999 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10001 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10002 size = AOP_SIZE(IC_RESULT(ic));
10005 pic16_emitcode ("pop","acc");
10006 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10009 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10011 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10014 /* set pseudo stack pointer to where it should be - dw*/
10015 GpsuedoStkPtr = ic->parmBytes;
10017 /* setting GpsuedoStkPtr has side effects here: */
10018 /* FIXME: What's the correct size of the return(ed) value?
10019 * For now, assuming '4' as before... */
10020 assignResultValue(IC_RESULT(ic), 4, 0);
10023 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10026 /*-----------------------------------------------------------------*/
10027 /* genDummyRead - generate code for dummy read of volatiles */
10028 /*-----------------------------------------------------------------*/
10030 genDummyRead (iCode * ic)
10035 if (op && IS_SYMOP(op)) {
10036 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10037 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10040 pic16_aopOp (op, ic, FALSE);
10041 pic16_mov2w_volatile(AOP(op));
10042 pic16_freeAsmop (op, NULL, ic, TRUE);
10044 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10048 /*-----------------------------------------------------------------*/
10049 /* genpic16Code - generate code for pic16 based controllers */
10050 /*-----------------------------------------------------------------*/
10052 * At this point, ralloc.c has gone through the iCode and attempted
10053 * to optimize in a way suitable for a PIC. Now we've got to generate
10054 * PIC instructions that correspond to the iCode.
10056 * Once the instructions are generated, we'll pass through both the
10057 * peep hole optimizer and the pCode optimizer.
10058 *-----------------------------------------------------------------*/
10060 void genpic16Code (iCode *lic)
10065 lineHead = lineCurr = NULL;
10067 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10068 pic16_addpBlock(pb);
10071 /* if debug information required */
10072 if (options.debug && currFunc) {
10074 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10079 for (ic = lic ; ic ; ic = ic->next ) {
10081 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10082 if ( cln != ic->lineno ) {
10083 if ( options.debug ) {
10084 debugFile->writeCLine (ic);
10087 if(!options.noCcodeInAsm) {
10088 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10089 printCLine(ic->filename, ic->lineno)));
10095 if(options.iCodeInAsm) {
10098 /* insert here code to print iCode as comment */
10099 iLine = printILine(ic);
10100 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10104 /* if the result is marked as
10105 * spilt and rematerializable or code for
10106 * this has already been generated then
10108 if (resultRemat(ic) || ic->generated )
10111 /* depending on the operation */
10130 /* IPOP happens only when trying to restore a
10131 * spilt live range, if there is an ifx statement
10132 * following this pop then the if statement might
10133 * be using some of the registers being popped which
10134 * would destroy the contents of the register so
10135 * we need to check for this condition and handle it */
10137 && ic->next->op == IFX
10138 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10139 genIfx (ic->next,ic);
10157 genEndFunction (ic);
10173 pic16_genPlus (ic) ;
10177 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10178 pic16_genMinus (ic);
10194 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10198 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10204 /* note these two are xlated by algebraic equivalence
10205 * during parsing SDCC.y */
10206 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10207 "got '>=' or '<=' shouldn't have come here");
10211 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10223 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10227 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10231 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10255 genRightShift (ic);
10258 case GET_VALUE_AT_ADDRESS:
10263 if (POINTER_SET(ic))
10290 addSet(&_G.sendSet,ic);
10293 case DUMMY_READ_VOLATILE:
10303 /* now we are ready to call the
10304 peep hole optimizer */
10305 if (!options.nopeep)
10306 peepHole (&lineHead);
10308 /* now do the actual printing */
10309 printLine (lineHead, codeOutBuf);
10312 DFPRINTF((stderr,"printing pBlock\n\n"));
10313 pic16_printpBlock(stdout,pb);