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)
2299 int lsize, rsize, i;
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 lsize = AOP_SIZE(IC_LEFT(ic));
2335 rsize = AOP_SIZE(IC_RESULT(ic));
2336 label = newiTempLabel ( NULL );
2338 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2339 /* If the result is longer than the operand,
2340 store sign extension (0x00 or 0xff) in W */
2341 if (rsize > lsize) {
2342 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00));
2343 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_LEFT(ic)), lsize-1), 7));
2344 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF));
2346 for (i = rsize - 1; i > 0; --i) {
2347 if (i > lsize - 1) {
2348 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2350 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2353 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_RESULT(ic)), 0));
2354 for (i = 1; i < rsize; ++i) {
2355 if (i == rsize - 1) {
2358 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2360 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2363 for (i = min(rsize, lsize) - 1; i >= 0; i--) {
2364 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2365 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2367 /* Sign extend if the result is longer than the operand */
2368 if (rsize > lsize) {
2369 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00));
2370 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_RESULT(ic)), lsize - 1), 7));
2371 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF));
2372 for (i = rsize - 1; i > lsize - 1; --i) {
2373 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2377 for (i = 0; i < rsize - 2; i++) {
2378 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2379 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key));
2382 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), rsize - 2));
2384 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), rsize - 1));
2387 pic16_emitpLabel (label->key);
2390 /* release the aops */
2391 pic16_freeAsmop(IC_LEFT(ic), NULL, ic, (RESULTONSTACK(ic) ? 0 : 1));
2392 pic16_freeAsmop(IC_RESULT(ic), NULL, ic, TRUE);
2395 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2397 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2398 pic16_emitpcode(POC_MOVFW, src);
2399 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2401 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2402 src, pic16_popGet(AOP(op), offset)));
2407 /*-----------------------------------------------------------------*/
2408 /* assignResultValue - assign results to oper, rescall==1 is */
2409 /* called from genCall() or genPcall() */
2410 /*-----------------------------------------------------------------*/
2411 static void assignResultValue(operand * oper, int res_size, int rescall)
2413 int size = AOP_SIZE(oper);
2417 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2418 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2421 /* assign result from a call/pcall function() */
2423 /* function results are stored in a special order,
2424 * see top of file with Function return policy, or manual */
2427 /* 8-bits, result in WREG */
2428 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2430 if(size > 1 && res_size > 1) {
2431 /* 16-bits, result in PRODL:WREG */
2432 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2435 if(size > 2 && res_size > 2) {
2436 /* 24-bits, result in PRODH:PRODL:WREG */
2437 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2440 if(size > 3 && res_size > 3) {
2441 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2442 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2445 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2448 /* >32-bits, result on stack, and FSR0 points to beginning.
2449 * Fix stack when done */
2451 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2453 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2454 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2456 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2461 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2462 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2463 if(STACK_MODEL_LARGE) {
2465 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2469 int areg = 0; /* matching argument register */
2471 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2472 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2475 /* its called from genReceive (probably) -- VR */
2476 /* I hope this code will not be called from somewhere else in the future!
2477 * We manually set the pseudo stack pointer in genReceive. - dw
2479 if(!GpsuedoStkPtr && _G.useWreg) {
2480 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2482 /* The last byte in the assignment is in W */
2483 if(areg <= GpsuedoStkPtr) {
2485 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2487 // debugf("receive from WREG\n", 0);
2489 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2492 _G.stack_lat = AOP_SIZE(oper)-1;
2497 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2498 // debugf("receive from STACK\n", 0);
2505 /*-----------------------------------------------------------------*/
2506 /* genIpush - generate code for pushing this gets a little complex */
2507 /*-----------------------------------------------------------------*/
2508 static void genIpush (iCode *ic)
2510 // int size, offset=0;
2513 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2516 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2518 /* send to stack as normal */
2519 addSet(&_G.sendSet,ic);
2520 // addSetHead(&_G.sendSet,ic);
2521 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2526 int size, offset = 0 ;
2530 /* if this is not a parm push : ie. it is spill push
2531 and spill push is always done on the local stack */
2532 if (!ic->parmPush) {
2534 /* and the item is spilt then do nothing */
2535 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2538 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2539 size = AOP_SIZE(IC_LEFT(ic));
2540 /* push it on the stack */
2542 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2547 pic16_emitcode("push","%s",l);
2552 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2556 /*-----------------------------------------------------------------*/
2557 /* genIpop - recover the registers: can happen only for spilling */
2558 /*-----------------------------------------------------------------*/
2559 static void genIpop (iCode *ic)
2562 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2567 /* if the temp was not pushed then */
2568 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2571 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2572 size = AOP_SIZE(IC_LEFT(ic));
2575 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2578 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2582 static int wparamCmp(void *p1, void *p2)
2584 return (!strcmp((char *)p1, (char *)p2));
2587 int inWparamList(char *s)
2589 return isinSetWith(wparamList, s, wparamCmp);
2593 /*-----------------------------------------------------------------*/
2594 /* genCall - generates a call statement */
2595 /*-----------------------------------------------------------------*/
2596 static void genCall (iCode *ic)
2606 ftype = OP_SYM_TYPE(IC_LEFT(ic));
2607 /* if caller saves & we have not saved then */
2608 // if (!ic->regsSaved)
2609 // saveRegisters(ic);
2611 /* initialise stackParms for IPUSH pushes */
2612 // stackParms = psuedoStkPtr;
2613 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2614 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2615 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2618 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2621 /* if send set is not empty the assign */
2624 int psuedoStkPtr=-1;
2625 int firstTimeThruLoop = 1;
2628 /* reverse sendSet if function is not reentrant */
2629 if(!IFFUNC_ISREENT(ftype))
2630 _G.sendSet = reverseSet(_G.sendSet);
2632 /* First figure how many parameters are getting passed */
2636 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2640 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2641 size = AOP_SIZE(IC_LEFT(sic));
2645 /* pass the last byte through WREG */
2649 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2650 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2651 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2653 if(!firstTimeThruLoop) {
2654 /* If this is not the first time we've been through the loop
2655 * then we need to save the parameter in a temporary
2656 * register. The last byte of the last parameter is
2660 // --psuedoStkPtr; // sanity check
2664 firstTimeThruLoop=0;
2666 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2671 /* all arguments are passed via stack */
2675 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2676 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2677 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2679 // pushaop(AOP(IC_LEFT(sic)), size);
2680 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2687 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2691 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2692 pushw(); /* save last parameter to stack if functions has varargs */
2696 } else use_wreg = 0;
2698 _G.stackRegSet = _G.sendSet;
2703 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2707 /* if we need to assign a result value */
2708 if ((IS_ITEMP(IC_RESULT(ic))
2709 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2710 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2711 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2714 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2717 /* Must not assign an 8-bit result to a 16-bit variable;
2718 * this would use (used...) the uninitialized PRODL! */
2719 /* FIXME: Need a proper way to obtain size of function result type,
2720 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2721 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2723 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2724 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2726 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2729 if(!stackParms && ic->parmBytes) {
2730 stackParms = ic->parmBytes;
2733 stackParms -= use_wreg;
2736 if(stackParms == 1) {
2737 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
2739 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2740 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2742 if(STACK_MODEL_LARGE) {
2744 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2749 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2752 /* adjust the stack for parameters if required */
2753 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2756 /* if register bank was saved then pop them */
2758 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2760 /* if we hade saved some registers then unsave them */
2761 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2762 unsaveRegisters (ic);
2768 /*-----------------------------------------------------------------*/
2769 /* genPcall - generates a call by pointer statement */
2770 /* new version, created from genCall - HJD */
2771 /*-----------------------------------------------------------------*/
2772 static void genPcall (iCode *ic)
2776 symbol *retlbl = newiTempLabel(NULL);
2777 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2781 fntype = operandType( IC_LEFT(ic) )->next;
2783 /* if send set is not empty the assign */
2786 int psuedoStkPtr=-1;
2788 /* reverse sendSet if function is not reentrant */
2789 if(!IFFUNC_ISREENT(fntype))
2790 _G.sendSet = reverseSet(_G.sendSet);
2794 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2797 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2798 size = AOP_SIZE(IC_LEFT(sic));
2801 /* all parameters are passed via stack, since WREG is clobbered
2802 * by the calling sequence */
2804 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2805 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2806 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2808 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2812 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2815 _G.stackRegSet = _G.sendSet;
2819 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2821 // push return address
2822 // push $ on return stack, then replace with retlbl
2824 /* Thanks to Thorsten Klose for pointing out that the following
2825 * snippet should be interrupt safe */
2826 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2827 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2829 pic16_emitpcodeNULLop(POC_PUSH);
2831 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2832 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2833 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2834 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2835 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2836 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2839 /* restore interrupt control register */
2840 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2841 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2843 /* make the call by writing the pointer into pc */
2844 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2845 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2847 // note: MOVFF to PCL not allowed
2848 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2849 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2852 /* return address is here: (X) */
2853 pic16_emitpLabelFORCE(retlbl->key);
2855 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2858 /* if we need assign a result value */
2859 if ((IS_ITEMP(IC_RESULT(ic))
2860 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2861 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2862 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2865 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2868 /* FIXME: Need proper way to obtain the function result's type.
2869 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2870 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2872 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2873 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2875 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2878 // stackParms -= use_wreg;
2881 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2882 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2883 if(STACK_MODEL_LARGE) {
2885 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2890 /*-----------------------------------------------------------------*/
2891 /* resultRemat - result is rematerializable */
2892 /*-----------------------------------------------------------------*/
2893 static int resultRemat (iCode *ic)
2895 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2896 if (SKIP_IC(ic) || ic->op == IFX)
2899 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2900 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2901 if (sym->remat && !POINTER_SET(ic))
2909 /*-----------------------------------------------------------------*/
2910 /* inExcludeList - return 1 if the string is in exclude Reg list */
2911 /*-----------------------------------------------------------------*/
2912 static bool inExcludeList(char *s)
2914 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2917 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2918 if (options.excludeRegs[i] &&
2919 STRCASECMP(options.excludeRegs[i],"none") == 0)
2922 for ( i = 0 ; options.excludeRegs[i]; i++) {
2923 if (options.excludeRegs[i] &&
2924 STRCASECMP(s,options.excludeRegs[i]) == 0)
2931 /*-----------------------------------------------------------------*/
2932 /* genFunction - generated code for function entry */
2933 /*-----------------------------------------------------------------*/
2934 static void genFunction (iCode *ic)
2940 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2942 pic16_labelOffset += (max_key+4);
2947 ftype = operandType(IC_LEFT(ic));
2948 sym = OP_SYMBOL(IC_LEFT(ic));
2950 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2951 /* create an absolute section at the interrupt vector:
2952 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2957 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2959 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2960 sprintf(asymname, "ivec_%s", sym->name);
2962 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2964 /* when an interrupt is declared as naked, do not emit the special
2965 * wrapper segment at vector address. The user should take care for
2966 * this instead. -- VR */
2968 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2969 asym = newSymbol(asymname, 0);
2970 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2971 pic16_addpBlock( apb );
2973 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2974 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2975 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2976 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2977 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2979 /* mark the end of this tiny function */
2980 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2982 sprintf(asymname, "%s", sym->rname);
2988 abSym = Safe_calloc(1, sizeof(absSym));
2989 strcpy(abSym->name, asymname);
2991 switch( FUNC_INTNO(sym->type) ) {
2992 case 0: abSym->address = 0x000000; break;
2993 case 1: abSym->address = 0x000008; break;
2994 case 2: abSym->address = 0x000018; break;
2997 // fprintf(stderr, "no interrupt number is given\n");
2998 abSym->address = -1; break;
3001 /* relocate interrupt vectors if needed */
3002 if(abSym->address != -1)
3003 abSym->address += pic16_options.ivt_loc;
3005 addSet(&absSymSet, abSym);
3009 /* create the function header */
3010 pic16_emitcode(";","-----------------------------------------");
3011 pic16_emitcode(";"," function %s",sym->name);
3012 pic16_emitcode(";","-----------------------------------------");
3014 /* prevent this symbol from being emitted as 'extern' */
3015 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3017 pic16_emitcode("","%s:",sym->rname);
3018 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3023 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3024 if(!strcmp(ab->name, sym->rname)) {
3025 pic16_pBlockConvert2Absolute(pb);
3031 if(IFFUNC_ISNAKED(ftype)) {
3032 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3036 /* if critical function then turn interrupts off */
3037 if (IFFUNC_ISCRITICAL(ftype)) {
3038 //pic16_emitcode("clr","ea");
3041 currFunc = sym; /* update the currFunc symbol */
3042 _G.fregsUsed = sym->regsUsed;
3043 _G.sregsAlloc = newBitVect(128);
3046 /* if this is an interrupt service routine then
3047 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3048 if (IFFUNC_ISISR(sym->type)) {
3049 _G.usefastretfie = 1; /* use shadow registers by default */
3051 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3052 if(!FUNC_ISSHADOWREGS(sym->type)) {
3053 /* do not save WREG,STATUS,BSR for high priority interrupts
3054 * because they are stored in the hardware shadow registers already */
3055 _G.usefastretfie = 0;
3056 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3057 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3058 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3061 /* these should really be optimized somehow, because not all
3062 * interrupt handlers modify them */
3063 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3064 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3065 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3066 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3067 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3068 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3070 // pic16_pBlockConvert2ISR(pb);
3073 /* emit code to setup stack frame if user enabled,
3074 * and function is not main() */
3076 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3077 if(strcmp(sym->name, "main")) {
3079 || !options.ommitFramePtr
3081 || IFFUNC_ARGS(sym->type)
3082 || FUNC_HASSTACKPARM(sym->etype)
3084 /* setup the stack frame */
3085 if(STACK_MODEL_LARGE)
3086 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3087 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3089 if(STACK_MODEL_LARGE)
3090 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3091 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3095 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3098 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3100 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3101 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3103 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3106 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3107 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3114 /* if callee-save to be used for this function
3115 * then save the registers being used in this function */
3116 // if (IFFUNC_CALLEESAVES(sym->type))
3117 if(strcmp(sym->name, "main")) {
3120 /* if any registers used */
3121 if (sym->regsUsed) {
3122 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3124 if(!pic16_options.xinst) {
3125 /* save the registers used */
3126 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3127 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3128 if (bitVectBitValue(sym->regsUsed,i)) {
3130 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3132 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3135 if(!pic16_regWithIdx(i)->wasUsed) {
3136 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3137 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3138 pic16_regWithIdx(i)->wasUsed = 1;
3145 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3146 for(i=0;i<sym->regsUsed->size;i++) {
3147 if(bitVectBitValue(sym->regsUsed, i)) {
3152 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3155 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3160 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3161 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3164 /*-----------------------------------------------------------------*/
3165 /* genEndFunction - generates epilogue for functions */
3166 /*-----------------------------------------------------------------*/
3167 static void genEndFunction (iCode *ic)
3169 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3173 if(IFFUNC_ISNAKED(sym->type)) {
3174 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3180 /* add code for ISCRITICAL */
3181 if(IFFUNC_ISCRITICAL(sym->type)) {
3182 /* if critical function, turn on interrupts */
3184 /* TODO: add code here -- VR */
3187 // sym->regsUsed = _G.fregsUsed;
3189 /* now we need to restore the registers */
3190 /* if any registers used */
3192 /* first restore registers that might be used for stack access */
3193 if(_G.sregsAllocSet) {
3196 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3197 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3198 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3202 if (strcmp(sym->name, "main") && sym->regsUsed) {
3205 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3206 /* restore registers used */
3207 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3208 for ( i = sym->regsUsed->size; i >= 0; i--) {
3209 if (bitVectBitValue(sym->regsUsed,i)) {
3210 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3214 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3219 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3221 if (sym->stack == 1) {
3222 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3223 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3225 // we have to add more than one...
3226 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3227 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3228 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3230 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3231 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3232 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3236 if(strcmp(sym->name, "main")) {
3238 || !options.ommitFramePtr
3240 || IFFUNC_ARGS(sym->type)
3241 || FUNC_HASSTACKPARM(sym->etype)
3243 /* restore stack frame */
3244 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3245 if(STACK_MODEL_LARGE)
3246 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3252 if (IFFUNC_ISISR(sym->type)) {
3253 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3254 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3255 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3256 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3257 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3258 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3260 if(!FUNC_ISSHADOWREGS(sym->type)) {
3261 /* do not restore interrupt vector for WREG,STATUS,BSR
3262 * for high priority interrupt, see genFunction */
3263 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3264 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3265 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3267 // _G.interruptvector = 0; /* sanity check */
3270 /* if debug then send end of function */
3271 /* if (options.debug && currFunc) */
3273 debugFile->writeEndFunction (currFunc, ic, 1);
3276 if(_G.usefastretfie)
3277 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3279 pic16_emitpcodeNULLop(POC_RETFIE);
3281 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3283 _G.usefastretfie = 0;
3287 if (IFFUNC_ISCRITICAL(sym->type)) {
3288 pic16_emitcode("setb","ea");
3291 /* if debug then send end of function */
3293 debugFile->writeEndFunction (currFunc, ic, 1);
3296 /* insert code to restore stack frame, if user enabled it
3297 * and function is not main() */
3300 pic16_emitpcodeNULLop(POC_RETURN);
3302 /* Mark the end of a function */
3303 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3307 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3309 unsigned long lit=1;
3314 // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3315 if(AOP_TYPE(op) == AOP_LIT) {
3316 if(!IS_FLOAT(operandType( op ))) {
3317 lit = ulFromVal (AOP(op)->aopu.aop_lit);
3320 unsigned long lit_int;
3324 /* take care if literal is a float */
3325 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3330 if (AOP_TYPE(op) == AOP_LIT) {
3331 /* FIXME: broken for
3332 * char __at(0x456) foo;
3334 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3335 pic16_movLit2f(dest, (lit >> (8ul*offset)));
3336 } else if (AOP_TYPE(op) == AOP_PCODE
3337 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3338 /* char *s= "aaa"; return s; */
3339 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3340 * that the generic pointer is interpreted correctly
3341 * as referring to __code space, but this is fragile! */
3342 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3343 /* XXX: should check that dest != WREG */
3344 pic16_emitpcode(POC_MOVWF, dest);
3346 if(dest->type == PO_WREG && (offset == 0)) {
3347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3350 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3354 /*-----------------------------------------------------------------*/
3355 /* genRet - generate code for return statement */
3356 /*-----------------------------------------------------------------*/
3357 static void genRet (iCode *ic)
3363 /* if we have no return value then
3364 * just generate the "ret" */
3369 /* we have something to return then
3370 * move the return value into place */
3371 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3372 size = AOP_SIZE(IC_LEFT(ic));
3376 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3379 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3382 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3384 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3387 /* >32-bits, setup stack and FSR0 */
3389 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3390 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3392 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3394 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3399 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3400 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3402 if(STACK_MODEL_LARGE) {
3403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3404 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3406 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3410 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3413 /* generate a jump to the return label
3414 * if the next is not the return statement */
3415 if (!(ic->next && ic->next->op == LABEL
3416 && IC_LABEL(ic->next) == returnLabel)) {
3418 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3419 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3423 /*-----------------------------------------------------------------*/
3424 /* genLabel - generates a label */
3425 /*-----------------------------------------------------------------*/
3426 static void genLabel (iCode *ic)
3430 /* special case never generate */
3431 if (IC_LABEL(ic) == entryLabel)
3434 pic16_emitpLabel(IC_LABEL(ic)->key);
3435 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3438 /*-----------------------------------------------------------------*/
3439 /* genGoto - generates a goto */
3440 /*-----------------------------------------------------------------*/
3442 static void genGoto (iCode *ic)
3445 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3446 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3450 /*-----------------------------------------------------------------*/
3451 /* genMultbits :- multiplication of bits */
3452 /*-----------------------------------------------------------------*/
3453 static void genMultbits (operand *left,
3459 if(!pic16_sameRegs(AOP(result),AOP(right)))
3460 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3462 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3463 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3464 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3469 /*-----------------------------------------------------------------*/
3470 /* genMultOneByte : 8 bit multiplication & division */
3471 /*-----------------------------------------------------------------*/
3472 static void genMultOneByte (operand *left,
3478 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3479 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3481 /* (if two literals, the value is computed before) */
3482 /* if one literal, literal on the right */
3483 if (AOP_TYPE(left) == AOP_LIT){
3489 /* size is already checked in genMult == 1 */
3490 // size = AOP_SIZE(result);
3492 if (AOP_TYPE(right) == AOP_LIT){
3493 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3494 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3495 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3496 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3498 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3499 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3500 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3501 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3504 pic16_genMult8X8_n (left, right,result);
3508 /*-----------------------------------------------------------------*/
3509 /* genMultOneWord : 16 bit multiplication */
3510 /*-----------------------------------------------------------------*/
3511 static void genMultOneWord (operand *left,
3516 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3517 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3519 /* (if two literals, the value is computed before)
3520 * if one literal, literal on the right */
3521 if (AOP_TYPE(left) == AOP_LIT){
3527 /* size is checked already == 2 */
3528 // size = AOP_SIZE(result);
3530 if (AOP_TYPE(right) == AOP_LIT) {
3531 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3532 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3533 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3534 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3536 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3537 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3538 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3539 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3542 pic16_genMult16X16_16(left, right,result);
3547 /*-----------------------------------------------------------------*/
3548 /* genMultOneLong : 32 bit multiplication */
3549 /*-----------------------------------------------------------------*/
3550 static void genMultOneLong (operand *left,
3555 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3556 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3558 /* (if two literals, the value is computed before)
3559 * if one literal, literal on the right */
3560 if (AOP_TYPE(left) == AOP_LIT){
3566 /* size is checked already == 4 */
3567 // size = AOP_SIZE(result);
3569 if (AOP_TYPE(right) == AOP_LIT) {
3570 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3571 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3572 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3573 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3575 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3576 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3577 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3578 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3581 pic16_genMult32X32_32(left, right,result);
3587 /*-----------------------------------------------------------------*/
3588 /* genMult - generates code for multiplication */
3589 /*-----------------------------------------------------------------*/
3590 static void genMult (iCode *ic)
3592 operand *left = IC_LEFT(ic);
3593 operand *right = IC_RIGHT(ic);
3594 operand *result= IC_RESULT(ic);
3597 /* assign the amsops */
3598 pic16_aopOp (left,ic,FALSE);
3599 pic16_aopOp (right,ic,FALSE);
3600 pic16_aopOp (result,ic,TRUE);
3602 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3604 /* special cases first *
3606 if (AOP_TYPE(left) == AOP_CRY
3607 && AOP_TYPE(right)== AOP_CRY) {
3608 genMultbits(left,right,result);
3612 /* if both are of size == 1 */
3613 if(AOP_SIZE(left) == 1
3614 && AOP_SIZE(right) == 1) {
3615 genMultOneByte(left,right,result);
3620 /* if both are of size == 2 */
3621 if(AOP_SIZE(left) == 2
3622 && AOP_SIZE(right) == 2) {
3623 genMultOneWord(left, right, result);
3627 /* if both are of size == 4 */
3628 if(AOP_SIZE(left) == 4
3629 && AOP_SIZE(right) == 4) {
3630 genMultOneLong(left, right, result);
3635 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3636 assert( !"Multiplication should have been transformed into function call!" );
3638 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3641 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3642 /* should have been converted to function call */
3646 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3647 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3648 pic16_freeAsmop(result,NULL,ic,TRUE);
3652 /*-----------------------------------------------------------------*/
3653 /* genDivbits :- division of bits */
3654 /*-----------------------------------------------------------------*/
3655 static void genDivbits (operand *left,
3662 /* the result must be bit */
3663 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3664 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3668 pic16_emitcode("div","ab");
3669 pic16_emitcode("rrc","a");
3670 pic16_aopPut(AOP(result),"c",0);
3673 /*-----------------------------------------------------------------*/
3674 /* genDivOneByte : 8 bit division */
3675 /*-----------------------------------------------------------------*/
3676 static void genDivOneByte (operand *left,
3680 sym_link *opetype = operandType(result);
3685 /* result = divident / divisor
3686 * - divident may be a register or a literal,
3687 * - divisor may be a register or a literal,
3688 * so there are 3 cases (literal / literal is optimized
3689 * by the front-end) to handle.
3690 * In addition we must handle signed and unsigned, which
3691 * result in 6 final different cases -- VR */
3695 size = AOP_SIZE(result) - 1;
3697 /* signed or unsigned */
3698 if (SPEC_USIGN(opetype)) {
3699 pCodeOp *pct1, /* count */
3702 symbol *label1, *label2, *label3;;
3705 /* unsigned is easy */
3707 pct1 = pic16_popGetTempReg(1);
3708 pct2 = pic16_popGetTempReg(1);
3709 pct3 = pic16_popGetTempReg(1);
3711 label1 = newiTempLabel(NULL);
3712 label2 = newiTempLabel(NULL);
3713 label3 = newiTempLabel(NULL);
3715 /* the following algorithm is extracted from divuint.c */
3717 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3718 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3720 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3722 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3724 pic16_emitpLabel(label1->key);
3727 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3731 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3735 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3737 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3738 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3740 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3741 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3742 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3744 pic16_emitpLabel( label3->key );
3745 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3746 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3750 pic16_emitpLabel(label2->key);
3751 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3752 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3753 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3755 /* result is in wreg */
3756 if(AOP_TYPE(result) != AOP_ACC)
3757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3759 pic16_popReleaseTempReg( pct3, 1);
3760 pic16_popReleaseTempReg( pct2, 1);
3761 pic16_popReleaseTempReg( pct1, 1);
3766 /* signed is a little bit more difficult */
3768 /* save the signs of the operands */
3769 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3771 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3772 pic16_emitcode("push","acc"); /* save it on the stack */
3774 /* now sign adjust for both left & right */
3775 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3777 lbl = newiTempLabel(NULL);
3778 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3779 pic16_emitcode("cpl","a");
3780 pic16_emitcode("inc","a");
3781 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3782 pic16_emitcode("mov","b,a");
3784 /* sign adjust left side */
3785 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3788 lbl = newiTempLabel(NULL);
3789 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3790 pic16_emitcode("cpl","a");
3791 pic16_emitcode("inc","a");
3792 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3794 /* now the division */
3795 pic16_emitcode("div","ab");
3796 /* we are interested in the lower order
3798 pic16_emitcode("mov","b,a");
3799 lbl = newiTempLabel(NULL);
3800 pic16_emitcode("pop","acc");
3801 /* if there was an over flow we don't
3802 adjust the sign of the result */
3803 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3804 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3806 pic16_emitcode("clr","a");
3807 pic16_emitcode("subb","a,b");
3808 pic16_emitcode("mov","b,a");
3809 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3811 /* now we are done */
3812 pic16_aopPut(AOP(result),"b",0);
3814 pic16_emitcode("mov","c,b.7");
3815 pic16_emitcode("subb","a,acc");
3818 pic16_aopPut(AOP(result),"a",offset++);
3823 /*-----------------------------------------------------------------*/
3824 /* genDiv - generates code for division */
3825 /*-----------------------------------------------------------------*/
3826 static void genDiv (iCode *ic)
3828 operand *left = IC_LEFT(ic);
3829 operand *right = IC_RIGHT(ic);
3830 operand *result= IC_RESULT(ic);
3832 int leftVal = 0, rightVal = 0;
3834 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3837 /* Division is a very lengthy algorithm, so it is better
3838 * to call support routines than inlining algorithm.
3839 * Division functions written here just in case someone
3840 * wants to inline and not use the support libraries -- VR */
3844 /* assign the amsops */
3845 pic16_aopOp (left,ic,FALSE);
3846 pic16_aopOp (right,ic,FALSE);
3847 pic16_aopOp (result,ic,TRUE);
3851 else if (ic->op == '%')
3854 assert( !"invalid operation requested in genDivMod" );
3856 /* get literal values */
3857 if (IS_VALOP(left)) {
3858 leftVal = (int) ulFromVal ( OP_VALUE(left) );
3859 assert( leftVal >= -128 && leftVal < 256 );
3860 if (leftVal < 0) { signedLits++; }
3862 if (IS_VALOP(right)) {
3863 rightVal = (int) ulFromVal ( OP_VALUE(right) );
3864 assert( rightVal >= -128 && rightVal < 256 );
3865 if (rightVal < 0) { signedLits++; }
3868 /* We should only come here to convert all
3869 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3870 * with exactly one operand being s8_t into
3871 * u8_t x u8_t -> u8_t. All other cases should have been
3872 * turned into calls to support routines beforehand... */
3873 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3874 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3876 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3877 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3879 /* Both operands are signed or negative, use _divschar
3880 * instead of _divuchar */
3881 pushaop(AOP(right), 0);
3882 pushaop(AOP(left), 0);
3884 /* call _divschar */
3885 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3889 sym = newSymbol( functions[op][0], 0 );
3891 strcpy(sym->rname, functions[op][0]);
3892 checkAddSym(&externs, sym);
3896 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3897 if (AOP_SIZE(result) > 1)
3899 pic16_emitpcode(POC_MOVFF,
3900 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3901 pic16_popGet(AOP(result), 1)));
3903 pic16_addSign(result, 2, 1);
3906 /* clean up stack */
3907 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3908 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3913 /* push right operand */
3914 if (IS_VALOP(right)) {
3916 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3919 pushaop(AOP(right), 0);
3921 } else if (!IS_UNSIGNED(operandType(right))) {
3922 pic16_mov2w(AOP(right), 0);
3923 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3924 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3925 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3928 pushaop(AOP(right), 0);
3931 /* push left operand */
3932 if (IS_VALOP(left)) {
3934 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3937 pushaop(AOP(left), 0);
3939 } else if (!IS_UNSIGNED(operandType(left))) {
3940 pic16_mov2w(AOP(left),0);
3941 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3942 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3943 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3946 pushaop(AOP(left), 0);
3949 /* call _divuchar */
3950 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3954 sym = newSymbol( functions[op][1], 0 );
3956 strcpy(sym->rname, functions[op][1]);
3957 checkAddSym(&externs, sym);
3960 /* Revert negation(s) from above.
3961 * This is inefficient: if both operands are negative, this
3962 * should not touch WREG. However, determining that exactly
3963 * one operand was negated costs at least 3 instructions,
3964 * so there is nothing to be gained here, is there?
3966 * I negate WREG because either operand might share registers with
3967 * result, so assigning first might destroy an operand. */
3969 /* For the modulus operator, (a/b)*b == a shall hold.
3970 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3971 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
3972 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
3973 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
3974 * Only invert the result if the left operand is negative (sigh).
3976 if (AOP_SIZE(result) <= 1 || !negated)
3980 if (IS_VALOP(right)) {
3982 /* we negated this operand above */
3983 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3985 } else if (!IS_UNSIGNED(operandType(right))) {
3986 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3987 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3991 if (IS_VALOP(left)) {
3993 /* we negated this operand above */
3994 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3996 } else if (!IS_UNSIGNED(operandType(left))) {
3997 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3998 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4001 /* Move result to destination. */
4002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4004 /* Zero-extend: no operand was signed (or result is just a byte). */
4005 pic16_addSign(result, 1, 0);
4007 assert( AOP_SIZE(result) > 1 );
4008 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4011 if (IS_VALOP(right)) {
4013 /* we negated this operand above */
4014 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4016 } else if (!IS_UNSIGNED(operandType(right))) {
4017 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4018 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4022 if (IS_VALOP(left)) {
4024 /* we negated this operand above */
4025 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4027 } else if (!IS_UNSIGNED(operandType(left))) {
4028 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4029 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4032 /* Move result to destination. */
4033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4035 /* Negate result if required. */
4036 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4037 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4040 pic16_addSign(result, 2, 1);
4043 /* clean up stack */
4044 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4045 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4050 /* special cases first */
4052 if (AOP_TYPE(left) == AOP_CRY &&
4053 AOP_TYPE(right)== AOP_CRY) {
4054 genDivbits(left,right,result);
4058 /* if both are of size == 1 */
4059 if (AOP_SIZE(left) == 1 &&
4060 AOP_SIZE(right) == 1 ) {
4061 genDivOneByte(left,right,result);
4066 /* should have been converted to function call */
4069 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4070 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4071 pic16_freeAsmop(result,NULL,ic,TRUE);
4075 /*-----------------------------------------------------------------*/
4076 /* genModbits :- modulus of bits */
4077 /*-----------------------------------------------------------------*/
4078 static void genModbits (operand *left,
4086 werror(W_POSSBUG2, __FILE__, __LINE__);
4087 /* the result must be bit */
4088 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4089 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4093 pic16_emitcode("div","ab");
4094 pic16_emitcode("mov","a,b");
4095 pic16_emitcode("rrc","a");
4096 pic16_aopPut(AOP(result),"c",0);
4099 /*-----------------------------------------------------------------*/
4100 /* genModOneByte : 8 bit modulus */
4101 /*-----------------------------------------------------------------*/
4102 static void genModOneByte (operand *left,
4106 sym_link *opetype = operandType(result);
4111 werror(W_POSSBUG2, __FILE__, __LINE__);
4113 /* signed or unsigned */
4114 if (SPEC_USIGN(opetype)) {
4115 /* unsigned is easy */
4116 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4117 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4119 pic16_emitcode("div","ab");
4120 pic16_aopPut(AOP(result),"b",0);
4124 /* signed is a little bit more difficult */
4126 /* save the signs of the operands */
4127 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4130 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4131 pic16_emitcode("push","acc"); /* save it on the stack */
4133 /* now sign adjust for both left & right */
4134 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4137 lbl = newiTempLabel(NULL);
4138 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4139 pic16_emitcode("cpl","a");
4140 pic16_emitcode("inc","a");
4141 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4142 pic16_emitcode("mov","b,a");
4144 /* sign adjust left side */
4145 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4148 lbl = newiTempLabel(NULL);
4149 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4150 pic16_emitcode("cpl","a");
4151 pic16_emitcode("inc","a");
4152 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4154 /* now the multiplication */
4155 pic16_emitcode("div","ab");
4156 /* we are interested in the lower order
4158 lbl = newiTempLabel(NULL);
4159 pic16_emitcode("pop","acc");
4160 /* if there was an over flow we don't
4161 adjust the sign of the result */
4162 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4163 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4165 pic16_emitcode("clr","a");
4166 pic16_emitcode("subb","a,b");
4167 pic16_emitcode("mov","b,a");
4168 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4170 /* now we are done */
4171 pic16_aopPut(AOP(result),"b",0);
4176 /*-----------------------------------------------------------------*/
4177 /* genMod - generates code for division */
4178 /*-----------------------------------------------------------------*/
4179 static void genMod (iCode *ic)
4181 /* Task deferred to genDiv */
4184 operand *left = IC_LEFT(ic);
4185 operand *right = IC_RIGHT(ic);
4186 operand *result= IC_RESULT(ic);
4190 /* assign the amsops */
4191 pic16_aopOp (left,ic,FALSE);
4192 pic16_aopOp (right,ic,FALSE);
4193 pic16_aopOp (result,ic,TRUE);
4195 /* special cases first */
4197 if (AOP_TYPE(left) == AOP_CRY &&
4198 AOP_TYPE(right)== AOP_CRY) {
4199 genModbits(left,right,result);
4203 /* if both are of size == 1 */
4204 if (AOP_SIZE(left) == 1 &&
4205 AOP_SIZE(right) == 1 ) {
4206 genModOneByte(left,right,result);
4210 /* should have been converted to function call */
4214 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4215 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4216 pic16_freeAsmop(result,NULL,ic,TRUE);
4220 /*-----------------------------------------------------------------*/
4221 /* genIfxJump :- will create a jump depending on the ifx */
4222 /*-----------------------------------------------------------------*/
4224 note: May need to add parameter to indicate when a variable is in bit space.
4226 static void genIfxJump (iCode *ic, char *jval)
4230 /* if true label then we jump if condition
4232 if ( IC_TRUE(ic) ) {
4234 if(strcmp(jval,"a") == 0)
4236 else if (strcmp(jval,"c") == 0)
4239 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4240 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4243 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4244 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4248 /* false label is present */
4249 if(strcmp(jval,"a") == 0)
4251 else if (strcmp(jval,"c") == 0)
4254 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4255 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4258 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4259 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4264 /* mark the icode as generated */
4268 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4272 /* if true label then we jump if condition
4274 if ( IC_TRUE(ic) ) {
4275 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4276 pic16_emitpcode(POC_BTFSC, jop);
4278 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4279 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4282 /* false label is present */
4283 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4284 pic16_emitpcode(POC_BTFSS, jop);
4286 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4287 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4291 /* mark the icode as generated */
4298 /*-----------------------------------------------------------------*/
4300 /*-----------------------------------------------------------------*/
4301 static void genSkip(iCode *ifx,int status_bit)
4303 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4307 if ( IC_TRUE(ifx) ) {
4308 switch(status_bit) {
4323 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4324 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4328 switch(status_bit) {
4342 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4343 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4350 /*-----------------------------------------------------------------*/
4352 /*-----------------------------------------------------------------*/
4353 static void genSkipc(resolvedIfx *rifx)
4355 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4365 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4366 rifx->generated = 1;
4369 /*-----------------------------------------------------------------*/
4370 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4371 /* aop (if it's NOT a literal) or from lit (if */
4372 /* aop is a literal) */
4373 /*-----------------------------------------------------------------*/
4374 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4375 if (aop->type == AOP_LIT) {
4376 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4378 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4382 /*-----------------------------------------------------------------*/
4383 /* genCmp :- greater or less than comparison */
4384 /*-----------------------------------------------------------------*/
4386 /* genCmp performs a left < right comparison, stores
4387 * the outcome in result (if != NULL) and generates
4388 * control flow code for the ifx (if != NULL).
4390 * This version leaves in sequences like
4391 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4392 * which should be optmized by the peephole
4393 * optimizer - RN 2005-01-01 */
4394 static void genCmp (operand *left,operand *right,
4395 operand *result, iCode *ifx, int sign)
4408 assert (left && right);
4409 assert (AOP_SIZE(left) == AOP_SIZE(right));
4411 size = AOP_SIZE(right) - 1;
4412 mask = (0x100UL << (size*8)) - 1;
4413 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4418 resolveIfx (&rIfx, ifx);
4420 /* handle for special cases */
4421 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4424 /**********************************************************************
4425 * handle bits - bit compares are promoted to int compares seemingly! *
4426 **********************************************************************/
4428 // THIS IS COMPLETELY UNTESTED!
4429 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4430 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4431 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4432 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4435 // 1 < {0,1} is false --> clear C by skipping the next instruction
4436 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4437 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4438 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4439 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4440 emitCLRC; // only skipped for left=0 && right=1
4442 goto correct_result_in_carry;
4446 /*************************************************
4447 * make sure that left is register (or the like) *
4448 *************************************************/
4449 if (!isAOP_REGlike(left)) {
4450 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4451 assert (isAOP_LIT(left));
4452 assert (isAOP_REGlike(right));
4453 // swap left and right
4454 // left < right <==> right > left <==> (right >= left + 1)
4455 lit = ulFromVal (AOP(left)->aopu.aop_lit);
4457 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4458 // MAXVALUE < right? always false
4459 if (performedLt) emitCLRC; else emitSETC;
4460 goto correct_result_in_carry;
4463 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4464 // that's why we handled it above.
4471 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4472 } else if (isAOP_LIT(right)) {
4473 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4476 assert (isAOP_REGlike(left)); // left must be register or the like
4477 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4479 /*************************************************
4480 * special cases go here *
4481 *************************************************/
4483 if (isAOP_LIT(right)) {
4485 // unsigned comparison to a literal
4486 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4488 // unsigned left < 0? always false
4489 if (performedLt) emitCLRC; else emitSETC;
4490 goto correct_result_in_carry;
4493 // signed comparison to a literal
4494 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4495 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4496 // signed left < 0x80000000? always false
4497 if (performedLt) emitCLRC; else emitSETC;
4498 goto correct_result_in_carry;
4499 } else if (lit == 0) {
4500 // compare left < 0; set CARRY if SIGNBIT(left) is set
4501 if (performedLt) emitSETC; else emitCLRC;
4502 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4503 if (performedLt) emitCLRC; else emitSETC;
4504 goto correct_result_in_carry;
4507 } // right is literal
4509 /*************************************************
4510 * perform a general case comparison *
4511 * make sure we get CARRY==1 <==> left >= right *
4512 *************************************************/
4513 // compare most significant bytes
4514 //DEBUGpc ("comparing bytes at offset %d", size);
4516 // unsigned comparison
4517 mov2w_regOrLit (AOP(right), lit, size);
4518 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4520 // signed comparison
4521 // (add 2^n to both operands then perform an unsigned comparison)
4522 if (isAOP_LIT(right)) {
4523 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4524 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4526 if (litbyte == 0x80) {
4527 // left >= 0x80 -- always true, but more bytes to come
4528 pic16_mov2w (AOP(left), size);
4529 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4532 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4533 pic16_mov2w (AOP(left), size);
4534 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4535 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4538 /* using PRODL as a temporary register here */
4539 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4540 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4541 pic16_mov2w (AOP(left), size);
4542 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4543 pic16_emitpcode (POC_MOVWF, pctemp);
4544 pic16_mov2w (AOP(right), size);
4545 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4546 pic16_emitpcode (POC_SUBFW, pctemp);
4547 //pic16_popReleaseTempReg(pctemp, 1);
4551 // compare remaining bytes (treat as unsigned case from above)
4552 templbl = newiTempLabel ( NULL );
4555 //DEBUGpc ("comparing bytes at offset %d", offs);
4556 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4557 mov2w_regOrLit (AOP(right), lit, offs);
4558 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4560 pic16_emitpLabel (templbl->key);
4561 goto result_in_carry;
4565 /****************************************************
4566 * now CARRY contains the result of the comparison: *
4567 * SUBWF sets CARRY iff *
4568 * F-W >= 0 <==> F >= W <==> !(F < W) *
4569 * (F=left, W=right) *
4570 ****************************************************/
4573 if (result && AOP_TYPE(result) != AOP_CRY) {
4574 // value will be stored
4577 // value wil only be used in the following genSkipc()
4578 rIfx.condition ^= 1;
4582 correct_result_in_carry:
4584 // assign result to variable (if neccessary)
4585 if (result && AOP_TYPE(result) != AOP_CRY) {
4586 //DEBUGpc ("assign result");
4587 size = AOP_SIZE(result);
4589 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4591 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4594 // perform conditional jump
4596 //DEBUGpc ("generate control flow");
4602 /*-----------------------------------------------------------------*/
4603 /* genCmpGt :- greater than comparison */
4604 /*-----------------------------------------------------------------*/
4605 static void genCmpGt (iCode *ic, iCode *ifx)
4607 operand *left, *right, *result;
4608 sym_link *letype , *retype;
4614 right= IC_RIGHT(ic);
4615 result = IC_RESULT(ic);
4617 letype = getSpec(operandType(left));
4618 retype =getSpec(operandType(right));
4619 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4620 /* assign the amsops */
4621 pic16_aopOp (left,ic,FALSE);
4622 pic16_aopOp (right,ic,FALSE);
4623 pic16_aopOp (result,ic,TRUE);
4625 genCmp(right, left, result, ifx, sign);
4627 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629 pic16_freeAsmop(result,NULL,ic,TRUE);
4632 /*-----------------------------------------------------------------*/
4633 /* genCmpLt - less than comparisons */
4634 /*-----------------------------------------------------------------*/
4635 static void genCmpLt (iCode *ic, iCode *ifx)
4637 operand *left, *right, *result;
4638 sym_link *letype , *retype;
4644 right= IC_RIGHT(ic);
4645 result = IC_RESULT(ic);
4647 letype = getSpec(operandType(left));
4648 retype =getSpec(operandType(right));
4649 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4651 /* assign the amsops */
4652 pic16_aopOp (left,ic,FALSE);
4653 pic16_aopOp (right,ic,FALSE);
4654 pic16_aopOp (result,ic,TRUE);
4656 genCmp(left, right, result, ifx, sign);
4658 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4659 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4660 pic16_freeAsmop(result,NULL,ic,TRUE);
4663 /*-----------------------------------------------------------------*/
4664 /* pic16_isLitOp - check if operand has to be treated as literal */
4665 /*-----------------------------------------------------------------*/
4666 bool pic16_isLitOp(operand *op)
4668 return ((AOP_TYPE(op) == AOP_LIT)
4669 || ( (AOP_TYPE(op) == AOP_PCODE)
4670 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4671 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4674 /*-----------------------------------------------------------------*/
4675 /* pic16_isLitAop - check if operand has to be treated as literal */
4676 /*-----------------------------------------------------------------*/
4677 bool pic16_isLitAop(asmop *aop)
4679 return ((aop->type == AOP_LIT)
4680 || ( (aop->type == AOP_PCODE)
4681 && ( (aop->aopu.pcop->type == PO_LITERAL)
4682 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4687 /*-----------------------------------------------------------------*/
4688 /* genCmpEq - generates code for equal to */
4689 /*-----------------------------------------------------------------*/
4690 static void genCmpEq (iCode *ic, iCode *ifx)
4692 operand *left, *right, *result;
4693 symbol *falselbl = newiTempLabel(NULL);
4694 symbol *donelbl = newiTempLabel(NULL);
4696 int preserve_result = 0;
4697 int generate_result = 0;
4699 unsigned long lit = -1;
4703 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4704 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4705 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4707 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4709 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4711 werror(W_POSSBUG2, __FILE__, __LINE__);
4712 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4713 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4717 if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4719 operand *tmp = right ;
4724 if (AOP_TYPE(right) == AOP_LIT) {
4725 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4728 if ( regsInCommon(left, result) || regsInCommon(right, result) )
4729 preserve_result = 1;
4731 if(result && AOP_SIZE(result))
4732 generate_result = 1;
4734 if(generate_result && !preserve_result)
4736 for(i = 0; i < AOP_SIZE(result); i++)
4737 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4740 assert( AOP_SIZE(left) == AOP_SIZE(right) );
4741 for(i=0; i < AOP_SIZE(left); i++)
4743 if(AOP_TYPE(left) != AOP_ACC)
4745 if(pic16_isLitOp(left))
4746 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4750 if(pic16_isLitOp(right)) {
4751 if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4752 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4755 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4757 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->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));
4769 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4771 if(generate_result && preserve_result)
4772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4774 if(ifx && IC_TRUE(ifx))
4775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4777 if(ifx && IC_FALSE(ifx))
4778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4780 pic16_emitpLabel(falselbl->key);
4784 if(ifx && IC_FALSE(ifx))
4785 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4787 if(generate_result && preserve_result)
4789 for(i = 0; i < AOP_SIZE(result); i++)
4790 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4793 pic16_emitpLabel(donelbl->key);
4799 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4800 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4801 pic16_freeAsmop(result,NULL,ic,TRUE);
4807 // old version kept for reference
4809 /*-----------------------------------------------------------------*/
4810 /* genCmpEq - generates code for equal to */
4811 /*-----------------------------------------------------------------*/
4812 static void genCmpEq (iCode *ic, iCode *ifx)
4814 operand *left, *right, *result;
4815 unsigned long lit = 0L;
4817 symbol *falselbl = newiTempLabel(NULL);
4820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4823 DEBUGpic16_emitcode ("; ifx is non-null","");
4825 DEBUGpic16_emitcode ("; ifx is null","");
4827 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4828 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4829 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4831 size = max(AOP_SIZE(left),AOP_SIZE(right));
4833 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4835 /* if literal, literal on the right or
4836 if the right is in a pointer register and left
4838 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4839 operand *tmp = right ;
4845 if(ifx && !AOP_SIZE(result)){
4847 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
4848 /* if they are both bit variables */
4849 if (AOP_TYPE(left) == AOP_CRY &&
4850 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4851 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
4852 if(AOP_TYPE(right) == AOP_LIT){
4853 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4855 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4856 pic16_emitcode("cpl","c");
4857 } else if(lit == 1L) {
4858 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4860 pic16_emitcode("clr","c");
4862 /* AOP_TYPE(right) == AOP_CRY */
4864 symbol *lbl = newiTempLabel(NULL);
4865 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4866 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4867 pic16_emitcode("cpl","c");
4868 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4870 /* if true label then we jump if condition
4872 tlbl = newiTempLabel(NULL);
4873 if ( IC_TRUE(ifx) ) {
4874 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4875 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4877 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4878 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4880 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4883 /* left and right are both bit variables, result is carry */
4886 resolveIfx(&rIfx,ifx);
4888 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4889 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4890 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4891 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4896 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
4898 /* They're not both bit variables. Is the right a literal? */
4899 if(AOP_TYPE(right) == AOP_LIT) {
4900 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4905 switch(lit & 0xff) {
4907 if ( IC_TRUE(ifx) ) {
4908 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4910 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4912 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4913 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4917 if ( IC_TRUE(ifx) ) {
4918 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4920 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4922 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4923 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4927 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4929 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4934 /* end of size == 1 */
4938 genc16bit2lit(left,lit,offset);
4941 /* end of size == 2 */
4946 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4947 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4948 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4949 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4952 /* search for patterns that can be optimized */
4954 genc16bit2lit(left,lit,0);
4958 emitSKPZ; // if hi word unequal
4960 emitSKPNZ; // if hi word equal
4962 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4963 genc16bit2lit(left,lit,2);
4966 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4967 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4971 pic16_emitpLabel(falselbl->key);
4980 } else if(AOP_TYPE(right) == AOP_CRY ) {
4981 /* we know the left is not a bit, but that the right is */
4982 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4983 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4984 pic16_popGet(AOP(right),offset));
4985 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4987 /* if the two are equal, then W will be 0 and the Z bit is set
4988 * we could test Z now, or go ahead and check the high order bytes if
4989 * the variable we're comparing is larger than a byte. */
4992 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4994 if ( IC_TRUE(ifx) ) {
4996 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4997 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5001 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5005 /* They're both variables that are larger than bits */
5008 tlbl = newiTempLabel(NULL);
5011 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5012 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5014 if ( IC_TRUE(ifx) ) {
5018 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5020 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5021 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5025 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5028 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5029 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5034 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5036 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5037 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5041 if(s>1 && IC_TRUE(ifx)) {
5042 pic16_emitpLabel(tlbl->key);
5043 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5047 /* mark the icode as generated */
5052 /* if they are both bit variables */
5053 if (AOP_TYPE(left) == AOP_CRY &&
5054 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5055 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5056 if(AOP_TYPE(right) == AOP_LIT){
5057 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5059 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5060 pic16_emitcode("cpl","c");
5061 } else if(lit == 1L) {
5062 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5064 pic16_emitcode("clr","c");
5066 /* AOP_TYPE(right) == AOP_CRY */
5068 symbol *lbl = newiTempLabel(NULL);
5069 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5070 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5071 pic16_emitcode("cpl","c");
5072 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5075 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5076 pic16_outBitC(result);
5080 genIfxJump (ifx,"c");
5083 /* if the result is used in an arithmetic operation
5084 then put the result in place */
5085 pic16_outBitC(result);
5088 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5089 gencjne(left,right,result,ifx);
5092 gencjne(left,right,newiTempLabel(NULL));
5094 if(IC_TRUE(ifx)->key)
5095 gencjne(left,right,IC_TRUE(ifx)->key);
5097 gencjne(left,right,IC_FALSE(ifx)->key);
5101 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5102 pic16_aopPut(AOP(result),"a",0);
5107 genIfxJump (ifx,"a");
5111 /* if the result is used in an arithmetic operation
5112 then put the result in place */
5114 if (AOP_TYPE(result) != AOP_CRY)
5115 pic16_outAcc(result);
5117 /* leave the result in acc */
5121 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5122 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5123 pic16_freeAsmop(result,NULL,ic,TRUE);
5127 /*-----------------------------------------------------------------*/
5128 /* ifxForOp - returns the icode containing the ifx for operand */
5129 /*-----------------------------------------------------------------*/
5130 static iCode *ifxForOp ( operand *op, iCode *ic )
5134 /* if true symbol then needs to be assigned */
5135 if (IS_TRUE_SYMOP(op))
5138 /* if this has register type condition and
5139 the next instruction is ifx with the same operand
5140 and live to of the operand is upto the ifx only then */
5142 && ic->next->op == IFX
5143 && IC_COND(ic->next)->key == op->key
5144 && OP_SYMBOL(op)->liveTo <= ic->next->seq
5146 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5152 ic->next->op == IFX &&
5153 IC_COND(ic->next)->key == op->key) {
5154 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5159 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5161 ic->next->op == IFX)
5162 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5165 ic->next->op == IFX &&
5166 IC_COND(ic->next)->key == op->key) {
5167 DEBUGpic16_emitcode ("; "," key is okay");
5168 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5169 OP_SYMBOL(op)->liveTo,
5174 /* the code below is completely untested
5175 * it just allows ulong2fs.c compile -- VR */
5178 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5179 __FILE__, __FUNCTION__, __LINE__);
5181 /* if this has register type condition and
5182 the next instruction is ifx with the same operand
5183 and live to of the operand is upto the ifx only then */
5185 ic->next->op == IFX &&
5186 IC_COND(ic->next)->key == op->key &&
5187 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5191 ic->next->op == IFX &&
5192 IC_COND(ic->next)->key == op->key) {
5193 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5197 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5198 __FILE__, __FUNCTION__, __LINE__);
5200 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
5205 /*-----------------------------------------------------------------*/
5206 /* genAndOp - for && operation */
5207 /*-----------------------------------------------------------------*/
5208 static void genAndOp (iCode *ic)
5210 operand *left,*right, *result;
5215 /* note here that && operations that are in an
5216 if statement are taken away by backPatchLabels
5217 only those used in arthmetic operations remain */
5218 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5219 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5220 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5222 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5224 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5225 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5226 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5228 /* if both are bit variables */
5229 /* if (AOP_TYPE(left) == AOP_CRY && */
5230 /* AOP_TYPE(right) == AOP_CRY ) { */
5231 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5232 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5233 /* pic16_outBitC(result); */
5235 /* tlbl = newiTempLabel(NULL); */
5236 /* pic16_toBoolean(left); */
5237 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5238 /* pic16_toBoolean(right); */
5239 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5240 /* pic16_outBitAcc(result); */
5243 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5244 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5245 pic16_freeAsmop(result,NULL,ic,TRUE);
5249 /*-----------------------------------------------------------------*/
5250 /* genOrOp - for || operation */
5251 /*-----------------------------------------------------------------*/
5254 modified this code, but it doesn't appear to ever get called
5257 static void genOrOp (iCode *ic)
5259 operand *left,*right, *result;
5264 /* note here that || operations that are in an
5265 if statement are taken away by backPatchLabels
5266 only those used in arthmetic operations remain */
5267 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5268 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5269 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5271 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5273 /* if both are bit variables */
5274 if (AOP_TYPE(left) == AOP_CRY &&
5275 AOP_TYPE(right) == AOP_CRY ) {
5276 pic16_emitcode("clrc","");
5277 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5278 AOP(left)->aopu.aop_dir,
5279 AOP(left)->aopu.aop_dir);
5280 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5281 AOP(right)->aopu.aop_dir,
5282 AOP(right)->aopu.aop_dir);
5283 pic16_emitcode("setc","");
5286 tlbl = newiTempLabel(NULL);
5287 pic16_toBoolean(left);
5289 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5290 pic16_toBoolean(right);
5291 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5293 pic16_outBitAcc(result);
5296 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5297 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5298 pic16_freeAsmop(result,NULL,ic,TRUE);
5301 /*-----------------------------------------------------------------*/
5302 /* isLiteralBit - test if lit == 2^n */
5303 /*-----------------------------------------------------------------*/
5304 static int isLiteralBit(unsigned long lit)
5306 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5307 0x100L,0x200L,0x400L,0x800L,
5308 0x1000L,0x2000L,0x4000L,0x8000L,
5309 0x10000L,0x20000L,0x40000L,0x80000L,
5310 0x100000L,0x200000L,0x400000L,0x800000L,
5311 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5312 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5315 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5316 for(idx = 0; idx < 32; idx++)
5322 /*-----------------------------------------------------------------*/
5323 /* continueIfTrue - */
5324 /*-----------------------------------------------------------------*/
5325 static void continueIfTrue (iCode *ic)
5329 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5333 /*-----------------------------------------------------------------*/
5335 /*-----------------------------------------------------------------*/
5336 static void jumpIfTrue (iCode *ic)
5340 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5344 /*-----------------------------------------------------------------*/
5345 /* jmpTrueOrFalse - */
5346 /*-----------------------------------------------------------------*/
5347 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5349 // ugly but optimized by peephole
5352 symbol *nlbl = newiTempLabel(NULL);
5353 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5354 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5355 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5356 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5358 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5359 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5364 /*-----------------------------------------------------------------*/
5365 /* genAnd - code for and */
5366 /*-----------------------------------------------------------------*/
5367 static void genAnd (iCode *ic, iCode *ifx)
5369 operand *left, *right, *result;
5370 int size, offset = 0;
5371 unsigned long lit = 0L;
5376 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5377 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5378 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5380 resolveIfx (&rIfx, ifx);
5382 /* if left is a literal & right is not then exchange them */
5383 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5384 AOP_NEEDSACC (left))
5386 operand *tmp = right;
5391 /* if result = right then exchange them */
5392 if (pic16_sameRegs (AOP (result), AOP (right)))
5394 operand *tmp = right;
5399 /* if right is bit then exchange them */
5400 if (AOP_TYPE (right) == AOP_CRY &&
5401 AOP_TYPE (left) != AOP_CRY)
5403 operand *tmp = right;
5408 if (AOP_TYPE (right) == AOP_LIT)
5409 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5411 size = AOP_SIZE (result);
5413 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5416 // result = bit & yy;
5417 if (AOP_TYPE(left) == AOP_CRY){
5418 // c = bit & literal;
5419 if(AOP_TYPE(right) == AOP_LIT){
5421 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5424 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5427 if(size && (AOP_TYPE(result) == AOP_CRY)){
5428 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5431 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5435 pic16_emitcode("clr","c");
5438 if (AOP_TYPE(right) == AOP_CRY){
5440 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5441 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5444 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5446 pic16_emitcode("rrc","a");
5447 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5453 pic16_outBitC(result);
5455 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5456 genIfxJump(ifx, "c");
5460 // if (val & 0xZZ) - size = 0, ifx != FALSE -
5461 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5462 if ((AOP_TYPE (right) == AOP_LIT) &&
5463 (AOP_TYPE (result) == AOP_CRY) &&
5464 (AOP_TYPE (left) != AOP_CRY))
5466 symbol *tlbl = newiTempLabel (NULL);
5467 int sizel = AOP_SIZE (left);
5474 /* get number of non null bytes in literal */
5477 if (lit & (0xff << (sizel * 8)))
5481 emitBra = nonnull || rIfx.condition;
5483 for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5485 unsigned char bytelit = lit;
5493 /* patch provided by Aaron Colwell */
5494 if ((posbit = isLiteralBit (bytelit)) != 0)
5498 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5499 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5503 pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5508 if (bytelit == 0xff)
5510 /* Aaron had a MOVF instruction here, changed to MOVFW cause
5511 * a peephole could optimize it out -- VR */
5512 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5516 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5517 pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5524 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5528 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5533 /* last non null byte */
5543 // bit = left & literal
5547 pic16_emitpLabel (tlbl->key);
5550 // if(left & literal)
5556 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
5559 pic16_emitpLabel (tlbl->key);
5562 pic16_outBitC (result);
5566 /* if left is same as result */
5567 if(pic16_sameRegs(AOP(result),AOP(left))){
5569 for(;size--; offset++,lit>>=8) {
5570 if(AOP_TYPE(right) == AOP_LIT){
5571 switch(lit & 0xff) {
5573 /* and'ing with 0 has clears the result */
5574 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5575 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5578 /* and'ing with 0xff is a nop when the result and left are the same */
5583 int p = pic16_my_powof2( (~lit) & 0xff );
5585 /* only one bit is set in the literal, so use a bcf instruction */
5586 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5587 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5590 pic16_emitcode("movlw","0x%x", (lit & 0xff));
5591 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5592 if(know_W != (lit&0xff))
5593 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5595 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5600 if (AOP_TYPE(left) == AOP_ACC) {
5601 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5603 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5604 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5611 // left & result in different registers
5612 if(AOP_TYPE(result) == AOP_CRY){
5614 // if(size), result in bit
5615 // if(!size && ifx), conditional oper: if(left & right)
5616 symbol *tlbl = newiTempLabel(NULL);
5617 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5619 pic16_emitcode("setb","c");
5621 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5622 pic16_emitcode("anl","a,%s",
5623 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5624 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5629 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5630 pic16_outBitC(result);
5632 jmpTrueOrFalse(ifx, tlbl);
5634 for(;(size--);offset++) {
5636 // result = left & right
5637 if(AOP_TYPE(right) == AOP_LIT){
5638 int t = (lit >> (offset*8)) & 0x0FFL;
5641 pic16_emitcode("clrf","%s",
5642 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5643 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5646 pic16_emitcode("movf","%s,w",
5647 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5648 pic16_emitcode("movwf","%s",
5649 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5650 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5651 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5654 pic16_emitcode("movlw","0x%x",t);
5655 pic16_emitcode("andwf","%s,w",
5656 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5657 pic16_emitcode("movwf","%s",
5658 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5660 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5661 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5662 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5667 if (AOP_TYPE(left) == AOP_ACC) {
5668 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5669 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5671 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5672 pic16_emitcode("andwf","%s,w",
5673 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5675 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5677 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5678 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5684 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5685 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5686 pic16_freeAsmop(result,NULL,ic,TRUE);
5689 /*-----------------------------------------------------------------*/
5690 /* genOr - code for or */
5691 /*-----------------------------------------------------------------*/
5692 static void genOr (iCode *ic, iCode *ifx)
5694 operand *left, *right, *result;
5695 int size, offset = 0;
5696 unsigned long lit = 0L;
5701 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5702 pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5703 pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5705 resolveIfx (&rIfx, ifx);
5707 /* if left is a literal & right is not then exchange them */
5708 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5709 AOP_NEEDSACC (left))
5711 operand *tmp = right;
5716 /* if result = right then exchange them */
5717 if (pic16_sameRegs (AOP (result), AOP (right)))
5719 operand *tmp = right;
5724 /* if right is bit then exchange them */
5725 if (AOP_TYPE (right) == AOP_CRY &&
5726 AOP_TYPE (left) != AOP_CRY)
5728 operand *tmp = right;
5733 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5735 if (AOP_TYPE (right) == AOP_LIT)
5736 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5738 size = AOP_SIZE (result);
5742 if (AOP_TYPE(left) == AOP_CRY){
5743 if(AOP_TYPE(right) == AOP_LIT){
5744 // c = bit & literal;
5746 // lit != 0 => result = 1
5747 if(AOP_TYPE(result) == AOP_CRY){
5749 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5750 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5751 // AOP(result)->aopu.aop_dir,
5752 // AOP(result)->aopu.aop_dir);
5754 continueIfTrue(ifx);
5758 // lit == 0 => result = left
5759 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5761 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5764 if (AOP_TYPE(right) == AOP_CRY){
5765 if(pic16_sameRegs(AOP(result),AOP(left))){
5767 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5768 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5769 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5772 if( AOP_TYPE(result) == AOP_ACC) {
5773 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5774 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5775 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5776 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5780 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5781 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5782 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5783 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5789 symbol *tlbl = newiTempLabel(NULL);
5790 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5793 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5794 if( AOP_TYPE(right) == AOP_ACC) {
5795 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5797 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5798 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5803 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5804 pic16_emitcode(";XXX setb","c");
5805 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5806 AOP(left)->aopu.aop_dir,tlbl->key+100);
5807 pic16_toBoolean(right);
5808 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5809 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5810 jmpTrueOrFalse(ifx, tlbl);
5814 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5821 pic16_outBitC(result);
5823 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5824 genIfxJump(ifx, "c");
5828 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5829 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5830 if ((AOP_TYPE (right) == AOP_LIT) &&
5831 (AOP_TYPE (result) == AOP_CRY) &&
5832 (AOP_TYPE (left) != AOP_CRY))
5834 if (IS_OP_VOLATILE(left)) {
5835 pic16_mov2w_volatile(AOP(left));
5840 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5849 /* if left is same as result */
5850 if(pic16_sameRegs(AOP(result),AOP(left))){
5852 for(;size--; offset++,lit>>=8) {
5853 if(AOP_TYPE(right) == AOP_LIT){
5854 if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5855 /* or'ing with 0 has no effect */
5858 int p = pic16_my_powof2(lit & 0xff);
5860 /* only one bit is set in the literal, so use a bsf instruction */
5861 pic16_emitpcode(POC_BSF,
5862 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5864 if(know_W != (lit & 0xff))
5865 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5866 know_W = lit & 0xff;
5867 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5872 if (AOP_TYPE(left) == AOP_ACC) {
5873 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
5875 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5876 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5881 // left & result in different registers
5882 if(AOP_TYPE(result) == AOP_CRY){
5884 // if(size), result in bit
5885 // if(!size && ifx), conditional oper: if(left | right)
5886 symbol *tlbl = newiTempLabel(NULL);
5887 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5888 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5892 pic16_emitcode(";XXX setb","c");
5894 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5895 pic16_emitcode(";XXX orl","a,%s",
5896 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5897 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5902 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5903 pic16_outBitC(result);
5905 jmpTrueOrFalse(ifx, tlbl);
5906 } else for(;(size--);offset++){
5908 // result = left & right
5909 if(AOP_TYPE(right) == AOP_LIT){
5910 int t = (lit >> (offset*8)) & 0x0FFL;
5913 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
5914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5917 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5918 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5919 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5924 // faster than result <- left, anl result,right
5925 // and better if result is SFR
5926 if (AOP_TYPE(left) == AOP_ACC) {
5927 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
5929 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5930 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5932 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5937 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5938 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5939 pic16_freeAsmop(result,NULL,ic,TRUE);
5942 /*-----------------------------------------------------------------*/
5943 /* genXor - code for xclusive or */
5944 /*-----------------------------------------------------------------*/
5945 static void genXor (iCode *ic, iCode *ifx)
5947 operand *left, *right, *result;
5948 int size, offset = 0;
5949 unsigned long lit = 0L;
5954 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5955 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5956 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5958 resolveIfx (&rIfx,ifx);
5960 /* if left is a literal & right is not ||
5961 if left needs acc & right does not */
5962 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5963 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5965 operand *tmp = right;
5970 /* if result = right then exchange them */
5971 if (pic16_sameRegs (AOP (result), AOP (right)))
5973 operand *tmp = right ;
5978 /* if right is bit then exchange them */
5979 if (AOP_TYPE (right) == AOP_CRY &&
5980 AOP_TYPE (left) != AOP_CRY)
5982 operand *tmp = right ;
5987 if (AOP_TYPE (right) == AOP_LIT)
5988 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5990 size = AOP_SIZE (result);
5994 if (AOP_TYPE(left) == AOP_CRY)
5996 if (AOP_TYPE(right) == AOP_LIT)
5998 // c = bit & literal;
6001 // lit>>1 != 0 => result = 1
6002 if (AOP_TYPE(result) == AOP_CRY)
6006 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
6009 continueIfTrue(ifx);
6012 pic16_emitcode("setb", "c");
6019 // lit == 0, result = left
6020 if (size && pic16_sameRegs(AOP(result), AOP(left)))
6022 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6026 // lit == 1, result = not(left)
6027 if (size && pic16_sameRegs(AOP(result), AOP(left)))
6029 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6030 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6031 pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6036 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6037 pic16_emitcode("cpl", "c");
6045 symbol *tlbl = newiTempLabel(NULL);
6046 if (AOP_TYPE(right) == AOP_CRY)
6049 pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6053 int sizer = AOP_SIZE(right);
6055 // if val>>1 != 0, result = 1
6056 pic16_emitcode("setb", "c");
6059 MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6061 // test the msb of the lsb
6062 pic16_emitcode("anl", "a,#0xfe");
6063 pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6067 pic16_emitcode("rrc", "a");
6069 pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6070 pic16_emitcode("cpl", "c");
6071 pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6076 pic16_outBitC(result);
6078 else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6079 genIfxJump(ifx, "c");
6083 // if(val ^ 0xZZ) - size = 0, ifx != FALSE -
6084 // bit = val ^ 0xZZ - size = 1, ifx = FALSE -
6085 if ((AOP_TYPE (right) == AOP_LIT) &&
6086 (AOP_TYPE (result) == AOP_CRY) &&
6087 (AOP_TYPE (left) != AOP_CRY))
6089 symbol *tlbl = newiTempLabel (NULL);
6095 for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6097 unsigned char bytelit = lit;
6102 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6106 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6110 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6111 pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6118 /* rIfx.lbl might be far away... */
6120 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6124 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6129 /* last non null byte */
6137 // bit = left ^ literal
6141 pic16_emitpLabel (tlbl->key);
6143 // if (left ^ literal)
6148 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
6151 pic16_emitpLabel (tlbl->key);
6155 pic16_outBitC (result);
6159 if (pic16_sameRegs(AOP(result), AOP(left)))
6161 /* if left is same as result */
6162 for (; size--; offset++)
6164 if (AOP_TYPE(right) == AOP_LIT)
6166 int t = (lit >> (offset * 8)) & 0x0FFL;
6171 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6172 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6177 if (AOP_TYPE(left) == AOP_ACC)
6178 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6181 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6182 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6189 // left ^ result in different registers
6190 if (AOP_TYPE(result) == AOP_CRY)
6193 // if(size), result in bit
6194 // if(!size && ifx), conditional oper: if(left ^ right)
6195 symbol *tlbl = newiTempLabel(NULL);
6196 int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6198 pic16_emitcode("setb", "c");
6201 if ((AOP_TYPE(right) == AOP_LIT) &&
6202 (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6204 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6208 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6209 pic16_emitcode("xrl", "a,%s",
6210 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6212 pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6218 pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6219 pic16_outBitC(result);
6222 jmpTrueOrFalse(ifx, tlbl);
6226 for (; (size--); offset++)
6229 // result = left ^ right
6230 if (AOP_TYPE(right) == AOP_LIT)
6232 int t = (lit >> (offset * 8)) & 0x0FFL;
6236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6241 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6242 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6246 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6247 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6248 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6253 // faster than result <- left, anl result,right
6254 // and better if result is SFR
6255 if (AOP_TYPE(left) == AOP_ACC)
6257 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6261 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6262 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6264 if ( AOP_TYPE(result) != AOP_ACC)
6266 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6273 pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6274 pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6275 pic16_freeAsmop(result, NULL, ic, TRUE);
6278 /*-----------------------------------------------------------------*/
6279 /* genInline - write the inline code out */
6280 /*-----------------------------------------------------------------*/
6281 static void genInline (iCode *ic)
6283 char *buffer, *bp, *bp1;
6284 bool inComment = FALSE;
6286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6288 _G.inLine += (!options.asmpeep);
6290 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6292 while((bp1=strstr(bp, "\\n"))) {
6300 /* This is an experimental code for #pragma inline
6301 and is temporarily disabled for 2.5.0 release */
6309 cbuf = Safe_strdup(buffer);
6310 cblen = strlen(buffer)+1;
6311 memset(cbuf, 0, cblen);
6316 if(*bp != '%')*bp1++ = *bp++;
6322 if(i>elementsInSet(asmInlineMap))break;
6325 s = indexSet(asmInlineMap, i);
6326 DEBUGpc("searching symbol s = `%s'", s);
6327 sym = findSym(SymbolTab, NULL, s);
6330 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6332 strcat(bp1, sym->rname);
6338 if(strlen(bp1) > cblen - 16) {
6339 int i = strlen(cbuf);
6341 cbuf = realloc(cbuf, cblen);
6342 memset(cbuf+i, 0, 50);
6348 buffer = Safe_strdup( cbuf );
6355 /* emit each line as a code */
6369 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6374 /* Add \n for labels, not dirs such as c:\mydir */
6375 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6380 /* print label, use this special format with NULL directive
6381 * to denote that the argument should not be indented with tab */
6382 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6391 if ((bp1 != bp) && *bp1)
6392 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6396 _G.inLine -= (!options.asmpeep);
6399 /*-----------------------------------------------------------------*/
6400 /* genRRC - rotate right with carry */
6401 /*-----------------------------------------------------------------*/
6402 static void genRRC (iCode *ic)
6404 operand *left , *result ;
6407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6409 /* rotate right with carry */
6411 result=IC_RESULT(ic);
6412 pic16_aopOp (left,ic,FALSE);
6413 pic16_aopOp (result,ic,TRUE);
6415 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6417 same = pic16_sameRegs(AOP(result),AOP(left));
6419 size = AOP_SIZE(result);
6421 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6423 /* get the lsb and put it into the carry */
6424 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
6429 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),size));
6431 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size));
6432 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
6436 pic16_freeAsmop(left,NULL,ic,TRUE);
6437 pic16_freeAsmop(result,NULL,ic,TRUE);
6440 /*-----------------------------------------------------------------*/
6441 /* genRLC - generate code for rotate left with carry */
6442 /*-----------------------------------------------------------------*/
6443 static void genRLC (iCode *ic)
6445 operand *left , *result ;
6446 int size, offset = 0;
6449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6450 /* rotate right with carry */
6452 result=IC_RESULT(ic);
6453 pic16_aopOp (left,ic,FALSE);
6454 pic16_aopOp (result,ic,TRUE);
6456 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6458 same = pic16_sameRegs(AOP(result),AOP(left));
6460 /* move it to the result */
6461 size = AOP_SIZE(result);
6463 /* get the msb and put it into the carry */
6464 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6471 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6473 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6474 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6481 pic16_freeAsmop(left,NULL,ic,TRUE);
6482 pic16_freeAsmop(result,NULL,ic,TRUE);
6486 /* gpasm can get the highest order bit with HIGH/UPPER
6487 * so the following probably is not needed -- VR */
6489 /*-----------------------------------------------------------------*/
6490 /* genGetHbit - generates code get highest order bit */
6491 /*-----------------------------------------------------------------*/
6492 static void genGetHbit (iCode *ic)
6494 operand *left, *result;
6496 result=IC_RESULT(ic);
6497 pic16_aopOp (left,ic,FALSE);
6498 pic16_aopOp (result,ic,FALSE);
6500 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6501 /* get the highest order byte into a */
6502 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6503 if(AOP_TYPE(result) == AOP_CRY){
6504 pic16_emitcode("rlc","a");
6505 pic16_outBitC(result);
6508 pic16_emitcode("rl","a");
6509 pic16_emitcode("anl","a,#0x01");
6510 pic16_outAcc(result);
6514 pic16_freeAsmop(left,NULL,ic,TRUE);
6515 pic16_freeAsmop(result,NULL,ic,TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* AccRol - rotate left accumulator by known count */
6521 /*-----------------------------------------------------------------*/
6522 static void AccRol (int shCount)
6524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6525 shCount &= 0x0007; // shCount : 0..7
6530 pic16_emitcode("rl","a");
6533 pic16_emitcode("rl","a");
6534 pic16_emitcode("rl","a");
6537 pic16_emitcode("swap","a");
6538 pic16_emitcode("rr","a");
6541 pic16_emitcode("swap","a");
6544 pic16_emitcode("swap","a");
6545 pic16_emitcode("rl","a");
6548 pic16_emitcode("rr","a");
6549 pic16_emitcode("rr","a");
6552 pic16_emitcode("rr","a");
6558 /*-----------------------------------------------------------------*/
6559 /* AccLsh - left shift accumulator by known count */
6560 /*-----------------------------------------------------------------*/
6561 static void AccLsh (int shCount, int doMask)
6563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6569 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6572 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6573 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6576 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6577 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6580 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6583 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6584 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6587 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6588 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6591 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6595 /* no masking is required in genPackBits */
6596 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6600 /*-----------------------------------------------------------------*/
6601 /* AccRsh - right shift accumulator by known count */
6602 /*-----------------------------------------------------------------*/
6603 static void AccRsh (int shCount, int andmask)
6605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6606 assert ((shCount >= 0) && (shCount <= 8));
6611 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6614 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6615 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6618 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6619 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6622 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6625 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6626 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6629 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6630 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6633 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6636 // Rotating by 8 is a NOP.
6641 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6643 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6646 /*-----------------------------------------------------------------*/
6647 /* shiftR1Left2Result - shift right one byte from left to result */
6648 /*-----------------------------------------------------------------*/
6649 static void shiftR1Left2ResultSigned (operand *left, int offl,
6650 operand *result, int offr,
6655 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6656 assert ((shCount >= 0) && (shCount <= 8));
6658 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6660 /* Do NOT use result for intermediate results, it might be an SFR!. */
6664 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6670 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6672 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6674 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6675 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6680 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6681 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6682 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6683 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6684 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6685 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6689 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6690 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6691 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6692 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6693 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6694 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6698 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6699 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6700 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6701 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6702 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6706 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6707 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6708 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6709 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6710 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6715 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6716 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6717 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6718 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6719 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6720 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6724 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6725 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6726 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6731 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6736 /*-----------------------------------------------------------------*/
6737 /* shiftR1Left2Result - shift right one byte from left to result */
6738 /*-----------------------------------------------------------------*/
6739 static void shiftR1Left2Result (operand *left, int offl,
6740 operand *result, int offr,
6741 int shCount, int sign)
6745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6746 assert ((shCount >= 0) && (shCount <= 8));
6748 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6750 /* Copy the msb into the carry if signed. */
6752 shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6756 /* Do NOT use result for intermediate results, it might be an SFR!. */
6760 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6761 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6768 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6770 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6771 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6772 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6777 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6778 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6779 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6784 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6785 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6786 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6791 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6792 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6797 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6798 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6799 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6800 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6804 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6805 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6806 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6807 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6811 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6812 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6813 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6817 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6822 /*-----------------------------------------------------------------*/
6823 /* shiftL1Left2Result - shift left one byte from left to result */
6824 /*-----------------------------------------------------------------*/
6825 static void shiftL1Left2Result (operand *left, int offl,
6826 operand *result, int offr, int shCount)
6830 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6831 assert ((shCount >= 0) && (shCount <= 8));
6833 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6835 /* Do NOT use result for intermediate results, it might be an SFR!. */
6839 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6840 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6847 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6849 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6850 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6851 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6856 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6857 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6859 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6863 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6864 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6865 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6866 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6870 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6871 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6876 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6877 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6878 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6879 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6883 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6884 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6885 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6886 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6890 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6891 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6892 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6896 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6901 /*-----------------------------------------------------------------*/
6902 /* movLeft2Result - move byte from left to result */
6903 /*-----------------------------------------------------------------*/
6904 static void movLeft2Result (operand *left, int offl,
6905 operand *result, int offr)
6907 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6908 if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6909 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6910 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6914 /*-----------------------------------------------------------------*/
6915 /* shiftL2Left2Result - shift left two bytes from left to result */
6916 /*-----------------------------------------------------------------*/
6917 static void shiftL2Left2Result (operand *left, int offl,
6918 operand *result, int offr, int shCount)
6920 int same = pic16_sameRegs(AOP(result), AOP(left));
6923 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6925 if (same && (offl != offr)) { // shift bytes
6928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6929 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6931 } else { // just treat as different later on
6944 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6945 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6950 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6951 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6958 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6959 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6960 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6961 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6962 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6963 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6965 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6966 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6970 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6971 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6972 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6973 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6974 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6975 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6976 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6977 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6978 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6979 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6982 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6983 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6984 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6985 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6986 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6996 /* note, use a mov/add for the shift since the mov has a
6997 chance of getting optimized out */
6998 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7000 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7001 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7006 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7007 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7013 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7016 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
7019 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7020 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7024 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7025 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7029 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl));
7030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7031 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
7032 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl+MSB16));
7033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7034 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr+MSB16));
7035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xc0));
7036 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7037 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7038 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(result),offr));
7039 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(result),offr+MSB16));
7040 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7043 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7044 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7045 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7046 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7047 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7052 /*-----------------------------------------------------------------*/
7053 /* shiftR2Left2Result - shift right two bytes from left to result */
7054 /*-----------------------------------------------------------------*/
7055 static void shiftR2Left2Result (operand *left, int offl,
7056 operand *result, int offr,
7057 int shCount, int sign)
7059 int same = pic16_sameRegs(AOP(result), AOP(left));
7061 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7063 if (same && (offl != offr)) { // shift right bytes
7066 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7067 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7069 } else { // just treat as different later on
7080 /* obtain sign from left operand */
7082 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7087 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7088 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7090 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7091 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7092 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7093 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7098 /* now get sign from already assigned result (avoid BANKSEL) */
7099 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7102 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7103 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7110 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7111 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7112 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7114 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7115 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7116 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7117 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7119 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7121 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7123 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7124 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7125 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7126 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7127 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7131 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7132 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7136 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7137 pic16_emitpcode(POC_BTFSC,
7138 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7139 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7147 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7148 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7150 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7151 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7152 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7153 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7155 pic16_emitpcode(POC_BTFSC,
7156 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7157 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7159 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7160 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7161 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7164 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7165 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7166 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7167 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7169 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7170 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7171 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7173 pic16_emitpcode(POC_BTFSC,
7174 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7175 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7178 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7186 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7187 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7188 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7191 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7193 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7198 /*-----------------------------------------------------------------*/
7199 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7200 /*-----------------------------------------------------------------*/
7201 static void shiftLLeftOrResult (operand *left, int offl,
7202 operand *result, int offr, int shCount)
7204 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7206 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7207 /* shift left accumulator */
7209 /* or with result */
7210 /* back to result */
7211 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7214 /*-----------------------------------------------------------------*/
7215 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7216 /*-----------------------------------------------------------------*/
7217 static void shiftRLeftOrResult (operand *left, int offl,
7218 operand *result, int offr, int shCount)
7220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7222 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7223 /* shift right accumulator */
7225 /* or with result */
7226 /* back to result */
7227 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7230 /*-----------------------------------------------------------------*/
7231 /* genlshOne - left shift a one byte quantity by known count */
7232 /*-----------------------------------------------------------------*/
7233 static void genlshOne (operand *result, operand *left, int shCount)
7235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7236 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7239 /*-----------------------------------------------------------------*/
7240 /* genlshTwo - left shift two bytes by known amount != 0 */
7241 /*-----------------------------------------------------------------*/
7242 static void genlshTwo (operand *result,operand *left, int shCount)
7246 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7247 size = pic16_getDataSize(result);
7249 /* if shCount >= 8 */
7255 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7257 movLeft2Result(left, LSB, result, MSB16);
7259 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7262 /* 1 <= shCount <= 7 */
7265 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7267 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7271 /*-----------------------------------------------------------------*/
7272 /* shiftLLong - shift left one long from left to result */
7273 /* offr = LSB or MSB16 */
7274 /*-----------------------------------------------------------------*/
7275 static void shiftLLong (operand *left, operand *result, int offr )
7277 int size = AOP_SIZE(result);
7278 int same = pic16_sameRegs(AOP(left),AOP(result));
7281 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7283 if (same && (offr == MSB16)) { //shift one byte
7284 for(i=size-1;i>=MSB16;i--) {
7285 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7286 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7289 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB));
7292 if (size > LSB+offr ){
7294 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7296 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7297 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7301 if(size > MSB16+offr){
7303 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7305 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7306 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7310 if(size > MSB24+offr){
7312 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7314 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7315 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7319 if(size > MSB32+offr){
7321 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7323 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7324 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7328 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7332 /*-----------------------------------------------------------------*/
7333 /* genlshFour - shift four byte by a known amount != 0 */
7334 /*-----------------------------------------------------------------*/
7335 static void genlshFour (operand *result, operand *left, int shCount)
7339 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7340 size = AOP_SIZE(result);
7342 /* if shifting more that 3 bytes */
7343 if (shCount >= 24 ) {
7346 /* lowest order of left goes to the highest
7347 order of the destination */
7348 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7350 movLeft2Result(left, LSB, result, MSB32);
7352 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7353 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7354 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7359 /* more than two bytes */
7360 else if ( shCount >= 16 ) {
7361 /* lower order two bytes goes to higher order two bytes */
7363 /* if some more remaining */
7365 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7367 movLeft2Result(left, MSB16, result, MSB32);
7368 movLeft2Result(left, LSB, result, MSB24);
7370 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7371 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7375 /* if more than 1 byte */
7376 else if ( shCount >= 8 ) {
7377 /* lower order three bytes goes to higher order three bytes */
7381 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7383 movLeft2Result(left, LSB, result, MSB16);
7385 else{ /* size = 4 */
7387 movLeft2Result(left, MSB24, result, MSB32);
7388 movLeft2Result(left, MSB16, result, MSB24);
7389 movLeft2Result(left, LSB, result, MSB16);
7390 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7392 else if(shCount == 1)
7393 shiftLLong(left, result, MSB16);
7395 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7396 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7397 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7398 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7403 /* 1 <= shCount <= 7 */
7404 else if(shCount <= 3)
7406 shiftLLong(left, result, LSB);
7407 while(--shCount >= 1)
7408 shiftLLong(result, result, LSB);
7410 /* 3 <= shCount <= 7, optimize */
7412 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7413 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7414 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7418 /*-----------------------------------------------------------------*/
7419 /* genLeftShiftLiteral - left shifting by known count */
7420 /*-----------------------------------------------------------------*/
7421 void pic16_genLeftShiftLiteral (operand *left,
7426 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7430 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7431 pic16_freeAsmop(right,NULL,ic,TRUE);
7433 pic16_aopOp(left,ic,FALSE);
7434 pic16_aopOp(result,ic,TRUE);
7436 size = getSize(operandType(result));
7439 pic16_emitcode("; shift left ","result %d, left %d",size,
7443 /* I suppose that the left size >= result size */
7446 movLeft2Result(left, size, result, size);
7450 else if(shCount >= (size * 8))
7452 pic16_aopPut(AOP(result),zero,size);
7456 genlshOne (result,left,shCount);
7461 genlshTwo (result,left,shCount);
7465 genlshFour (result,left,shCount);
7469 pic16_freeAsmop(left,NULL,ic,TRUE);
7470 pic16_freeAsmop(result,NULL,ic,TRUE);
7473 /*-----------------------------------------------------------------*
7474 * genMultiAsm - repeat assembly instruction for size of register.
7475 * if endian == 1, then the high byte (i.e base address + size of
7476 * register) is used first else the low byte is used first;
7477 *-----------------------------------------------------------------*/
7478 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7496 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7502 /*-----------------------------------------------------------------*/
7503 /* genrshOne - right shift a one byte quantity by known count */
7504 /*-----------------------------------------------------------------*/
7505 static void genrshOne (operand *result, operand *left,
7506 int shCount, int sign)
7508 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7509 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7512 /*-----------------------------------------------------------------*/
7513 /* genrshTwo - right shift two bytes by known amount != 0 */
7514 /*-----------------------------------------------------------------*/
7515 static void genrshTwo (operand *result,operand *left,
7516 int shCount, int sign)
7518 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7519 /* if shCount >= 8 */
7523 shiftR1Left2Result(left, MSB16, result, LSB,
7526 movLeft2Result(left, MSB16, result, LSB);
7528 pic16_addSign (result, 1, sign);
7531 /* 1 <= shCount <= 7 */
7533 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7536 /*-----------------------------------------------------------------*/
7537 /* shiftRLong - shift right one long from left to result */
7538 /* offl = LSB or MSB16 */
7539 /*-----------------------------------------------------------------*/
7540 static void shiftRLong (operand *left, int offl,
7541 operand *result, int sign)
7543 int size = AOP_SIZE(result);
7544 int same = pic16_sameRegs(AOP(left),AOP(result));
7546 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7548 if (same && (offl == MSB16)) { //shift one byte right
7549 for(i=MSB16;i<size;i++) {
7550 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7551 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7556 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7562 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7564 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7565 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7569 /* add sign of "a" */
7570 pic16_addSign(result, MSB32, sign);
7574 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7576 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7577 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7581 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7583 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7584 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7588 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7591 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7592 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7597 /*-----------------------------------------------------------------*/
7598 /* genrshFour - shift four byte by a known amount != 0 */
7599 /*-----------------------------------------------------------------*/
7600 static void genrshFour (operand *result, operand *left,
7601 int shCount, int sign)
7603 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7604 /* if shifting more that 3 bytes */
7605 if(shCount >= 24 ) {
7608 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7610 movLeft2Result(left, MSB32, result, LSB);
7612 pic16_addSign(result, MSB16, sign);
7614 else if(shCount >= 16){
7617 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7619 movLeft2Result(left, MSB24, result, LSB);
7620 movLeft2Result(left, MSB32, result, MSB16);
7622 pic16_addSign(result, MSB24, sign);
7624 else if(shCount >= 8){
7627 shiftRLong(left, MSB16, result, sign);
7628 else if(shCount == 0){
7629 movLeft2Result(left, MSB16, result, LSB);
7630 movLeft2Result(left, MSB24, result, MSB16);
7631 movLeft2Result(left, MSB32, result, MSB24);
7632 pic16_addSign(result, MSB32, sign);
7634 else{ //shcount >= 2
7635 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7636 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7637 /* the last shift is signed */
7638 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7639 pic16_addSign(result, MSB32, sign);
7642 else{ /* 1 <= shCount <= 7 */
7644 shiftRLong(left, LSB, result, sign);
7646 shiftRLong(result, LSB, result, sign);
7649 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7650 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7651 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7656 /*-----------------------------------------------------------------*/
7657 /* genRightShiftLiteral - right shifting by known count */
7658 /*-----------------------------------------------------------------*/
7659 static void genRightShiftLiteral (operand *left,
7665 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7668 pic16_freeAsmop(right,NULL,ic,TRUE);
7670 pic16_aopOp(left,ic,FALSE);
7671 pic16_aopOp(result,ic,TRUE);
7673 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7676 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7680 lsize = pic16_getDataSize(left);
7681 res_size = pic16_getDataSize(result);
7682 /* test the LEFT size !!! */
7684 /* I suppose that the left size >= result size */
7686 assert (res_size <= lsize);
7687 while (res_size--) {
7688 pic16_mov2f (AOP(result), AOP(left), res_size);
7690 } else if (shCount >= (lsize * 8)) {
7697 * even for 8-bit operands; result might be an SFR.
7699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7700 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7702 while (res_size--) {
7703 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7705 } else { // unsigned
7706 while (res_size--) {
7707 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7710 } else { // 0 < shCount < 8*lsize
7713 genrshOne (result,left,shCount,sign);
7717 genrshTwo (result,left,shCount,sign);
7721 genrshFour (result,left,shCount,sign);
7728 pic16_freeAsmop(left,NULL,ic,TRUE);
7729 pic16_freeAsmop(result,NULL,ic,TRUE);
7732 /*-----------------------------------------------------------------*/
7733 /* genGenericShift - generates code for left or right shifting */
7734 /*-----------------------------------------------------------------*/
7735 static void genGenericShift (iCode *ic, int isShiftLeft)
7737 operand *left,*right, *result;
7739 int sign, signedCount;
7740 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7741 PIC_OPCODE pos_shift, neg_shift;
7745 right = IC_RIGHT(ic);
7747 result = IC_RESULT(ic);
7749 pic16_aopOp(right,ic,FALSE);
7750 pic16_aopOp(left,ic,FALSE);
7751 pic16_aopOp(result,ic,TRUE);
7753 sign = !SPEC_USIGN(operandType (left));
7754 signedCount = !SPEC_USIGN(operandType (right));
7756 /* if the shift count is known then do it
7757 as efficiently as possible */
7758 if (AOP_TYPE(right) == AOP_LIT) {
7759 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7760 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7761 // we should modify right->aopu.aop_lit here!
7762 // Instead we use abs(shCount) in genXXXShiftLiteral()...
7763 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7765 pic16_genLeftShiftLiteral (left,right,result,ic);
7767 genRightShiftLiteral (left,right,result,ic, sign);
7770 } // if (right is literal)
7772 /* shift count is unknown then we have to form a loop.
7773 * Note: we take only the lower order byte since shifting
7774 * more than 32 bits make no sense anyway, ( the
7775 * largest size of an object can be only 32 bits )
7776 * Note: we perform arithmetic shifts if the left operand is
7777 * signed and we do an (effective) right shift, i. e. we
7778 * shift in the sign bit from the left. */
7780 label_complete = newiTempLabel ( NULL );
7781 label_loop_pos = newiTempLabel ( NULL );
7782 label_loop_neg = NULL;
7783 label_negative = NULL;
7784 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7785 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7788 // additional labels needed
7789 label_loop_neg = newiTempLabel ( NULL );
7790 label_negative = newiTempLabel ( NULL );
7793 // copy source to result -- this will effectively truncate the left operand to the size of result!
7794 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7795 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7796 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7797 pic16_mov2f (AOP(result),AOP(left), offset);
7800 // if result is longer than left, fill with zeros (or sign)
7801 if (AOP_SIZE(left) < AOP_SIZE(result)) {
7802 if (sign && AOP_SIZE(left) > 0) {
7803 // shift signed operand -- fill with sign
7804 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7805 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7806 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7807 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7808 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7811 // shift unsigned operand -- fill result with zeros
7812 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7813 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7816 } // if (size mismatch)
7818 pic16_mov2w (AOP(right), 0);
7819 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7820 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7823 // perform a shift by one (shift count is positive)
7824 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7825 // 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])
7826 pic16_emitpLabel (label_loop_pos->key);
7828 if (sign && (pos_shift == POC_RRCF)) {
7829 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7832 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7833 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7834 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7836 // perform a shift by one (shift count is positive)
7837 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7838 // 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])
7839 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7840 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7842 pic16_emitpLabel (label_loop_pos->key);
7843 if (sign && (pos_shift == POC_RRCF)) {
7844 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7847 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7848 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7849 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7850 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7854 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7856 pic16_emitpLabel (label_negative->key);
7857 // perform a shift by -1 (shift count is negative)
7858 // 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)
7860 pic16_emitpLabel (label_loop_neg->key);
7861 if (sign && (neg_shift == POC_RRCF)) {
7862 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7865 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7866 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7867 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7868 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7869 } // if (signedCount)
7871 pic16_emitpLabel (label_complete->key);
7874 pic16_freeAsmop (right,NULL,ic,TRUE);
7875 pic16_freeAsmop(left,NULL,ic,TRUE);
7876 pic16_freeAsmop(result,NULL,ic,TRUE);
7879 static void genLeftShift (iCode *ic) {
7880 genGenericShift (ic, 1);
7883 static void genRightShift (iCode *ic) {
7884 genGenericShift (ic, 0);
7888 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7889 void pic16_loadFSR0(operand *op, int lit)
7891 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7892 if (AOP_TYPE(op) == AOP_LIT) {
7893 /* handle 12 bit integers correctly */
7894 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7895 if ((val & 0x0fff) != val) {
7896 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7897 val, (val & 0x0fff) );
7900 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7902 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7905 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7906 // set up FSR0 with address of result
7907 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7908 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7912 /*----------------------------------------------------------------*/
7913 /* pic16_derefPtr - move one byte from the location ptr points to */
7914 /* to WREG (doWrite == 0) or one byte from WREG */
7915 /* to the location ptr points to (doWrite != 0) */
7916 /*----------------------------------------------------------------*/
7917 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7919 if (!IS_PTR(operandType(ptr)))
7921 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7922 else pic16_mov2w (AOP(ptr), 0);
7926 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7927 /* We might determine pointer type right here: */
7928 p_type = DCL_TYPE(operandType(ptr));
7933 if (!fsr0_setup || !*fsr0_setup)
7935 pic16_loadFSR0( ptr, 0 );
7936 if (fsr0_setup) *fsr0_setup = 1;
7939 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7941 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7945 if (AOP(ptr)->aopu.aop_reg[2]) {
7946 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7947 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7948 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7949 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7950 pic16_mov2w(AOP(ptr), 2);
7951 pic16_callGenericPointerRW(doWrite, 1);
7953 // data pointer (just 2 byte given)
7954 if (!fsr0_setup || !*fsr0_setup)
7956 pic16_loadFSR0( ptr, 0 );
7957 if (fsr0_setup) *fsr0_setup = 1;
7960 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7962 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7967 assert (0 && "invalid pointer type specified");
7972 /*-----------------------------------------------------------------*/
7973 /* genUnpackBits - generates code for unpacking bits */
7974 /*-----------------------------------------------------------------*/
7975 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7978 sym_link *etype, *letype;
7984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7985 etype = getSpec(operandType(result));
7986 letype = getSpec(operandType(left));
7988 // if(IS_BITFIELD(etype)) {
7989 blen = SPEC_BLEN(etype);
7990 bstr = SPEC_BSTR(etype);
7993 lbstr = SPEC_BSTR( letype );
7995 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7996 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7999 if((blen == 1) && (bstr < 8)
8000 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
8001 /* it is a single bit, so use the appropriate bit instructions */
8002 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
8004 same = pic16_sameRegs(AOP(left),AOP(result));
8005 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
8006 pic16_emitpcode(POC_CLRF, op);
8008 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8009 /* workaround to reduce the extra lfsr instruction */
8010 pic16_emitpcode(POC_BTFSC,
8011 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
8013 assert (PIC_IS_DATA_PTR (operandType(left)));
8014 pic16_loadFSR0 (left, 0);
8015 pic16_emitpcode(POC_BTFSC,
8016 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8019 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8020 /* unsigned bitfields result in either 0 or 1 */
8021 pic16_emitpcode(POC_INCF, op);
8023 /* signed bitfields result in either 0 or -1 */
8024 pic16_emitpcode(POC_DECF, op);
8027 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8030 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8036 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8037 // access symbol directly
8038 pic16_mov2w (AOP(left), 0);
8040 pic16_derefPtr (left, ptype, 0, NULL);
8043 /* if we have bitdisplacement then it fits */
8044 /* into this byte completely or if length is */
8045 /* less than a byte */
8046 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
8048 /* shift right acc */
8051 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8052 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8054 /* VR -- normally I would use the following, but since we use the hack,
8055 * to avoid the masking from AccRsh, why not mask it right now? */
8058 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8061 /* extend signed bitfields to 8 bits */
8062 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8064 assert (blen + bstr > 0);
8065 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8066 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8071 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8075 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8076 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8083 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8085 int size, offset = 0, leoffset=0 ;
8087 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8088 pic16_aopOp(result, ic, TRUE);
8092 size = AOP_SIZE(result);
8093 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8097 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8098 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8099 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8104 if(AOP(left)->aopu.pcop->type == PO_DIR)
8105 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8107 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8110 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8112 // pic16_DumpOp("(result)",result);
8113 if(pic16_isLitAop(AOP(result))) {
8114 pic16_mov2w(AOP(left), offset); // patch 8
8115 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8117 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8118 pic16_popGet(AOP(left), offset), //patch 8
8119 pic16_popGet(AOP(result), offset)));
8127 pic16_freeAsmop(result,NULL,ic,TRUE);
8132 /*-----------------------------------------------------------------*/
8133 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8134 /*-----------------------------------------------------------------*/
8135 static void genNearPointerGet (operand *left,
8139 // asmop *aop = NULL;
8140 //regs *preg = NULL ;
8141 sym_link *rtype, *retype;
8142 sym_link *ltype, *letype;
8146 rtype = operandType(result);
8147 retype= getSpec(rtype);
8148 ltype = operandType(left);
8149 letype= getSpec(ltype);
8151 pic16_aopOp(left,ic,FALSE);
8153 // pic16_DumpOp("(left)",left);
8154 // pic16_DumpOp("(result)",result);
8156 /* if left is rematerialisable and
8157 * result is not bit variable type and
8158 * the left is pointer to data space i.e
8159 * lower 128 bytes of space */
8161 if (AOP_TYPE(left) == AOP_PCODE
8162 && !IS_BITFIELD(retype)
8163 && DCL_TYPE(ltype) == POINTER) {
8165 genDataPointerGet (left,result,ic);
8166 pic16_freeAsmop(left, NULL, ic, TRUE);
8170 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8171 pic16_aopOp (result,ic,TRUE);
8173 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8176 if(IS_BITFIELD( retype )
8177 && (SPEC_BLEN(operandType(result))==1)
8181 int bitstrt, bytestrt;
8183 /* if this is bitfield of size 1, see if we are checking the value
8184 * of a single bit in an if-statement,
8185 * if yes, then don't generate usual code, but execute the
8186 * genIfx directly -- VR */
8190 /* CHECK: if next iCode is IFX
8191 * and current result operand is nextic's conditional operand
8192 * and current result operand live ranges ends at nextic's key number
8194 if((nextic->op == IFX)
8195 && (result == IC_COND(nextic))
8196 && (OP_LIVETO(result) == nextic->seq)
8197 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
8199 /* everything is ok then */
8200 /* find a way to optimize the genIfx iCode */
8202 bytestrt = SPEC_BSTR(operandType(result))/8;
8203 bitstrt = SPEC_BSTR(operandType(result))%8;
8205 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8207 genIfxpCOpJump(nextic, jop);
8209 pic16_freeAsmop(left, NULL, ic, TRUE);
8210 pic16_freeAsmop(result, NULL, ic, TRUE);
8216 /* if bitfield then unpack the bits */
8217 if (IS_BITFIELD(letype))
8218 genUnpackBits (result, left, NULL, POINTER);
8220 /* we have can just get the values */
8221 int size = AOP_SIZE(result);
8224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8226 pic16_loadFSR0( left, 0 );
8230 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8231 pic16_popGet(AOP(result), offset++)));
8233 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8234 pic16_popGet(AOP(result), offset++)));
8240 /* now some housekeeping stuff */
8242 /* we had to allocate for this iCode */
8243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8244 pic16_freeAsmop(NULL,aop,ic,TRUE);
8246 /* we did not allocate which means left
8247 * already in a pointer register, then
8248 * if size > 0 && this could be used again
8249 * we have to point it back to where it
8251 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8252 if (AOP_SIZE(result) > 1
8253 && !OP_SYMBOL(left)->remat
8254 && ( OP_SYMBOL(left)->liveTo > ic->seq
8256 // int size = AOP_SIZE(result) - 1;
8258 // pic16_emitcode("dec","%s",rname);
8264 pic16_freeAsmop(left,NULL,ic,TRUE);
8265 pic16_freeAsmop(result,NULL,ic,TRUE);
8268 /*-----------------------------------------------------------------*/
8269 /* genGenPointerGet - gget value from generic pointer space */
8270 /*-----------------------------------------------------------------*/
8271 static void genGenPointerGet (operand *left,
8272 operand *result, iCode *ic)
8275 sym_link *letype = getSpec(operandType(left));
8277 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8278 pic16_aopOp(left,ic,FALSE);
8279 pic16_aopOp(result,ic,TRUE);
8280 size = AOP_SIZE(result);
8282 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8284 /* if bit then unpack */
8285 if (IS_BITFIELD(letype)) {
8286 genUnpackBits(result,left,"BAD",GPOINTER);
8290 /* set up WREG:PRODL:FSR0L with address from left */
8291 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8292 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8293 pic16_mov2w(AOP(left), 2);
8294 pic16_callGenericPointerRW(0, size);
8296 assignResultValue(result, size, 1);
8299 pic16_freeAsmop(left,NULL,ic,TRUE);
8300 pic16_freeAsmop(result,NULL,ic,TRUE);
8303 /*-----------------------------------------------------------------*/
8304 /* genConstPointerGet - get value from const generic pointer space */
8305 /*-----------------------------------------------------------------*/
8306 static void genConstPointerGet (operand *left,
8307 operand *result, iCode *ic)
8309 //sym_link *retype = getSpec(operandType(result));
8310 // symbol *albl = newiTempLabel(NULL); // patch 15
8311 // symbol *blbl = newiTempLabel(NULL); //
8312 // PIC_OPCODE poc; // patch 15
8316 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8317 pic16_aopOp(left,ic,FALSE);
8318 pic16_aopOp(result,ic,TRUE);
8319 size = AOP_SIZE(result);
8321 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8323 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8325 // set up table pointer
8326 if( (AOP_TYPE(left) == AOP_PCODE)
8327 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8328 || (AOP(left)->aopu.pcop->type == PO_DIR)))
8330 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8331 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8332 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8333 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8334 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8335 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8337 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8338 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8339 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8343 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8344 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8348 pic16_freeAsmop(left,NULL,ic,TRUE);
8349 pic16_freeAsmop(result,NULL,ic,TRUE);
8353 /*-----------------------------------------------------------------*/
8354 /* genPointerGet - generate code for pointer get */
8355 /*-----------------------------------------------------------------*/
8356 static void genPointerGet (iCode *ic)
8358 operand *left, *result ;
8359 sym_link *type, *etype;
8365 result = IC_RESULT(ic) ;
8367 /* depending on the type of pointer we need to
8368 move it to the correct pointer register */
8369 type = operandType(left);
8370 etype = getSpec(type);
8373 if (IS_PTR_CONST(type))
8375 if (IS_CODEPTR(type))
8377 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8379 /* if left is of type of pointer then it is simple */
8380 if (IS_PTR(type) && !IS_FUNC(type->next))
8381 p_type = DCL_TYPE(type);
8383 /* we have to go by the storage class */
8384 p_type = PTR_TYPE(SPEC_OCLS(etype));
8386 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8388 if (SPEC_OCLS(etype)->codesp ) {
8389 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8390 //p_type = CPOINTER ;
8392 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8393 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8394 /*p_type = FPOINTER ;*/
8396 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8397 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8398 /* p_type = PPOINTER; */
8400 if (SPEC_OCLS(etype) == idata ) {
8401 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8402 /* p_type = IPOINTER; */
8404 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8405 /* p_type = POINTER ; */
8409 /* now that we have the pointer type we assign
8410 the pointer values */
8415 genNearPointerGet (left,result,ic);
8419 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8421 genPagedPointerGet(left,result,ic);
8425 genFarPointerGet (left,result,ic);
8430 genConstPointerGet (left,result,ic);
8431 //pic16_emitcodePointerGet (left,result,ic);
8436 if (IS_PTR_CONST(type))
8437 genConstPointerGet (left,result,ic);
8440 genGenPointerGet (left,result,ic);
8444 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8445 "genPointerGet: illegal pointer type");
8450 /*-----------------------------------------------------------------*/
8451 /* genPackBits - generates code for packed bit storage */
8452 /*-----------------------------------------------------------------*/
8453 static void genPackBits (sym_link *etype , operand *result,
8455 char *rname, int p_type)
8461 int shifted_and_masked = 0;
8462 unsigned long lit = (unsigned long)-1;
8465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8466 blen = SPEC_BLEN(etype);
8467 bstr = SPEC_BSTR(etype);
8469 retype = getSpec(operandType(right));
8471 if(AOP_TYPE(right) == AOP_LIT) {
8472 lit = ulFromVal (AOP(right)->aopu.aop_lit);
8474 if((blen == 1) && (bstr < 8)) {
8475 /* it is a single bit, so use the appropriate bit instructions */
8477 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8479 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8480 /* workaround to reduce the extra lfsr instruction */
8482 pic16_emitpcode(POC_BSF,
8483 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8485 pic16_emitpcode(POC_BCF,
8486 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8489 if (PIC_IS_DATA_PTR(operandType(result))) {
8490 pic16_loadFSR0(result, 0);
8491 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8492 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8495 pic16_derefPtr (result, p_type, 0, NULL);
8496 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8497 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8498 /* write back new value */
8499 pic16_derefPtr (result, p_type, 1, NULL);
8505 /* IORLW below is more efficient */
8506 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8507 lit = (lit & ((1UL << blen) - 1)) << bstr;
8508 shifted_and_masked = 1;
8511 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8512 && IS_BITFIELD(retype)
8513 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8517 rblen = SPEC_BLEN( retype );
8518 rbstr = SPEC_BSTR( retype );
8520 if(IS_BITFIELD(etype)) {
8521 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8522 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8524 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8529 if(IS_BITFIELD(etype)) {
8530 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8532 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8539 /* move right to W */
8540 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8543 /* if the bit length is less than or */
8544 /* it exactly fits a byte then */
8545 if((shCnt=SPEC_BSTR(etype))
8546 || SPEC_BLEN(etype) <= 8 ) {
8549 if (blen != 8 || (bstr % 8) != 0) {
8550 // we need to combine the value with the old value
8551 if(!shifted_and_masked)
8553 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8555 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8556 SPEC_BSTR(etype), SPEC_BLEN(etype));
8558 /* shift left acc, do NOT mask the result again */
8561 /* using PRODH as a temporary register here */
8562 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8565 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8566 || IS_DIRECT(result)) {
8567 /* access symbol directly */
8568 pic16_mov2w (AOP(result), 0);
8571 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8574 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8575 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8576 (unsigned char)(0xff >> (8-bstr))) ));
8577 if (!shifted_and_masked) {
8578 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8580 /* We have the shifted and masked (literal) right value in `lit' */
8582 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8584 } else { // if (blen == 8 && (bstr % 8) == 0)
8585 if (shifted_and_masked) {
8586 // move right (literal) to WREG (only case where right is not yet in WREG)
8587 pic16_mov2w(AOP(right), (bstr / 8));
8591 /* write new value back */
8592 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8593 || IS_DIRECT(result)) {
8594 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8596 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8605 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8606 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8611 pic16_loadFSR0(result, 0); // load FSR0 with address of result
8612 rLen = SPEC_BLEN(etype)-8;
8614 /* now generate for lengths greater than one byte */
8618 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8624 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8630 pic16_emitcode("movx","@dptr,a");
8635 DEBUGpic16_emitcode(";lcall","__gptrput");
8643 pic16_mov2w(AOP(right), offset++);
8646 /* last last was not complete */
8648 /* save the byte & read byte */
8651 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8652 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8657 pic16_emitcode ("mov","b,a");
8658 pic16_emitcode("movx","a,@dptr");
8662 pic16_emitcode ("push","b");
8663 pic16_emitcode ("push","acc");
8664 pic16_emitcode ("lcall","__gptrget");
8665 pic16_emitcode ("pop","b");
8671 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8672 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8673 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8674 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8675 // pic16_emitcode ("orl","a,b");
8678 // if (p_type == GPOINTER)
8679 // pic16_emitcode("pop","b");
8684 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8685 // pic16_emitcode("mov","@%s,a",rname);
8689 pic16_emitcode("movx","@dptr,a");
8693 DEBUGpic16_emitcode(";lcall","__gptrput");
8700 // pic16_freeAsmop(right, NULL, ic, TRUE);
8703 /*-----------------------------------------------------------------*/
8704 /* genDataPointerSet - remat pointer to data space */
8705 /*-----------------------------------------------------------------*/
8706 static void genDataPointerSet(operand *right,
8710 int size, offset = 0, resoffset=0 ;
8712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8713 pic16_aopOp(right,ic,FALSE);
8715 size = AOP_SIZE(right);
8717 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8720 if ( AOP_TYPE(result) == AOP_PCODE) {
8721 fprintf(stderr,"genDataPointerSet %s, %d\n",
8722 AOP(result)->aopu.pcop->name,
8723 (AOP(result)->aopu.pcop->type == PO_DIR)?
8724 PCOR(AOP(result)->aopu.pcop)->instance:
8725 PCOI(AOP(result)->aopu.pcop)->offset);
8729 if(AOP(result)->aopu.pcop->type == PO_DIR)
8730 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8733 if (AOP_TYPE(right) == AOP_LIT) {
8734 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8735 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8737 pic16_mov2w(AOP(right), offset);
8738 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8744 pic16_freeAsmop(right,NULL,ic,TRUE);
8749 /*-----------------------------------------------------------------*/
8750 /* genNearPointerSet - pic16_emitcode for near pointer put */
8751 /*-----------------------------------------------------------------*/
8752 static void genNearPointerSet (operand *right,
8758 sym_link *ptype = operandType(result);
8761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8762 retype= getSpec(operandType(right));
8763 resetype = getSpec(operandType(result));
8765 pic16_aopOp(result,ic,FALSE);
8767 /* if the result is rematerializable &
8768 * in data space & not a bit variable */
8770 /* and result is not a bit variable */
8771 if (AOP_TYPE(result) == AOP_PCODE
8772 && DCL_TYPE(ptype) == POINTER
8773 && !IS_BITFIELD(retype)
8774 && !IS_BITFIELD(resetype)) {
8776 genDataPointerSet (right,result,ic);
8777 pic16_freeAsmop(result,NULL,ic,TRUE);
8781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8782 pic16_aopOp(right,ic,FALSE);
8783 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8785 /* if bitfield then unpack the bits */
8786 if (IS_BITFIELD(resetype)) {
8787 genPackBits (resetype, result, right, NULL, POINTER);
8789 /* we have can just get the values */
8790 int size = AOP_SIZE(right);
8793 pic16_loadFSR0(result, 0);
8795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8797 if (pic16_isLitOp(right)) {
8798 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8800 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8802 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8804 } else { // no literal
8806 pic16_emitpcode(POC_MOVFF,
8807 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8808 pic16_popCopyReg(&pic16_pc_postinc0)));
8810 pic16_emitpcode(POC_MOVFF,
8811 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8812 pic16_popCopyReg(&pic16_pc_indf0)));
8820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8821 /* now some housekeeping stuff */
8823 /* we had to allocate for this iCode */
8824 pic16_freeAsmop(NULL,aop,ic,TRUE);
8826 /* we did not allocate which means left
8827 * already in a pointer register, then
8828 * if size > 0 && this could be used again
8829 * we have to point it back to where it
8831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8832 if (AOP_SIZE(right) > 1
8833 && !OP_SYMBOL(result)->remat
8834 && ( OP_SYMBOL(result)->liveTo > ic->seq
8837 int size = AOP_SIZE(right) - 1;
8840 pic16_emitcode("decf","fsr0,f");
8841 //pic16_emitcode("dec","%s",rname);
8845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8848 pic16_freeAsmop(right,NULL,ic,TRUE);
8849 pic16_freeAsmop(result,NULL,ic,TRUE);
8852 /*-----------------------------------------------------------------*/
8853 /* genGenPointerSet - set value from generic pointer space */
8854 /*-----------------------------------------------------------------*/
8855 static void genGenPointerSet (operand *right,
8856 operand *result, iCode *ic)
8859 sym_link *retype = getSpec(operandType(result));
8861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8863 pic16_aopOp(result,ic,FALSE);
8864 pic16_aopOp(right,ic,FALSE);
8865 size = AOP_SIZE(right);
8867 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8870 /* if bit then unpack */
8871 if (IS_BITFIELD(retype)) {
8872 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8873 genPackBits(retype,result,right,"dptr",GPOINTER);
8877 size = AOP_SIZE(right);
8879 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
8882 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8884 /* value of right+0 is placed on stack, which will be retrieved
8885 * by the support function thus restoring the stack. The important
8886 * thing is that there is no need to manually restore stack pointer
8888 pushaop(AOP(right), 0);
8889 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8890 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8891 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8892 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8894 /* load address to write to in WREG:FSR0H:FSR0L */
8895 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8896 pic16_popCopyReg(&pic16_pc_fsr0l)));
8897 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8898 pic16_popCopyReg(&pic16_pc_prodl)));
8899 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8901 pic16_callGenericPointerRW(1, size);
8904 pic16_freeAsmop(right,NULL,ic,TRUE);
8905 pic16_freeAsmop(result,NULL,ic,TRUE);
8908 /*-----------------------------------------------------------------*/
8909 /* genPointerSet - stores the value into a pointer location */
8910 /*-----------------------------------------------------------------*/
8911 static void genPointerSet (iCode *ic)
8913 operand *right, *result ;
8914 sym_link *type, *etype;
8919 right = IC_RIGHT(ic);
8920 result = IC_RESULT(ic) ;
8922 /* depending on the type of pointer we need to
8923 move it to the correct pointer register */
8924 type = operandType(result);
8925 etype = getSpec(type);
8927 /* if left is of type of pointer then it is simple */
8928 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8929 p_type = DCL_TYPE(type);
8932 /* we have to go by the storage class */
8933 p_type = PTR_TYPE(SPEC_OCLS(etype));
8935 /* if (SPEC_OCLS(etype)->codesp ) { */
8936 /* p_type = CPOINTER ; */
8939 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8940 /* p_type = FPOINTER ; */
8942 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8943 /* p_type = PPOINTER ; */
8945 /* if (SPEC_OCLS(etype) == idata ) */
8946 /* p_type = IPOINTER ; */
8948 /* p_type = POINTER ; */
8951 /* now that we have the pointer type we assign
8952 the pointer values */
8957 genNearPointerSet (right,result,ic);
8961 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8963 genPagedPointerSet (right,result,ic);
8967 genFarPointerSet (right,result,ic);
8972 genGenPointerSet (right,result,ic);
8976 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8977 "genPointerSet: illegal pointer type");
8981 /*-----------------------------------------------------------------*/
8982 /* genIfx - generate code for Ifx statement */
8983 /*-----------------------------------------------------------------*/
8984 static void genIfx (iCode *ic, iCode *popIc)
8986 operand *cond = IC_COND(ic);
8991 pic16_aopOp(cond,ic,FALSE);
8993 /* get the value into acc */
8994 if (AOP_TYPE(cond) != AOP_CRY)
8995 pic16_toBoolean(cond);
8998 /* the result is now in the accumulator */
8999 pic16_freeAsmop(cond,NULL,ic,TRUE);
9001 /* if there was something to be popped then do it */
9005 /* if the condition is a bit variable */
9006 if (isbit && IS_ITEMP(cond) &&
9009 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9011 if (isbit && !IS_ITEMP(cond))
9012 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9019 /*-----------------------------------------------------------------*/
9020 /* genAddrOf - generates code for address of */
9021 /*-----------------------------------------------------------------*/
9022 static void genAddrOf (iCode *ic)
9024 operand *result, *left;
9026 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
9027 pCodeOp *pcop0, *pcop1, *pcop2;
9031 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9033 sym = OP_SYMBOL( IC_LEFT(ic) );
9036 /* get address of symbol on stack */
9037 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9039 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9040 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9043 // operands on stack are accessible via "FSR2 + index" with index
9044 // starting at 2 for arguments and growing from 0 downwards for
9045 // local variables (index == 0 is not assigned so we add one here)
9047 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9054 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9055 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9056 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9057 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9058 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9059 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9060 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9066 // if(pic16_debug_verbose) {
9067 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9068 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9071 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9072 size = AOP_SIZE(IC_RESULT(ic));
9074 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9075 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9076 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9079 pic16_emitpcode(POC_MOVLW, pcop0);
9080 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9081 pic16_emitpcode(POC_MOVLW, pcop1);
9082 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9083 pic16_emitpcode(POC_MOVLW, pcop2);
9084 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9087 pic16_emitpcode(POC_MOVLW, pcop0);
9088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9089 pic16_emitpcode(POC_MOVLW, pcop1);
9090 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9092 pic16_emitpcode(POC_MOVLW, pcop0);
9093 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9096 pic16_freeAsmop(left, NULL, ic, FALSE);
9098 pic16_freeAsmop(result,NULL,ic,TRUE);
9102 /*-----------------------------------------------------------------*/
9103 /* genAssign - generate code for assignment */
9104 /*-----------------------------------------------------------------*/
9105 static void genAssign (iCode *ic)
9107 operand *result, *right;
9108 sym_link *restype, *rtype;
9109 int size, offset,know_W;
9110 unsigned long lit = 0L;
9112 result = IC_RESULT(ic);
9113 right = IC_RIGHT(ic) ;
9117 /* if they are the same */
9118 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9121 /* reversed order operands are aopOp'ed so that result operand
9122 * is effective in case right is a stack symbol. This maneauver
9123 * allows to use the _G.resDirect flag later */
9124 pic16_aopOp(result,ic,TRUE);
9125 pic16_aopOp(right,ic,FALSE);
9127 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9129 /* if they are the same registers */
9130 if (pic16_sameRegs(AOP(right),AOP(result)))
9133 /* if the result is a bit */
9134 if (AOP_TYPE(result) == AOP_CRY) {
9135 /* if the right size is a literal then
9136 we know what the value is */
9137 if (AOP_TYPE(right) == AOP_LIT) {
9139 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9140 pic16_popGet(AOP(result),0));
9142 if (((int) operandLitValue(right)))
9143 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9144 AOP(result)->aopu.aop_dir,
9145 AOP(result)->aopu.aop_dir);
9147 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9148 AOP(result)->aopu.aop_dir,
9149 AOP(result)->aopu.aop_dir);
9154 /* the right is also a bit variable */
9155 if (AOP_TYPE(right) == AOP_CRY) {
9156 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9157 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9158 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9164 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9165 pic16_toBoolean(right);
9167 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9168 //pic16_aopPut(AOP(result),"a",0);
9172 /* bit variables done */
9174 size = AOP_SIZE(result);
9177 /* bit variables done */
9179 size = AOP_SIZE(result);
9180 restype = operandType(result);
9181 rtype = operandType(right);
9184 if(AOP_TYPE(right) == AOP_LIT) {
9185 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9187 lit = ulFromVal (AOP(right)->aopu.aop_lit);
9189 /* patch tag for literals that are cast to pointers */
9190 if (IS_CODEPTR(restype)) {
9191 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9192 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9194 if (IS_GENPTR(restype))
9196 if (IS_CODEPTR(rtype)) {
9197 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9198 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9199 } else if (PIC_IS_DATA_PTR(rtype)) {
9200 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9201 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9202 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9203 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9204 } else if (IS_PTR(rtype)) {
9205 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9206 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9212 unsigned long lit_int;
9217 if(IS_FIXED16X16(operandType(right))) {
9218 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9220 /* take care if literal is a float */
9221 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9227 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9228 // sizeof(unsigned long int), sizeof(float));
9231 if (AOP_TYPE(right) == AOP_REG) {
9232 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9234 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9239 /* when do we have to read the program memory?
9240 * - if right itself is a symbol in code space
9241 * (we don't care what it points to if it's a pointer)
9242 * - AND right is not a function (we would want its address)
9244 if(AOP_TYPE(right) != AOP_LIT
9245 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9246 && !IS_FUNC(OP_SYM_TYPE(right))
9247 && !IS_ITEMP(right)) {
9249 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9250 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9252 // set up table pointer
9253 if(pic16_isLitOp(right)) {
9254 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9255 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9256 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9257 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9258 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9259 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9260 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9262 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9263 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9264 pic16_popCopyReg(&pic16_pc_tblptrl)));
9265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9266 pic16_popCopyReg(&pic16_pc_tblptrh)));
9267 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9268 pic16_popCopyReg(&pic16_pc_tblptru)));
9271 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9272 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9274 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9275 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9276 pic16_popGet(AOP(result),offset)));
9280 /* FIXME: for pointers we need to extend differently (according
9281 * to pointer type DATA/CODE/EEPROM/... :*/
9282 size = getSize(OP_SYM_TYPE(right));
9283 if(AOP_SIZE(result) > size) {
9284 size = AOP_SIZE(result) - size;
9286 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9294 /* VR - What is this?! */
9295 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9296 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9298 if(aopIdx(AOP(result),0) == 4) {
9299 /* this is a workaround to save value of right into wreg too,
9300 * value of wreg is going to be used later */
9301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9302 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9303 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9307 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9311 size = AOP_SIZE(right);
9312 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9315 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
9316 if(AOP_TYPE(right) == AOP_LIT) {
9318 if(know_W != (lit&0xff))
9319 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9321 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9323 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9327 } else if (AOP_TYPE(right) == AOP_CRY) {
9328 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9330 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9331 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9332 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9334 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9335 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9340 if(!_G.resDirect) { /* use this aopForSym feature */
9341 if(AOP_TYPE(result) == AOP_ACC) {
9342 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9344 if(AOP_TYPE(right) == AOP_ACC) {
9345 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9347 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9354 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9357 pic16_freeAsmop (right,NULL,ic,FALSE);
9358 pic16_freeAsmop (result,NULL,ic,TRUE);
9361 /*-----------------------------------------------------------------*/
9362 /* genJumpTab - generates code for jump table */
9363 /*-----------------------------------------------------------------*/
9364 static void genJumpTab (iCode *ic)
9369 pCodeOp *jt_offs_hi;
9374 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9375 /* get the condition into accumulator */
9376 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9378 /* multiply by three */
9379 pic16_emitcode("add","a,acc");
9380 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9382 jtab = newiTempLabel(NULL);
9383 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9384 pic16_emitcode("jmp","@a+dptr");
9385 pic16_emitcode("","%05d_DS_:",jtab->key+100);
9388 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9389 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9391 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9392 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9393 pic16_emitpLabel(jtab->key);
9397 jt_offs = pic16_popGetTempReg(0);
9398 jt_offs_hi = pic16_popGetTempReg(1);
9399 jt_label = pic16_popGetLabel (jtab->key);
9400 //fprintf (stderr, "Creating jump table...\n");
9402 // calculate offset into jump table (idx * sizeof (GOTO))
9403 pic16_emitpcode(POC_CLRF , jt_offs_hi);
9404 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9405 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9406 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9407 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9408 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9409 pic16_emitpcode(POC_MOVWF , jt_offs);
9411 // prepare PCLATx (set to first entry in jump table)
9412 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9413 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9414 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9415 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9416 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9418 // set PCLATx to selected entry (new PCL is stored in jt_offs)
9419 pic16_emitpcode(POC_ADDWF , jt_offs);
9420 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9421 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9423 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
9425 // release temporaries and prepare jump into table (new PCL --> WREG)
9426 pic16_emitpcode(POC_MOVFW , jt_offs);
9427 pic16_popReleaseTempReg (jt_offs_hi, 1);
9428 pic16_popReleaseTempReg (jt_offs, 0);
9430 // jump into the table
9431 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9433 pic16_emitpLabelFORCE(jtab->key);
9436 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9437 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9439 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9440 /* now generate the jump labels */
9441 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9442 jtab = setNextItem(IC_JTLABELS(ic))) {
9443 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9444 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9447 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9451 /*-----------------------------------------------------------------*/
9452 /* genMixedOperation - gen code for operators between mixed types */
9453 /*-----------------------------------------------------------------*/
9455 TSD - Written for the PIC port - but this unfortunately is buggy.
9456 This routine is good in that it is able to efficiently promote
9457 types to different (larger) sizes. Unfortunately, the temporary
9458 variables that are optimized out by this routine are sometimes
9459 used in other places. So until I know how to really parse the
9460 iCode tree, I'm going to not be using this routine :(.
9462 static int genMixedOperation (iCode *ic)
9465 operand *result = IC_RESULT(ic);
9466 sym_link *ctype = operandType(IC_LEFT(ic));
9467 operand *right = IC_RIGHT(ic);
9473 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9475 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9481 nextright = IC_RIGHT(nextic);
9482 nextleft = IC_LEFT(nextic);
9483 nextresult = IC_RESULT(nextic);
9485 pic16_aopOp(right,ic,FALSE);
9486 pic16_aopOp(result,ic,FALSE);
9487 pic16_aopOp(nextright, nextic, FALSE);
9488 pic16_aopOp(nextleft, nextic, FALSE);
9489 pic16_aopOp(nextresult, nextic, FALSE);
9491 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9497 pic16_emitcode(";remove right +","");
9499 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9505 pic16_emitcode(";remove left +","");
9509 big = AOP_SIZE(nextleft);
9510 small = AOP_SIZE(nextright);
9512 switch(nextic->op) {
9515 pic16_emitcode(";optimize a +","");
9516 /* if unsigned or not an integral type */
9517 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9518 pic16_emitcode(";add a bit to something","");
9521 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9523 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9524 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9525 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9527 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9535 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9536 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9537 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9540 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9542 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9543 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9544 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9545 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9546 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9549 pic16_emitcode("rlf","known_zero,w");
9556 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9557 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9558 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9560 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9570 pic16_freeAsmop(right,NULL,ic,TRUE);
9571 pic16_freeAsmop(result,NULL,ic,TRUE);
9572 pic16_freeAsmop(nextright,NULL,ic,TRUE);
9573 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9575 nextic->generated = 1;
9582 /*-----------------------------------------------------------------*/
9583 /* genCast - gen code for casting */
9584 /*-----------------------------------------------------------------*/
9585 static void genCast (iCode *ic)
9587 operand *result = IC_RESULT(ic);
9588 sym_link *ctype = operandType(IC_LEFT(ic));
9589 sym_link *rtype = operandType(IC_RIGHT(ic));
9590 sym_link *restype = operandType(IC_RESULT(ic));
9591 operand *right = IC_RIGHT(ic);
9597 /* if they are equivalent then do nothing */
9598 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9601 pic16_aopOp(result,ic,FALSE);
9602 pic16_aopOp(right,ic,FALSE) ;
9604 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9607 /* if the result is a bit */
9608 if (AOP_TYPE(result) == AOP_CRY) {
9610 /* if the right size is a literal then
9611 * we know what the value is */
9612 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9614 if (AOP_TYPE(right) == AOP_LIT) {
9615 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9616 pic16_popGet(AOP(result),0));
9618 if (((int) operandLitValue(right)))
9619 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9620 AOP(result)->aopu.aop_dir,
9621 AOP(result)->aopu.aop_dir);
9623 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9624 AOP(result)->aopu.aop_dir,
9625 AOP(result)->aopu.aop_dir);
9629 /* the right is also a bit variable */
9630 if (AOP_TYPE(right) == AOP_CRY) {
9632 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9634 pic16_emitcode("clrc","");
9635 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9636 AOP(right)->aopu.aop_dir,
9637 AOP(right)->aopu.aop_dir);
9638 pic16_aopPut(AOP(result),"c",0);
9643 if (AOP_TYPE(right) == AOP_REG) {
9644 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9645 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9646 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9648 pic16_toBoolean(right);
9649 pic16_aopPut(AOP(result),"a",0);
9653 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9656 size = AOP_SIZE(result);
9658 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9660 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9661 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9662 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9665 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9670 if(IS_BITFIELD(getSpec(restype))
9671 && IS_BITFIELD(getSpec(rtype))) {
9672 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9675 /* port from pic14 to cope with generic pointers */
9676 if (PIC_IS_TAGGED(restype))
9678 operand *result = IC_RESULT(ic);
9679 //operand *left = IC_LEFT(ic);
9680 operand *right = IC_RIGHT(ic);
9683 /* copy common part */
9684 int max, size = AOP_SIZE(result);
9685 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9686 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9691 pic16_mov2w (AOP(right), size);
9692 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9695 /* upcast into generic pointer type? */
9696 if (IS_GENPTR(restype)
9697 && !PIC_IS_TAGGED(rtype)
9698 && (AOP_SIZE(result) > max))
9700 /* determine appropriate tag for right */
9701 if (PIC_IS_DATA_PTR(rtype))
9702 tag = GPTR_TAG_DATA;
9703 else if (IS_CODEPTR(rtype))
9704 tag = GPTR_TAG_CODE;
9705 else if (PIC_IS_DATA_PTR(ctype)) {
9706 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9707 tag = GPTR_TAG_DATA;
9708 } else if (IS_CODEPTR(ctype)) {
9709 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9710 tag = GPTR_TAG_CODE;
9711 } else if (IS_PTR(rtype)) {
9712 PERFORM_ONCE(weirdcast,
9713 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9715 tag = GPTR_TAG_DATA;
9717 PERFORM_ONCE(weirdcast,
9718 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9720 tag = GPTR_TAG_DATA;
9723 assert (AOP_SIZE(result) == 3);
9724 /* zero-extend address... */
9725 for (size = max; size < AOP_SIZE(result)-1; size++)
9726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9727 /* ...and add tag */
9728 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9729 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9730 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9731 for (size = max; size < AOP_SIZE(result)-1; size++)
9732 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9733 /* add __code tag */
9734 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9735 } else if (AOP_SIZE(result) > max) {
9736 /* extend non-pointers */
9737 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9738 pic16_addSign(result, max, 0);
9743 /* if they are the same size : or less */
9744 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9746 /* if they are in the same place */
9747 if (pic16_sameRegs(AOP(right),AOP(result)))
9750 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9752 if (IS_PTR_CONST(rtype))
9754 if (IS_CODEPTR(rtype))
9756 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9759 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9761 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9763 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9765 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9766 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9767 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9769 if(AOP_SIZE(result) < 2) {
9770 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9772 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9776 /* if they in different places then copy */
9777 size = AOP_SIZE(result);
9780 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9788 /* if the result is of type pointer */
9789 if (IS_PTR(ctype)) {
9791 sym_link *type = operandType(right);
9792 sym_link *etype = getSpec(type);
9794 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
9796 /* pointer to generic pointer */
9797 if (IS_GENPTR(ctype)) {
9801 p_type = DCL_TYPE(type);
9803 /* we have to go by the storage class */
9804 p_type = PTR_TYPE(SPEC_OCLS(etype));
9806 /* if (SPEC_OCLS(etype)->codesp ) */
9807 /* p_type = CPOINTER ; */
9809 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9810 /* p_type = FPOINTER ; */
9812 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9813 /* p_type = PPOINTER; */
9815 /* if (SPEC_OCLS(etype) == idata ) */
9816 /* p_type = IPOINTER ; */
9818 /* p_type = POINTER ; */
9821 /* the first two bytes are known */
9822 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
9823 size = GPTRSIZE - 1;
9826 if(offset < AOP_SIZE(right)) {
9827 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9828 pic16_mov2f(AOP(result), AOP(right), offset);
9830 if ((AOP_TYPE(right) == AOP_PCODE) &&
9831 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9832 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9833 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9836 pic16_aopPut(AOP(result),
9837 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9842 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9845 /* the last byte depending on type */
9850 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9854 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9858 pic16_emitcode(";BUG!? ","%d",__LINE__);
9863 if (GPTRSIZE > AOP_SIZE(right)) {
9864 // assume __data pointer... THIS MIGHT BE WRONG!
9865 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9867 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9872 /* this should never happen */
9873 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9874 "got unknown pointer type");
9877 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9883 /* just copy the pointers */
9884 size = AOP_SIZE(result);
9887 pic16_aopPut(AOP(result),
9888 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9897 /* so we now know that the size of destination is greater
9898 than the size of the source.
9899 Now, if the next iCode is an operator then we might be
9900 able to optimize the operation without performing a cast.
9902 if(genMixedOperation(ic))
9905 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9907 /* we move to result for the size of source */
9908 size = AOP_SIZE(right);
9913 pic16_mov2f(AOP(result), AOP(right), offset);
9917 /* now depending on the sign of the destination */
9918 size = AOP_SIZE(result) - AOP_SIZE(right);
9919 /* if unsigned or not an integral type */
9920 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9922 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9924 /* we need to extend the sign :( */
9927 /* Save one instruction of casting char to int */
9928 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9929 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9930 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
9932 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9935 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9937 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9939 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
9947 pic16_freeAsmop(right,NULL,ic,TRUE);
9948 pic16_freeAsmop(result,NULL,ic,TRUE);
9952 /*-----------------------------------------------------------------*/
9953 /* genDjnz - generate decrement & jump if not zero instrucion */
9954 /*-----------------------------------------------------------------*/
9955 static int genDjnz (iCode *ic, iCode *ifx)
9958 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9963 /* if the if condition has a false label
9964 then we cannot save */
9968 /* if the minus is not of the form
9970 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9971 !IS_OP_LITERAL(IC_RIGHT(ic)))
9974 if (operandLitValue(IC_RIGHT(ic)) != 1)
9977 /* if the size of this greater than one then no
9979 if (getSize(operandType(IC_RESULT(ic))) > 1)
9982 /* otherwise we can save BIG */
9983 lbl = newiTempLabel(NULL);
9984 lbl1= newiTempLabel(NULL);
9986 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9988 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9989 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9991 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9996 /*-----------------------------------------------------------------*/
9997 /* genReceive - generate code for a receive iCode */
9998 /*-----------------------------------------------------------------*/
9999 static void genReceive (iCode *ic)
10005 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
10006 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
10008 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
10010 if (isOperandInFarSpace(IC_RESULT(ic))
10011 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
10012 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10014 int size = getSize(operandType(IC_RESULT(ic)));
10015 int offset = pic16_fReturnSizePic - size;
10019 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10020 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10024 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10026 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10027 size = AOP_SIZE(IC_RESULT(ic));
10030 pic16_emitcode ("pop","acc");
10031 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10034 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10036 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10039 /* set pseudo stack pointer to where it should be - dw*/
10040 GpsuedoStkPtr = ic->parmBytes;
10042 /* setting GpsuedoStkPtr has side effects here: */
10043 /* FIXME: What's the correct size of the return(ed) value?
10044 * For now, assuming '4' as before... */
10045 assignResultValue(IC_RESULT(ic), 4, 0);
10048 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10051 /*-----------------------------------------------------------------*/
10052 /* genDummyRead - generate code for dummy read of volatiles */
10053 /*-----------------------------------------------------------------*/
10055 genDummyRead (iCode * ic)
10060 if (op && IS_SYMOP(op)) {
10061 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10062 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10065 pic16_aopOp (op, ic, FALSE);
10066 pic16_mov2w_volatile(AOP(op));
10067 pic16_freeAsmop (op, NULL, ic, TRUE);
10069 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10073 /*-----------------------------------------------------------------*/
10074 /* genpic16Code - generate code for pic16 based controllers */
10075 /*-----------------------------------------------------------------*/
10077 * At this point, ralloc.c has gone through the iCode and attempted
10078 * to optimize in a way suitable for a PIC. Now we've got to generate
10079 * PIC instructions that correspond to the iCode.
10081 * Once the instructions are generated, we'll pass through both the
10082 * peep hole optimizer and the pCode optimizer.
10083 *-----------------------------------------------------------------*/
10085 void genpic16Code (iCode *lic)
10090 lineHead = lineCurr = NULL;
10092 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10093 pic16_addpBlock(pb);
10096 /* if debug information required */
10097 if (options.debug && currFunc) {
10099 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10104 for (ic = lic ; ic ; ic = ic->next ) {
10106 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10107 if ( cln != ic->lineno ) {
10108 if ( options.debug ) {
10109 debugFile->writeCLine (ic);
10112 if(!options.noCcodeInAsm) {
10113 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10114 printCLine(ic->filename, ic->lineno)));
10120 if(options.iCodeInAsm) {
10123 /* insert here code to print iCode as comment */
10124 iLine = printILine(ic);
10125 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10129 /* if the result is marked as
10130 * spilt and rematerializable or code for
10131 * this has already been generated then
10133 if (resultRemat(ic) || ic->generated )
10136 /* depending on the operation */
10155 /* IPOP happens only when trying to restore a
10156 * spilt live range, if there is an ifx statement
10157 * following this pop then the if statement might
10158 * be using some of the registers being popped which
10159 * would destroy the contents of the register so
10160 * we need to check for this condition and handle it */
10162 && ic->next->op == IFX
10163 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10164 genIfx (ic->next,ic);
10182 genEndFunction (ic);
10198 pic16_genPlus (ic) ;
10202 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10203 pic16_genMinus (ic);
10219 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10223 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10229 /* note these two are xlated by algebraic equivalence
10230 * during parsing SDCC.y */
10231 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10232 "got '>=' or '<=' shouldn't have come here");
10236 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10248 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10252 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10256 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10280 genRightShift (ic);
10283 case GET_VALUE_AT_ADDRESS:
10288 if (POINTER_SET(ic))
10315 addSet(&_G.sendSet,ic);
10318 case DUMMY_READ_VOLATILE:
10328 /* now we are ready to call the
10329 peep hole optimizer */
10330 if (!options.nopeep)
10331 peepHole (&lineHead);
10333 /* now do the actual printing */
10334 printLine (lineHead, codeOutBuf);
10337 DFPRINTF((stderr,"printing pBlock\n\n"));
10338 pic16_printpBlock(stdout,pb);