1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10 Bug Fixes - Raphael Neider <rneider AT web.de> (2004,2005)
11 Bug Fixes - Borut Razem <borut.razem AT siol.net> (2007)
13 This program is free software; you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by the
15 Free Software Foundation; either version 2, or (at your option) any
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 In other words, you are welcome to use, share and improve this program.
28 You are forbidden to forbid anyone else to use, share and improve
29 what you give them. Help stamp out software-hoarding!
32 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
33 Made everything static
34 -------------------------------------------------------------------------*/
40 #include "SDCCglobl.h"
44 #include "SDCCpeeph.h"
53 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
54 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
55 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
57 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
59 /* If you change these, you also have to update the library files
60 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
61 #define GPTR_TAG_DATA 0x80
62 #define GPTR_TAG_EEPROM 0x40
63 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
65 /* Wrapper to execute `code' at most once. */
66 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
68 void pic16_genMult8X8_n (operand *, operand *,operand *);
69 extern void pic16_printpBlock(FILE *of, pBlock *pb);
70 static asmop *newAsmop (short type);
71 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
72 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
73 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
74 static pCodeOp *pic16_popRegFromIdx(int rIdx);
76 int pic16_labelOffset=0;
77 extern int pic16_debug_verbose;
81 /* max_key keeps track of the largest label number used in
82 a function. This is then used to adjust the label offset
83 for the next function.
86 static int GpsuedoStkPtr=0;
88 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
90 const char *pic16_AopType(short type);
91 static iCode *ifxForOp ( operand *op, iCode *ic );
93 void pic16_pushpCodeOp(pCodeOp *pcop);
94 void pic16_poppCodeOp(pCodeOp *pcop);
97 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
99 /* set the following macro to 1 to enable passing the
100 * first byte of functions parameters via WREG */
101 #define USE_WREG_IN_FUNC_PARAMS 0
104 /* this is the down and dirty file with all kinds of
105 kludgy & hacky stuff. This is what it is all about
106 CODE GENERATION for a specific MCU . some of the
107 routines may be reusable, will have to see */
108 static char *zero = "#0x00";
109 static char *one = "#0x01";
113 * Function return value policy (MSB-->LSB):
115 * 16 bits -> PRODL:WREG
116 * 24 bits -> PRODH:PRODL:WREG
117 * 32 bits -> FSR0L:PRODH:PRODL:WREG
118 * >32 bits -> on stack, and FSR0 points to the beginning
120 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
121 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
122 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
123 static char **fReturn = fReturnpic16;
125 static char *accUse[] = {"WREG"};
135 bitVect *fregsUsed; /* registers used in function */
137 set *sregsAllocSet; /* registers used to store stack variables */
138 int stack_lat; /* stack offset latency */
140 int useWreg; /* flag when WREG is used to pass function parameter */
143 extern struct dbuf_s *codeOutBuf;
145 static lineNode *lineHead = NULL;
146 static lineNode *lineCurr = NULL;
148 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
149 0xE0, 0xC0, 0x80, 0x00};
150 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
151 0x07, 0x03, 0x01, 0x00};
155 /*-----------------------------------------------------------------*/
156 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
157 /* exponent of 2 is returned, otherwise -1 is */
159 /* note that this is similar to the function `powof2' in SDCCsymt */
163 /*-----------------------------------------------------------------*/
164 int pic16_my_powof2 (unsigned long num)
167 if( (num & (num-1)) == 0) {
180 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
182 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
184 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
185 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
186 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
187 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
188 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
189 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
190 ((result) ? AOP_SIZE(result) : 0));
193 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
196 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
198 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
199 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
200 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
201 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
202 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
203 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
207 void pic16_emitpcomment (char *fmt, ...)
210 char lb[INITIAL_INLINEASM];
211 unsigned char *lbp = (unsigned char *)lb;
216 vsprintf(lb+1,fmt,ap);
218 while (isspace(*lbp)) lbp++;
221 lineCurr = (lineCurr ?
222 connectLine(lineCurr,newLineNode(lb)) :
223 (lineHead = newLineNode(lb)));
224 lineCurr->isInline = _G.inLine;
225 lineCurr->isDebug = _G.debugLine;
226 lineCurr->isComment = 1;
228 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
231 // fprintf(stderr, "%s\n", lb);
234 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
237 char lb[INITIAL_INLINEASM];
238 unsigned char *lbp = (unsigned char *)lb;
240 if(!pic16_debug_verbose)
247 sprintf(lb,"%s\t",inst);
249 sprintf(lb,"%s",inst);
250 vsprintf(lb+(strlen(lb)),fmt,ap);
254 while (isspace(*lbp)) lbp++;
257 lineCurr = (lineCurr ?
258 connectLine(lineCurr,newLineNode(lb)) :
259 (lineHead = newLineNode(lb)));
260 lineCurr->isInline = _G.inLine;
261 lineCurr->isDebug = _G.debugLine;
263 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
266 // fprintf(stderr, "%s\n", lb);
271 void pic16_emitpLabel(int key)
273 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
276 void pic16_emitpLabelFORCE(int key)
278 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
281 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
282 * NEVER call pic16_emitpcode_real directly, please... */
283 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
287 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
289 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
292 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
295 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
297 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
300 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
303 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
309 #define pic16_emitcode DEBUGpic16_emitcode
311 /*-----------------------------------------------------------------*/
312 /* pic16_emitcode - writes the code into a file : for now it is simple */
313 /*-----------------------------------------------------------------*/
314 void pic16_emitcode (char *inst,char *fmt, ...)
317 char lb[INITIAL_INLINEASM];
318 unsigned char *lbp = lb;
324 sprintf(lb,"%s\t",inst);
326 sprintf(lb,"%s",inst);
327 vsprintf(lb+(strlen(lb)),fmt,ap);
331 while (isspace(*lbp)) lbp++;
334 lineCurr = (lineCurr ?
335 connectLine(lineCurr,newLineNode(lb)) :
336 (lineHead = newLineNode(lb)));
337 lineCurr->isInline = _G.inLine;
338 lineCurr->isDebug = _G.debugLine;
339 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
340 lineCurr->isComment = (*lbp == ';');
342 // VR fprintf(stderr, "lb = <%s>\n", lbp);
344 // if(pic16_debug_verbose)
345 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
352 /*-----------------------------------------------------------------*/
353 /* pic16_emitDebuggerSymbol - associate the current code location */
354 /* with a debugger symbol */
355 /*-----------------------------------------------------------------*/
357 pic16_emitDebuggerSymbol (char * debugSym)
360 pic16_emitcode (";", "%s ==.", debugSym);
364 /*-----------------------------------------------------------------*/
365 /* newAsmop - creates a new asmOp */
366 /*-----------------------------------------------------------------*/
367 static asmop *newAsmop (short type)
371 aop = Safe_calloc(1,sizeof(asmop));
376 /*-----------------------------------------------------------------*/
377 /* resolveIfx - converts an iCode ifx into a form more useful for */
378 /* generating code */
379 /*-----------------------------------------------------------------*/
380 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
384 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
390 resIfx->condition = 1; /* assume that the ifx is true */
391 resIfx->generated = 0; /* indicate that the ifx has not been used */
394 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
397 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
398 __FUNCTION__,__LINE__,resIfx->lbl->key);
403 resIfx->lbl = IC_TRUE(ifx);
405 resIfx->lbl = IC_FALSE(ifx);
406 resIfx->condition = 0;
411 DEBUGpic16_emitcode("; +++","ifx true is non-null");
413 DEBUGpic16_emitcode("; +++","ifx true is null");
415 DEBUGpic16_emitcode("; +++","ifx false is non-null");
417 DEBUGpic16_emitcode("; +++","ifx false is null");
421 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
425 /*-----------------------------------------------------------------*/
426 /* pointerCode - returns the code for a pointer type */
427 /*-----------------------------------------------------------------*/
428 static int pointerCode (sym_link *etype)
431 return PTR_TYPE(SPEC_OCLS(etype));
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
439 static asmop *aopForSym (iCode *ic, operand *op, bool result)
441 symbol *sym=OP_SYMBOL(op);
443 memmap *space= SPEC_OCLS(sym->etype);
447 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
449 // sym = OP_SYMBOL(op);
451 /* if already has one */
453 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
458 /* if symbol was initially placed onStack then we must re-place it
459 * to direct memory, since pic16 does not have a specific stack */
461 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
469 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
471 sym->aop = aop = newAsmop (AOP_PAGED);
472 aop->aopu.aop_dir = sym->rname ;
473 aop->size = getSize(sym->type);
474 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
475 pic16_allocDirReg( IC_LEFT(ic) );
483 /* assign depending on the storage class */
484 /* if it is on the stack or indirectly addressable */
485 /* space we need to assign either r0 or r1 to it */
486 if (sym->onStack) // || sym->iaccess)
491 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
492 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
494 /* acquire a temporary register -- it is saved in function */
496 sym->aop = aop = newAsmop(AOP_STA);
497 aop->aopu.stk.stk = sym->stack;
498 aop->size = getSize(sym->type);
501 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
502 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
503 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
504 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
506 for(i=0;i<aop->size;i++)
507 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
508 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
510 if(1 && ic->op == SEND) {
512 /* if SEND do the send here */
515 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
516 for(i=0;i<aop->size;i++) {
517 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
518 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
523 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
526 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
528 // we do not need to load the value if it is to be defined...
529 if (result) return aop;
532 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
535 for(i=0;i<aop->size;i++) {
537 /* initialise for stack access via frame pointer */
538 // operands on stack are accessible via "{FRAME POINTER} + index" with index
539 // starting at 2 for arguments and growing from 0 downwards for
540 // local variables (index == 0 is not assigned so we add one here)
542 int soffs = sym->stack;
548 if(1 && ic->op == SEND) {
549 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
550 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
551 pic16_popCopyReg( pic16_frame_plusw ),
552 pic16_popCopyReg(pic16_stack_postdec )));
554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
555 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
556 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
562 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
569 /* now assign the address of the variable to
570 the pointer register */
571 if (aop->type != AOP_STK) {
575 pic16_emitcode("push","acc");
577 pic16_emitcode("mov","a,_bp");
578 pic16_emitcode("add","a,#0x%02x",
580 ((char)(sym->stack - _G.nRegsSaved )) :
581 ((char)sym->stack)) & 0xff);
582 pic16_emitcode("mov","%s,a",
583 aop->aopu.aop_ptr->name);
586 pic16_emitcode("pop","acc");
588 pic16_emitcode("mov","%s,#%s",
589 aop->aopu.aop_ptr->name,
591 aop->paged = space->paged;
593 aop->aopu.aop_stk = sym->stack;
601 /* special case for a function */
602 if (IS_FUNC(sym->type)) {
603 sym->aop = aop = newAsmop(AOP_PCODE);
604 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
605 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
606 PCOI(aop->aopu.pcop)->index = 0;
607 aop->size = FPTRSIZE;
608 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
615 //DEBUGpic16_emitcode(";","%d",__LINE__);
616 /* if in bit space */
617 if (IN_BITSPACE(space)) {
618 sym->aop = aop = newAsmop (AOP_CRY);
619 aop->aopu.aop_dir = sym->rname ;
620 aop->size = getSize(sym->type);
621 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
624 /* if it is in direct space */
625 if (IN_DIRSPACE(space)) {
626 if(!strcmp(sym->rname, "_WREG")) {
627 sym->aop = aop = newAsmop (AOP_ACC);
628 aop->size = getSize(sym->type); /* should always be 1 */
629 assert(aop->size == 1);
630 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
633 sym->aop = aop = newAsmop (AOP_DIR);
634 aop->aopu.aop_dir = sym->rname ;
635 aop->size = getSize(sym->type);
636 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
637 pic16_allocDirReg( IC_LEFT(ic) );
642 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
643 sym->aop = aop = newAsmop (AOP_DIR);
644 aop->aopu.aop_dir = sym->rname ;
645 aop->size = getSize(sym->type);
646 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
647 pic16_allocDirReg( IC_LEFT(ic) );
652 /* only remaining is far space */
653 sym->aop = aop = newAsmop(AOP_PCODE);
655 /* change the next if to 1 to revert to good old immediate code */
656 if(IN_CODESPACE(space)) {
657 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
658 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
659 PCOI(aop->aopu.pcop)->index = 0;
661 /* try to allocate via direct register */
662 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
663 // aop->size = getSize( sym->type );
666 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
667 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
670 if(!pic16_allocDirReg (IC_LEFT(ic)))
674 if(IN_DIRSPACE( space ))
676 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
677 aop->size = FPTRSIZE;
678 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
679 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
680 else if(sym->onStack) {
683 if(SPEC_SCLS(sym->etype) == S_PDATA) {
684 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
685 aop->size = FPTRSIZE;
690 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
692 /* if it is in code space */
693 if (IN_CODESPACE(space))
699 /*-----------------------------------------------------------------*/
700 /* aopForRemat - rematerialzes an object */
701 /*-----------------------------------------------------------------*/
702 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
704 symbol *sym = OP_SYMBOL(op);
706 iCode *ic = NULL, *oldic;
707 asmop *aop = newAsmop(AOP_PCODE);
714 ic = sym->rematiCode;
716 if(IS_OP_POINTER(op)) {
717 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
720 // if(!result) /* fixme-vr */
724 // chat *iLine = printILine(ic);
725 // pic16_emitpcomment("ic: %s\n", iLine);
729 val += (int) operandLitValue(IC_RIGHT(ic));
730 } else if (ic->op == '-') {
731 val -= (int) operandLitValue(IC_RIGHT(ic));
735 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
738 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
741 if(!op->isaddr)viaimmd++; else viaimmd=0;
743 /* set the following if to 1 to revert to good old immediate code */
744 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
747 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
749 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
752 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
754 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
757 PCOI(aop->aopu.pcop)->index = val;
759 aop->size = getSize( sym->type );
761 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
763 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
764 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
766 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
770 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
771 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
773 val, IS_PTR_CONST(operandType(op)));
775 val, IS_CODEPTR(operandType(op)));
778 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
780 pic16_allocDirReg (IC_LEFT(ic));
782 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
789 static int aopIdx (asmop *aop, int offset)
794 if(aop->type != AOP_REG)
797 return aop->aopu.aop_reg[offset]->rIdx;
802 /*-----------------------------------------------------------------*/
803 /* regsInCommon - two operands have some registers in common */
804 /*-----------------------------------------------------------------*/
805 static bool regsInCommon (operand *op1, operand *op2)
810 /* if they have registers in common */
811 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
814 sym1 = OP_SYMBOL(op1);
815 sym2 = OP_SYMBOL(op2);
817 if (sym1->nRegs == 0 || sym2->nRegs == 0)
820 for (i = 0 ; i < sym1->nRegs ; i++) {
825 for (j = 0 ; j < sym2->nRegs ;j++ ) {
829 if (sym2->regs[j] == sym1->regs[i])
837 /*-----------------------------------------------------------------*/
838 /* operandsEqu - equivalent */
839 /*-----------------------------------------------------------------*/
840 static bool operandsEqu ( operand *op1, operand *op2)
844 /* if they not symbols */
845 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
848 sym1 = OP_SYMBOL(op1);
849 sym2 = OP_SYMBOL(op2);
851 /* if both are itemps & one is spilt
852 and the other is not then false */
853 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
854 sym1->isspilt != sym2->isspilt )
857 /* if they are the same */
861 if (sym1->rname[0] && sym2->rname[0]
862 && strcmp (sym1->rname, sym2->rname) == 0)
866 /* if left is a tmp & right is not */
870 (sym1->usl.spillLoc == sym2))
877 (sym2->usl.spillLoc == sym1))
883 /*-----------------------------------------------------------------*/
884 /* pic16_sameRegs - two asmops have the same registers */
885 /*-----------------------------------------------------------------*/
886 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
893 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
894 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
896 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
898 if (aop1->type != AOP_REG ||
899 aop2->type != AOP_REG )
902 /* This is a bit too restrictive if one is a subset of the other...
903 if (aop1->size != aop2->size )
907 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
908 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
910 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
911 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
918 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
920 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
921 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
923 if(aop1 == aop2)return TRUE;
924 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
926 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
932 /*-----------------------------------------------------------------*/
933 /* pic16_aopOp - allocates an asmop for an operand : */
934 /*-----------------------------------------------------------------*/
935 void pic16_aopOp (operand *op, iCode *ic, bool result)
944 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
946 /* if this a literal */
947 if (IS_OP_LITERAL(op)) {
948 op->aop = aop = newAsmop(AOP_LIT);
949 aop->aopu.aop_lit = op->operand.valOperand;
950 aop->size = getSize(operandType(op));
955 sym_link *type = operandType(op);
957 if(IS_PTR_CONST(type))
961 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
964 /* if already has a asmop then continue */
968 /* if the underlying symbol has a aop */
969 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
970 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
971 op->aop = OP_SYMBOL(op)->aop;
975 /* if this is a true symbol */
976 if (IS_TRUE_SYMOP(op)) {
977 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
978 op->aop = aopForSym(ic, op, result);
982 /* this is a temporary : this has
988 e) can be a return use only */
992 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
993 /* if the type is a conditional */
994 if (sym->regType == REG_CND) {
995 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1000 /* if it is spilt then two situations
1002 b) has a spill location */
1003 if (sym->isspilt || sym->nRegs == 0) {
1005 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1006 DEBUGpic16_emitcode(";","%d",__LINE__);
1007 /* rematerialize it NOW */
1010 sym->aop = op->aop = aop = aopForRemat (op, result);
1017 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1018 aop->size = getSize(sym->type);
1019 for ( i = 0 ; i < 1 ; i++ ) {
1020 aop->aopu.aop_str[i] = accUse[i];
1021 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1023 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1024 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1032 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1033 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1034 //pic16_allocDirReg (IC_LEFT(ic));
1035 aop->size = getSize(sym->type);
1040 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1041 aop->size = getSize(sym->type);
1042 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1043 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1045 DEBUGpic16_emitcode(";","%d",__LINE__);
1049 /* else spill location */
1050 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1051 /* force a new aop if sizes differ */
1052 sym->usl.spillLoc->aop = NULL;
1056 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1057 __FUNCTION__,__LINE__,
1058 sym->usl.spillLoc->rname,
1059 sym->rname, sym->usl.spillLoc->offset);
1062 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1063 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1064 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1065 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1067 sym->usl.spillLoc->offset, op);
1068 } else if (getSize(sym->type) <= 1) {
1069 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1070 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1071 assert (getSize(sym->type) <= 1);
1072 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1073 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1075 /* We need some kind of dummy area for getSize(sym->type) byte,
1076 * use WREG for all storage locations.
1077 * XXX: This only works if we are implementing a `dummy read',
1078 * the stored value will not be retrievable...
1079 * See #1503234 for a case requiring this. */
1080 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1081 aop->size = getSize(sym->type);
1082 for ( i = 0 ; i < aop->size ;i++)
1083 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1085 aop->size = getSize(sym->type);
1091 sym_link *type = operandType(op);
1093 if(IS_PTR_CONST(type))
1095 if(IS_CODEPTR(type))
1097 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1100 /* must be in a register */
1101 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1102 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1103 aop->size = sym->nRegs;
1104 for ( i = 0 ; i < sym->nRegs ;i++)
1105 aop->aopu.aop_reg[i] = sym->regs[i];
1108 /*-----------------------------------------------------------------*/
1109 /* pic16_freeAsmop - free up the asmop given to an operand */
1110 /*----------------------------------------------------------------*/
1111 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1129 switch (aop->type) {
1134 /* we must store the result on stack */
1135 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1136 // operands on stack are accessible via "FSR2 + index" with index
1137 // starting at 2 for arguments and growing from 0 downwards for
1138 // local variables (index == 0 is not assigned so we add one here)
1139 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1144 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1145 for(i=0;i<aop->size;i++) {
1146 /* initialise for stack access via frame pointer */
1147 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1148 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1149 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1152 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1156 for(i=0;i<aop->size;i++) {
1157 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1159 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1160 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1161 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1168 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1169 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1170 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1171 deleteSetItem( &_G.sregsAllocSet, sr );
1182 int stk = aop->aopu.aop_stk + aop->size;
1183 bitVectUnSetBit(ic->rUsed,R0_IDX);
1184 bitVectUnSetBit(ic->rUsed,R1_IDX);
1186 getFreePtr(ic,&aop,FALSE);
1188 if (options.stack10bit)
1190 /* I'm not sure what to do here yet... */
1193 "*** Warning: probably generating bad code for "
1194 "10 bit stack mode.\n");
1198 pic16_emitcode ("mov","a,_bp");
1199 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1200 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1202 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1206 pic16_emitcode("pop","acc");
1207 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1209 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1212 pic16_freeAsmop(op,NULL,ic,TRUE);
1214 pic16_emitcode("pop","ar0");
1219 pic16_emitcode("pop","ar1");
1229 /* all other cases just dealloc */
1233 OP_SYMBOL(op)->aop = NULL;
1234 /* if the symbol has a spill */
1236 SPIL_LOC(op)->aop = NULL;
1241 /*-----------------------------------------------------------------*/
1242 /* pic16_aopGet - for fetching value of the aop */
1243 /*-----------------------------------------------------------------*/
1244 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1249 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1251 /* offset is greater than size then zero */
1252 if (offset > (aop->size - 1) &&
1253 aop->type != AOP_LIT)
1256 /* depending on type */
1257 switch (aop->type) {
1260 sprintf(s,"(%s + %d)",
1263 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1265 sprintf(s,"%s",aop->aopu.aop_dir);
1266 rs = Safe_calloc(1,strlen(s)+1);
1271 return aop->aopu.aop_reg[offset]->name;
1274 return aop->aopu.aop_dir;
1277 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1278 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1280 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1281 rs = Safe_strdup("WREG");
1285 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1286 rs = Safe_calloc(1,strlen(s)+1);
1291 aop->coff = offset ;
1293 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1296 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1297 aop->type = AOP_ACC;
1298 return Safe_strdup("_WREG");
1300 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1302 return aop->aopu.aop_str[offset];
1306 pCodeOp *pcop = aop->aopu.pcop;
1307 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1309 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1310 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1312 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1314 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1317 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1320 rs = Safe_calloc(1,strlen(s)+1);
1326 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1328 sprintf(s,"(%s + %d)",
1332 sprintf(s,"%s",aop->aopu.aop_dir);
1333 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1334 rs = Safe_calloc(1,strlen(s)+1);
1340 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1344 // pCodeOp *pcop = aop->aop
1349 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1350 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1351 "aopget got unsupported aop->type");
1357 /* lock has the following meaning: When allocating temporary registers
1358 * for stack variables storage, the value of the temporary register is
1359 * saved on stack. Its value is restored at the end. This procedure is
1360 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1361 * a possibility that before a call to pic16_aopOp, a temporary register
1362 * is allocated for a while and it is freed after some time, this will
1363 * mess the stack and values will not be restored properly. So use lock=1
1364 * to allocate temporary registers used internally by the programmer, and
1365 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1366 * to inform the compiler developer about a possible bug. This is an internal
1367 * feature for developing the compiler -- VR */
1369 int _TempReg_lock = 0;
1370 /*-----------------------------------------------------------------*/
1371 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *pic16_popGetTempReg(int lock)
1378 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1380 // werror(W_POSSBUG2, __FILE__, __LINE__);
1383 _TempReg_lock += lock;
1388 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1389 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1390 PCOR(pcop)->r->wasUsed=1;
1391 PCOR(pcop)->r->isFree=0;
1393 /* push value on stack */
1394 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1402 /*-----------------------------------------------------------------*/
1403 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1404 /* is not part of f, but don't save if */
1406 /*-----------------------------------------------------------------*/
1407 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1413 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1416 // werror(W_POSSBUG2, __FILE__, __LINE__);
1419 _TempReg_lock += lock;
1424 i = bitVectFirstBit(f);
1427 /* bypass registers that are used by function */
1428 if(!bitVectBitValue(f, i)) {
1430 /* bypass registers that are already allocated for stack access */
1431 if(!bitVectBitValue(v, i)) {
1433 // debugf("getting register rIdx = %d\n", i);
1434 /* ok, get the operand */
1435 pcop = pic16_newpCodeOpReg( i );
1437 /* should never by NULL */
1438 assert( pcop != NULL );
1442 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1445 PCOR(pcop)->r->wasUsed=1;
1446 PCOR(pcop)->r->isFree=0;
1452 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1454 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1455 /* already used in previous steps, break */
1462 /* caller takes care of the following */
1463 // bitVectSetBit(v, i);
1466 /* push value on stack */
1467 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1468 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1484 /*-----------------------------------------------------------------*/
1485 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1486 /*-----------------------------------------------------------------*/
1487 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1491 _TempReg_lock -= lock;
1493 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1494 PCOR(pcop)->r->isFree = 1;
1496 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1499 /*-----------------------------------------------------------------*/
1500 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1501 /*-----------------------------------------------------------------*/
1502 pCodeOp *pic16_popGetLabel(int key)
1505 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1510 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1513 /*-----------------------------------------------------------------*/
1514 /* pic16_popCopyReg - copy a pcode operator */
1515 /*-----------------------------------------------------------------*/
1516 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1520 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1521 memcpy (pcor, pc, sizeof (pCodeOpReg));
1522 pcor->r->wasUsed = 1;
1524 //pcor->pcop.type = pc->pcop.type;
1526 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1527 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1529 pcor->pcop.name = NULL;
1532 //pcor->rIdx = pc->rIdx;
1533 //pcor->r->wasUsed=1;
1534 //pcor->instance = pc->instance;
1536 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1541 /*-----------------------------------------------------------------*/
1542 /* pic16_popGetLit - asm operator to pcode operator conversion */
1543 /*-----------------------------------------------------------------*/
1544 pCodeOp *pic16_popGetLit(int lit)
1546 return pic16_newpCodeOpLit(lit);
1549 /* Allow for 12 bit literals (LFSR x, <here!>). */
1550 pCodeOp *pic16_popGetLit12(int lit)
1552 return pic16_newpCodeOpLit12(lit);
1555 /*-----------------------------------------------------------------*/
1556 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1557 /*-----------------------------------------------------------------*/
1558 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1560 return pic16_newpCodeOpLit2(lit, arg2);
1564 /*-----------------------------------------------------------------*/
1565 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1566 /*-----------------------------------------------------------------*/
1567 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1569 return pic16_newpCodeOpImmd(name, offset,index, 0);
1573 /*-----------------------------------------------------------------*/
1574 /* pic16_popGet - asm operator to pcode operator conversion */
1575 /*-----------------------------------------------------------------*/
1576 pCodeOp *pic16_popGetWithString(char *str)
1582 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1586 pcop = pic16_newpCodeOp(str,PO_STR);
1591 /*-----------------------------------------------------------------*/
1592 /* pic16_popRegFromString - */
1593 /*-----------------------------------------------------------------*/
1594 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1597 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1598 pcop->type = PO_DIR;
1600 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1601 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1606 pcop->name = Safe_calloc(1,strlen(str)+1);
1607 strcpy(pcop->name,str);
1609 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1611 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1612 // PCOR(pcop)->r->wasUsed = 1;
1614 /* make sure that register doesn't exist,
1615 * and operand isn't NULL
1616 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1617 if((PCOR(pcop)->r == NULL)
1619 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1620 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1621 // __FUNCTION__, __LINE__, str, size, offset);
1623 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1624 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1627 PCOR(pcop)->instance = offset;
1632 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1636 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1637 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1639 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1640 PCOR(pcop)->rIdx = rIdx;
1641 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1643 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1645 PCOR(pcop)->r->isFree = 0;
1646 PCOR(pcop)->r->wasUsed = 1;
1648 pcop->type = PCOR(pcop)->r->pc_type;
1653 /*---------------------------------------------------------------------------------*/
1654 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1656 /*---------------------------------------------------------------------------------*/
1657 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1659 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1660 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1666 /*--------------------------------------------------------------------------------.-*/
1667 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1668 /* VR 030601 , adapted by Hans Dorn */
1669 /*--------------------------------------------------------------------------------.-*/
1670 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1673 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1677 /*---------------------------------------------------------------------------------*/
1678 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1679 /* movff instruction */
1680 /*---------------------------------------------------------------------------------*/
1681 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1683 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1684 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1690 /*-----------------------------------------------------------------*/
1691 /* pic16_popGet - asm operator to pcode operator conversion */
1692 /*-----------------------------------------------------------------*/
1693 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1695 // char *s = buffer ;
1701 /* offset is greater than size then zero */
1703 // if (offset > (aop->size - 1) &&
1704 // aop->type != AOP_LIT)
1705 // return NULL; //zero;
1707 /* depending on type */
1708 switch (aop->type) {
1710 /* pCodeOp is already allocated from aopForSym */
1711 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1712 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1717 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1719 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1721 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1723 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1724 PCOR(pcop)->rIdx = rIdx;
1725 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1726 PCOR(pcop)->r->wasUsed=1;
1727 PCOR(pcop)->r->isFree=0;
1729 PCOR(pcop)->instance = offset;
1730 pcop->type = PCOR(pcop)->r->pc_type;
1731 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1735 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1736 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1742 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1743 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1747 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1748 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1755 // debugf2("aop = %p\toffset = %d\n", aop, offset);
1756 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
1757 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1759 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1761 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1762 // pcop->type = PO_GPR_REGISTER;
1763 PCOR(pcop)->rIdx = rIdx;
1764 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1765 PCOR(pcop)->r->wasUsed=1;
1766 PCOR(pcop)->r->isFree=0;
1768 PCOR(pcop)->instance = offset;
1769 pcop->type = PCOR(pcop)->r->pc_type;
1771 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1772 // rs = aop->aopu.aop_reg[offset]->name;
1773 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1778 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1780 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1781 PCOR(pcop)->instance = offset;
1782 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1783 //if(PCOR(pcop)->r == NULL)
1784 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1788 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1789 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1792 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1793 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1796 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1797 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1798 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1799 pcop->type = PCOR(pcop)->r->pc_type;
1800 pcop->name = PCOR(pcop)->r->name;
1806 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1808 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1809 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1810 switch( aop->aopu.pcop->type ) {
1811 case PO_DIR: PCOR(pcop)->instance += offset; break;
1812 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1817 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1818 assert( 0 ); /* should never reach here */;
1823 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1824 "pic16_popGet got unsupported aop->type");
1827 /*-----------------------------------------------------------------*/
1828 /* pic16_aopPut - puts a string for a aop */
1829 /*-----------------------------------------------------------------*/
1830 void pic16_aopPut (asmop *aop, char *s, int offset)
1837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1839 if (aop->size && offset > ( aop->size - 1)) {
1840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1841 "pic16_aopPut got offset > aop->size");
1845 /* will assign value to value */
1846 /* depending on where it is ofcourse */
1847 switch (aop->type) {
1850 sprintf(d,"(%s + %d)",
1851 aop->aopu.aop_dir,offset);
1852 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1855 sprintf(d,"%s",aop->aopu.aop_dir);
1858 DEBUGpic16_emitcode(";","%d",__LINE__);
1860 pic16_emitcode("movf","%s,w",s);
1861 pic16_emitcode("movwf","%s",d);
1864 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1865 if(offset >= aop->size) {
1866 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1869 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1872 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1879 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1880 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1883 strcmp(s,"r0") == 0 ||
1884 strcmp(s,"r1") == 0 ||
1885 strcmp(s,"r2") == 0 ||
1886 strcmp(s,"r3") == 0 ||
1887 strcmp(s,"r4") == 0 ||
1888 strcmp(s,"r5") == 0 ||
1889 strcmp(s,"r6") == 0 ||
1890 strcmp(s,"r7") == 0 )
1891 pic16_emitcode("mov","%s,%s ; %d",
1892 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1896 if(strcmp(s,"W")==0 )
1897 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1899 pic16_emitcode("movwf","%s",
1900 aop->aopu.aop_reg[offset]->name);
1902 if(strcmp(s,zero)==0) {
1903 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1905 } else if(strcmp(s,"W")==0) {
1906 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907 pcop->type = PO_GPR_REGISTER;
1909 PCOR(pcop)->rIdx = -1;
1910 PCOR(pcop)->r = NULL;
1912 DEBUGpic16_emitcode(";","%d",__LINE__);
1913 pcop->name = Safe_strdup(s);
1914 pic16_emitpcode(POC_MOVFW,pcop);
1915 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1916 } else if(strcmp(s,one)==0) {
1917 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1918 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1920 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1926 if (strcmp(s,"a") == 0)
1927 pic16_emitcode("push","acc");
1929 pic16_emitcode("push","%s",s);
1934 /* if bit variable */
1935 if (!aop->aopu.aop_dir) {
1936 pic16_emitcode("clr","a");
1937 pic16_emitcode("rlc","a");
1940 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1943 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1946 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1948 lbl = newiTempLabel(NULL);
1950 if (strcmp(s,"a")) {
1953 pic16_emitcode("clr","c");
1954 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1955 pic16_emitcode("cpl","c");
1956 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1957 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1964 if (strcmp(aop->aopu.aop_str[offset],s))
1965 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1970 if (!offset && (strcmp(s,"acc") == 0))
1973 if (strcmp(aop->aopu.aop_str[offset],s))
1974 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1978 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1979 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1980 // "pic16_aopPut got unsupported aop->type");
1986 /*-----------------------------------------------------------------*/
1987 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
1988 /*-----------------------------------------------------------------*/
1989 void pic16_mov2w (asmop *aop, int offset)
1991 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1993 if(pic16_isLitAop(aop))
1994 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1996 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1999 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2001 if(pic16_isLitAop(src)) {
2002 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2003 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2005 if(pic16_sameRegsOfs(src, dst, offset))return;
2006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2007 pic16_popGet(dst, offset)));
2011 static void pic16_movLit2f(pCodeOp *pc, int lit)
2013 if (0 == (lit & 0x00ff))
2015 pic16_emitpcode (POC_CLRF, pc);
2016 } else if (0xff == (lit & 0x00ff))
2018 pic16_emitpcode (POC_SETF, pc);
2020 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2021 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2025 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2027 if(pic16_isLitAop(src)) {
2028 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2029 pic16_emitpcode(POC_MOVWF, dst);
2031 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2035 void pic16_testStackOverflow(void)
2037 #define GSTACK_TEST_NAME "_gstack_test"
2039 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2044 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2045 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2046 // strcpy(sym->rname, GSTACK_TEST_NAME);
2047 checkAddSym(&externs, sym);
2052 /* push pcop into stack */
2053 void pic16_pushpCodeOp(pCodeOp *pcop)
2055 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2056 if (pcop->type == PO_LITERAL) {
2057 pic16_emitpcode(POC_MOVLW, pcop);
2058 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2060 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2062 if(pic16_options.gstack)
2063 pic16_testStackOverflow();
2067 /* pop pcop from stack */
2068 void pic16_poppCodeOp(pCodeOp *pcop)
2070 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2071 if(pic16_options.gstack)
2072 pic16_testStackOverflow();
2076 /*-----------------------------------------------------------------*/
2077 /* pushw - pushes wreg to stack */
2078 /*-----------------------------------------------------------------*/
2081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2082 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2083 if(pic16_options.gstack)
2084 pic16_testStackOverflow();
2088 /*-----------------------------------------------------------------*/
2089 /* pushaop - pushes aop to stack */
2090 /*-----------------------------------------------------------------*/
2091 void pushaop(asmop *aop, int offset)
2093 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2095 if(_G.resDirect)return;
2097 if(pic16_isLitAop(aop)) {
2098 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2099 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2101 pic16_emitpcode(POC_MOVFF,
2102 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2105 if(pic16_options.gstack)
2106 pic16_testStackOverflow();
2109 /*-----------------------------------------------------------------*/
2110 /* popaop - pops aop from stack */
2111 /*-----------------------------------------------------------------*/
2112 void popaop(asmop *aop, int offset)
2114 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2115 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2116 if(pic16_options.gstack)
2117 pic16_testStackOverflow();
2120 void popaopidx(asmop *aop, int offset, int index)
2124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2126 if(STACK_MODEL_LARGE)ofs++;
2128 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2129 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2130 if(pic16_options.gstack)
2131 pic16_testStackOverflow();
2134 /*-----------------------------------------------------------------*/
2135 /* pic16_getDataSize - get the operand data size */
2136 /*-----------------------------------------------------------------*/
2137 int pic16_getDataSize(operand *op)
2139 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2142 return AOP_SIZE(op);
2144 // tsd- in the pic port, the genptr size is 1, so this code here
2145 // fails. ( in the 8051 port, the size was 4).
2148 size = AOP_SIZE(op);
2149 if (size == GPTRSIZE)
2151 sym_link *type = operandType(op);
2152 if (IS_GENPTR(type))
2154 /* generic pointer; arithmetic operations
2155 * should ignore the high byte (pointer type).
2158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2165 /*-----------------------------------------------------------------*/
2166 /* pic16_outAcc - output Acc */
2167 /*-----------------------------------------------------------------*/
2168 void pic16_outAcc(operand *result)
2171 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2172 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2175 size = pic16_getDataSize(result);
2177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2180 /* unsigned or positive */
2182 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2187 /*-----------------------------------------------------------------*/
2188 /* pic16_outBitC - output a bit C */
2189 /* Move to result the value of Carry flag -- VR */
2190 /*-----------------------------------------------------------------*/
2191 void pic16_outBitC(operand *result)
2195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2197 /* if the result is bit */
2198 if (AOP_TYPE(result) == AOP_CRY) {
2199 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2200 pic16_aopPut(AOP(result),"c",0);
2203 i = AOP_SIZE(result);
2205 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2207 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2211 /*-----------------------------------------------------------------*/
2212 /* pic16_outBitOp - output a bit from Op */
2213 /* Move to result the value of set/clr op -- VR */
2214 /*-----------------------------------------------------------------*/
2215 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2221 /* if the result is bit */
2222 if (AOP_TYPE(result) == AOP_CRY) {
2223 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2224 pic16_aopPut(AOP(result),"c",0);
2227 i = AOP_SIZE(result);
2229 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2231 pic16_emitpcode(POC_RRCF, pcop);
2232 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2236 /*-----------------------------------------------------------------*/
2237 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2238 /*-----------------------------------------------------------------*/
2239 void pic16_toBoolean(operand *oper)
2241 int size = AOP_SIZE(oper) - 1;
2244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2246 if ( AOP_TYPE(oper) != AOP_ACC) {
2247 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2250 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2254 /*-----------------------------------------------------------------*/
2255 /* genUminusFloat - unary minus for floating points */
2256 /*-----------------------------------------------------------------*/
2257 static void genUminusFloat(operand *op,operand *result)
2259 int size ,offset =0 ;
2262 /* for this we just need to flip the
2263 first it then copy the rest in place */
2264 size = AOP_SIZE(op);
2265 assert( size == AOP_SIZE(result) );
2268 pic16_mov2f(AOP(result), AOP(op), offset);
2272 /* toggle the MSB's highest bit */
2273 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2276 /*-----------------------------------------------------------------*/
2277 /* genUminus - unary minus code generation */
2278 /*-----------------------------------------------------------------*/
2279 static void genUminus (iCode *ic)
2282 sym_link *optype, *rtype;
2289 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2290 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2292 /* if both in bit space then special case */
2293 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2294 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2296 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2297 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2298 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2302 optype = operandType(IC_LEFT(ic));
2303 rtype = operandType(IC_RESULT(ic));
2306 /* if float then do float stuff */
2307 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2308 if(IS_FIXED(optype))
2309 debugf("implement fixed16x16 type\n", 0);
2311 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2315 /* otherwise subtract from zero by taking the 2's complement */
2316 size = AOP_SIZE(IC_LEFT(ic));
2317 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2318 label = newiTempLabel ( NULL );
2320 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2321 for (i=size-1; i > 0; i--) {
2322 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2324 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2325 for (i=1; i < size; i++) {
2326 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2327 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2330 for (i=size-1; i >= 0; i--) {
2331 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2332 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2335 for (i=0; i < size-2; i++) {
2336 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2337 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2339 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2341 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2344 pic16_emitpLabel (label->key);
2347 /* release the aops */
2348 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2349 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2352 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2354 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2355 pic16_emitpcode(POC_MOVFW, src);
2356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2358 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2359 src, pic16_popGet(AOP(op), offset)));
2364 /*-----------------------------------------------------------------*/
2365 /* assignResultValue - assign results to oper, rescall==1 is */
2366 /* called from genCall() or genPcall() */
2367 /*-----------------------------------------------------------------*/
2368 static void assignResultValue(operand * oper, int res_size, int rescall)
2370 int size = AOP_SIZE(oper);
2374 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2375 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2378 /* assign result from a call/pcall function() */
2380 /* function results are stored in a special order,
2381 * see top of file with Function return policy, or manual */
2384 /* 8-bits, result in WREG */
2385 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2387 if(size > 1 && res_size > 1) {
2388 /* 16-bits, result in PRODL:WREG */
2389 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2392 if(size > 2 && res_size > 2) {
2393 /* 24-bits, result in PRODH:PRODL:WREG */
2394 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2397 if(size > 3 && res_size > 3) {
2398 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2399 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2402 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2405 /* >32-bits, result on stack, and FSR0 points to beginning.
2406 * Fix stack when done */
2408 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2410 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2411 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2413 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2418 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2419 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2420 if(STACK_MODEL_LARGE) {
2422 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2426 int areg = 0; /* matching argument register */
2428 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2429 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2432 /* its called from genReceive (probably) -- VR */
2433 /* I hope this code will not be called from somewhere else in the future!
2434 * We manually set the pseudo stack pointer in genReceive. - dw
2436 if(!GpsuedoStkPtr && _G.useWreg) {
2437 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2439 /* The last byte in the assignment is in W */
2440 if(areg <= GpsuedoStkPtr) {
2442 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2444 // debugf("receive from WREG\n", 0);
2446 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2449 _G.stack_lat = AOP_SIZE(oper)-1;
2454 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2455 // debugf("receive from STACK\n", 0);
2462 /*-----------------------------------------------------------------*/
2463 /* genIpush - generate code for pushing this gets a little complex */
2464 /*-----------------------------------------------------------------*/
2465 static void genIpush (iCode *ic)
2467 // int size, offset=0;
2470 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2473 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2475 /* send to stack as normal */
2476 addSet(&_G.sendSet,ic);
2477 // addSetHead(&_G.sendSet,ic);
2478 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2483 int size, offset = 0 ;
2487 /* if this is not a parm push : ie. it is spill push
2488 and spill push is always done on the local stack */
2489 if (!ic->parmPush) {
2491 /* and the item is spilt then do nothing */
2492 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2495 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2496 size = AOP_SIZE(IC_LEFT(ic));
2497 /* push it on the stack */
2499 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2504 pic16_emitcode("push","%s",l);
2509 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2513 /*-----------------------------------------------------------------*/
2514 /* genIpop - recover the registers: can happen only for spilling */
2515 /*-----------------------------------------------------------------*/
2516 static void genIpop (iCode *ic)
2519 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2524 /* if the temp was not pushed then */
2525 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2528 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2529 size = AOP_SIZE(IC_LEFT(ic));
2532 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2535 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2539 static int wparamCmp(void *p1, void *p2)
2541 return (!strcmp((char *)p1, (char *)p2));
2544 int inWparamList(char *s)
2546 return isinSetWith(wparamList, s, wparamCmp);
2550 /*-----------------------------------------------------------------*/
2551 /* genCall - generates a call statement */
2552 /*-----------------------------------------------------------------*/
2553 static void genCall (iCode *ic)
2563 ftype = OP_SYM_TYPE(IC_LEFT(ic));
2564 /* if caller saves & we have not saved then */
2565 // if (!ic->regsSaved)
2566 // saveRegisters(ic);
2568 /* initialise stackParms for IPUSH pushes */
2569 // stackParms = psuedoStkPtr;
2570 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2571 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2572 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2575 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2578 /* if send set is not empty the assign */
2581 int psuedoStkPtr=-1;
2582 int firstTimeThruLoop = 1;
2585 /* reverse sendSet if function is not reentrant */
2586 if(!IFFUNC_ISREENT(ftype))
2587 _G.sendSet = reverseSet(_G.sendSet);
2589 /* First figure how many parameters are getting passed */
2593 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2597 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2598 size = AOP_SIZE(IC_LEFT(sic));
2602 /* pass the last byte through WREG */
2606 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2607 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2608 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2610 if(!firstTimeThruLoop) {
2611 /* If this is not the first time we've been through the loop
2612 * then we need to save the parameter in a temporary
2613 * register. The last byte of the last parameter is
2617 // --psuedoStkPtr; // sanity check
2621 firstTimeThruLoop=0;
2623 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2628 /* all arguments are passed via stack */
2632 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2633 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2634 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2636 // pushaop(AOP(IC_LEFT(sic)), size);
2637 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2644 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2648 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2649 pushw(); /* save last parameter to stack if functions has varargs */
2653 } else use_wreg = 0;
2655 _G.stackRegSet = _G.sendSet;
2660 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2664 /* if we need to assign a result value */
2665 if ((IS_ITEMP(IC_RESULT(ic))
2666 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2667 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2668 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2671 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2674 /* Must not assign an 8-bit result to a 16-bit variable;
2675 * this would use (used...) the uninitialized PRODL! */
2676 /* FIXME: Need a proper way to obtain size of function result type,
2677 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2678 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2680 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2681 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2683 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2686 if(!stackParms && ic->parmBytes) {
2687 stackParms = ic->parmBytes;
2690 stackParms -= use_wreg;
2693 if(stackParms == 1) {
2694 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
2696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2697 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2699 if(STACK_MODEL_LARGE) {
2701 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2706 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2709 /* adjust the stack for parameters if required */
2710 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2713 /* if register bank was saved then pop them */
2715 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2717 /* if we hade saved some registers then unsave them */
2718 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2719 unsaveRegisters (ic);
2725 /*-----------------------------------------------------------------*/
2726 /* genPcall - generates a call by pointer statement */
2727 /* new version, created from genCall - HJD */
2728 /*-----------------------------------------------------------------*/
2729 static void genPcall (iCode *ic)
2733 symbol *retlbl = newiTempLabel(NULL);
2734 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2738 fntype = operandType( IC_LEFT(ic) )->next;
2740 /* if send set is not empty the assign */
2743 int psuedoStkPtr=-1;
2745 /* reverse sendSet if function is not reentrant */
2746 if(!IFFUNC_ISREENT(fntype))
2747 _G.sendSet = reverseSet(_G.sendSet);
2751 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2754 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2755 size = AOP_SIZE(IC_LEFT(sic));
2758 /* all parameters are passed via stack, since WREG is clobbered
2759 * by the calling sequence */
2761 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2762 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2763 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2765 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2769 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2772 _G.stackRegSet = _G.sendSet;
2776 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2778 // push return address
2779 // push $ on return stack, then replace with retlbl
2781 /* Thanks to Thorsten Klose for pointing out that the following
2782 * snippet should be interrupt safe */
2783 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2784 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2786 pic16_emitpcodeNULLop(POC_PUSH);
2788 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2789 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2790 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2791 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2792 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2793 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2796 /* restore interrupt control register */
2797 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2798 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2800 /* make the call by writing the pointer into pc */
2801 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2802 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2804 // note: MOVFF to PCL not allowed
2805 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2806 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2809 /* return address is here: (X) */
2810 pic16_emitpLabelFORCE(retlbl->key);
2812 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2815 /* if we need assign a result value */
2816 if ((IS_ITEMP(IC_RESULT(ic))
2817 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2818 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2819 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2822 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2825 /* FIXME: Need proper way to obtain the function result's type.
2826 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2827 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2829 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2830 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2832 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2835 // stackParms -= use_wreg;
2838 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2839 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2840 if(STACK_MODEL_LARGE) {
2842 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2847 /*-----------------------------------------------------------------*/
2848 /* resultRemat - result is rematerializable */
2849 /*-----------------------------------------------------------------*/
2850 static int resultRemat (iCode *ic)
2852 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2853 if (SKIP_IC(ic) || ic->op == IFX)
2856 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2857 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2858 if (sym->remat && !POINTER_SET(ic))
2866 /*-----------------------------------------------------------------*/
2867 /* inExcludeList - return 1 if the string is in exclude Reg list */
2868 /*-----------------------------------------------------------------*/
2869 static bool inExcludeList(char *s)
2871 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2875 if (options.excludeRegs[i] &&
2876 STRCASECMP(options.excludeRegs[i],"none") == 0)
2879 for ( i = 0 ; options.excludeRegs[i]; i++) {
2880 if (options.excludeRegs[i] &&
2881 STRCASECMP(s,options.excludeRegs[i]) == 0)
2888 /*-----------------------------------------------------------------*/
2889 /* genFunction - generated code for function entry */
2890 /*-----------------------------------------------------------------*/
2891 static void genFunction (iCode *ic)
2897 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2899 pic16_labelOffset += (max_key+4);
2904 ftype = operandType(IC_LEFT(ic));
2905 sym = OP_SYMBOL(IC_LEFT(ic));
2907 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2908 /* create an absolute section at the interrupt vector:
2909 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2914 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2916 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2917 sprintf(asymname, "ivec_%s", sym->name);
2919 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2921 /* when an interrupt is declared as naked, do not emit the special
2922 * wrapper segment at vector address. The user should take care for
2923 * this instead. -- VR */
2925 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2926 asym = newSymbol(asymname, 0);
2927 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2928 pic16_addpBlock( apb );
2930 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2931 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2932 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2933 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2934 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2936 /* mark the end of this tiny function */
2937 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2939 sprintf(asymname, "%s", sym->rname);
2945 abSym = Safe_calloc(1, sizeof(absSym));
2946 strcpy(abSym->name, asymname);
2948 switch( FUNC_INTNO(sym->type) ) {
2949 case 0: abSym->address = 0x000000; break;
2950 case 1: abSym->address = 0x000008; break;
2951 case 2: abSym->address = 0x000018; break;
2954 // fprintf(stderr, "no interrupt number is given\n");
2955 abSym->address = -1; break;
2958 /* relocate interrupt vectors if needed */
2959 if(abSym->address != -1)
2960 abSym->address += pic16_options.ivt_loc;
2962 addSet(&absSymSet, abSym);
2966 /* create the function header */
2967 pic16_emitcode(";","-----------------------------------------");
2968 pic16_emitcode(";"," function %s",sym->name);
2969 pic16_emitcode(";","-----------------------------------------");
2971 /* prevent this symbol from being emitted as 'extern' */
2972 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2974 pic16_emitcode("","%s:",sym->rname);
2975 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2980 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2981 if(!strcmp(ab->name, sym->rname)) {
2982 pic16_pBlockConvert2Absolute(pb);
2988 if(IFFUNC_ISNAKED(ftype)) {
2989 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2993 /* if critical function then turn interrupts off */
2994 if (IFFUNC_ISCRITICAL(ftype)) {
2995 //pic16_emitcode("clr","ea");
2998 currFunc = sym; /* update the currFunc symbol */
2999 _G.fregsUsed = sym->regsUsed;
3000 _G.sregsAlloc = newBitVect(128);
3003 /* if this is an interrupt service routine then
3004 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3005 if (IFFUNC_ISISR(sym->type)) {
3006 _G.usefastretfie = 1; /* use shadow registers by default */
3008 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3009 if(!FUNC_ISSHADOWREGS(sym->type)) {
3010 /* do not save WREG,STATUS,BSR for high priority interrupts
3011 * because they are stored in the hardware shadow registers already */
3012 _G.usefastretfie = 0;
3013 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3014 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3015 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3018 /* these should really be optimized somehow, because not all
3019 * interrupt handlers modify them */
3020 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3021 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3022 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3023 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3024 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3025 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3027 // pic16_pBlockConvert2ISR(pb);
3030 /* emit code to setup stack frame if user enabled,
3031 * and function is not main() */
3033 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3034 if(strcmp(sym->name, "main")) {
3036 || !options.ommitFramePtr
3038 || IFFUNC_ARGS(sym->type)
3039 || FUNC_HASSTACKPARM(sym->etype)
3041 /* setup the stack frame */
3042 if(STACK_MODEL_LARGE)
3043 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3044 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3046 if(STACK_MODEL_LARGE)
3047 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3048 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3052 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3055 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3057 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3058 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3060 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3063 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3064 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3071 /* if callee-save to be used for this function
3072 * then save the registers being used in this function */
3073 // if (IFFUNC_CALLEESAVES(sym->type))
3074 if(strcmp(sym->name, "main")) {
3077 /* if any registers used */
3078 if (sym->regsUsed) {
3079 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3082 /* save the registers used */
3083 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3084 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3085 if (bitVectBitValue(sym->regsUsed,i)) {
3087 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3089 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3092 if(!pic16_regWithIdx(i)->wasUsed) {
3093 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3094 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3095 pic16_regWithIdx(i)->wasUsed = 1;
3102 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3103 for(i=0;i<sym->regsUsed->size;i++) {
3104 if(bitVectBitValue(sym->regsUsed, i)) {
3109 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3112 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3117 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3118 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3121 /*-----------------------------------------------------------------*/
3122 /* genEndFunction - generates epilogue for functions */
3123 /*-----------------------------------------------------------------*/
3124 static void genEndFunction (iCode *ic)
3126 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3130 if(IFFUNC_ISNAKED(sym->type)) {
3131 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3137 /* add code for ISCRITICAL */
3138 if(IFFUNC_ISCRITICAL(sym->type)) {
3139 /* if critical function, turn on interrupts */
3141 /* TODO: add code here -- VR */
3144 // sym->regsUsed = _G.fregsUsed;
3146 /* now we need to restore the registers */
3147 /* if any registers used */
3149 /* first restore registers that might be used for stack access */
3150 if(_G.sregsAllocSet) {
3153 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3154 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3155 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3159 if (strcmp(sym->name, "main") && sym->regsUsed) {
3162 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3163 /* restore registers used */
3164 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3165 for ( i = sym->regsUsed->size; i >= 0; i--) {
3166 if (bitVectBitValue(sym->regsUsed,i)) {
3167 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3171 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3176 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3178 if (sym->stack == 1) {
3179 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3180 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3182 // we have to add more than one...
3183 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3184 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3185 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3187 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3188 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3189 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3193 if(strcmp(sym->name, "main")) {
3195 || !options.ommitFramePtr
3197 || IFFUNC_ARGS(sym->type)
3198 || FUNC_HASSTACKPARM(sym->etype)
3200 /* restore stack frame */
3201 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3202 if(STACK_MODEL_LARGE)
3203 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3209 if (IFFUNC_ISISR(sym->type)) {
3210 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3211 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3212 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3213 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3214 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3215 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3217 if(!FUNC_ISSHADOWREGS(sym->type)) {
3218 /* do not restore interrupt vector for WREG,STATUS,BSR
3219 * for high priority interrupt, see genFunction */
3220 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3221 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3222 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3224 // _G.interruptvector = 0; /* sanity check */
3227 /* if debug then send end of function */
3228 /* if (options.debug && currFunc) */
3230 debugFile->writeEndFunction (currFunc, ic, 1);
3233 if(_G.usefastretfie)
3234 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3236 pic16_emitpcodeNULLop(POC_RETFIE);
3238 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3240 _G.usefastretfie = 0;
3244 if (IFFUNC_ISCRITICAL(sym->type)) {
3245 pic16_emitcode("setb","ea");
3248 /* if debug then send end of function */
3250 debugFile->writeEndFunction (currFunc, ic, 1);
3253 /* insert code to restore stack frame, if user enabled it
3254 * and function is not main() */
3257 pic16_emitpcodeNULLop(POC_RETURN);
3259 /* Mark the end of a function */
3260 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3264 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3266 unsigned long lit=1;
3271 // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3272 if(AOP_TYPE(op) == AOP_LIT) {
3273 if(!IS_FLOAT(operandType( op ))) {
3274 lit = ulFromVal (AOP(op)->aopu.aop_lit);
3277 unsigned long lit_int;
3281 /* take care if literal is a float */
3282 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3287 if (AOP_TYPE(op) == AOP_LIT) {
3288 /* FIXME: broken for
3289 * char __at(0x456) foo;
3291 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3292 pic16_movLit2f(dest, (lit >> (8ul*offset)));
3293 } else if (AOP_TYPE(op) == AOP_PCODE
3294 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3295 /* char *s= "aaa"; return s; */
3296 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3297 * that the generic pointer is interpreted correctly
3298 * as referring to __code space, but this is fragile! */
3299 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3300 /* XXX: should check that dest != WREG */
3301 pic16_emitpcode(POC_MOVWF, dest);
3303 if(dest->type == PO_WREG && (offset == 0)) {
3304 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3307 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3311 /*-----------------------------------------------------------------*/
3312 /* genRet - generate code for return statement */
3313 /*-----------------------------------------------------------------*/
3314 static void genRet (iCode *ic)
3320 /* if we have no return value then
3321 * just generate the "ret" */
3326 /* we have something to return then
3327 * move the return value into place */
3328 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3329 size = AOP_SIZE(IC_LEFT(ic));
3333 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3336 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3339 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3341 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3344 /* >32-bits, setup stack and FSR0 */
3346 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3347 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3349 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3351 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3356 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3357 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3359 if(STACK_MODEL_LARGE) {
3360 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3361 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3363 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3367 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3370 /* generate a jump to the return label
3371 * if the next is not the return statement */
3372 if (!(ic->next && ic->next->op == LABEL
3373 && IC_LABEL(ic->next) == returnLabel)) {
3375 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3376 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3380 /*-----------------------------------------------------------------*/
3381 /* genLabel - generates a label */
3382 /*-----------------------------------------------------------------*/
3383 static void genLabel (iCode *ic)
3387 /* special case never generate */
3388 if (IC_LABEL(ic) == entryLabel)
3391 pic16_emitpLabel(IC_LABEL(ic)->key);
3392 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3395 /*-----------------------------------------------------------------*/
3396 /* genGoto - generates a goto */
3397 /*-----------------------------------------------------------------*/
3399 static void genGoto (iCode *ic)
3402 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3403 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3407 /*-----------------------------------------------------------------*/
3408 /* genMultbits :- multiplication of bits */
3409 /*-----------------------------------------------------------------*/
3410 static void genMultbits (operand *left,
3416 if(!pic16_sameRegs(AOP(result),AOP(right)))
3417 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3419 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3420 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3421 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3426 /*-----------------------------------------------------------------*/
3427 /* genMultOneByte : 8 bit multiplication & division */
3428 /*-----------------------------------------------------------------*/
3429 static void genMultOneByte (operand *left,
3435 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3436 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3438 /* (if two literals, the value is computed before) */
3439 /* if one literal, literal on the right */
3440 if (AOP_TYPE(left) == AOP_LIT){
3446 /* size is already checked in genMult == 1 */
3447 // size = AOP_SIZE(result);
3449 if (AOP_TYPE(right) == AOP_LIT){
3450 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3451 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3452 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3453 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3455 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3456 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3457 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3458 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3461 pic16_genMult8X8_n (left, right,result);
3465 /*-----------------------------------------------------------------*/
3466 /* genMultOneWord : 16 bit multiplication */
3467 /*-----------------------------------------------------------------*/
3468 static void genMultOneWord (operand *left,
3473 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3474 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3476 /* (if two literals, the value is computed before)
3477 * if one literal, literal on the right */
3478 if (AOP_TYPE(left) == AOP_LIT){
3484 /* size is checked already == 2 */
3485 // size = AOP_SIZE(result);
3487 if (AOP_TYPE(right) == AOP_LIT) {
3488 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3489 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3490 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3491 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3493 pic16_emitpcomment("multiply variable :%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));
3499 pic16_genMult16X16_16(left, right,result);
3504 /*-----------------------------------------------------------------*/
3505 /* genMultOneLong : 32 bit multiplication */
3506 /*-----------------------------------------------------------------*/
3507 static void genMultOneLong (operand *left,
3512 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3513 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3515 /* (if two literals, the value is computed before)
3516 * if one literal, literal on the right */
3517 if (AOP_TYPE(left) == AOP_LIT){
3523 /* size is checked already == 4 */
3524 // size = AOP_SIZE(result);
3526 if (AOP_TYPE(right) == AOP_LIT) {
3527 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3528 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3529 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3530 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3532 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3533 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3534 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3535 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3538 pic16_genMult32X32_32(left, right,result);
3544 /*-----------------------------------------------------------------*/
3545 /* genMult - generates code for multiplication */
3546 /*-----------------------------------------------------------------*/
3547 static void genMult (iCode *ic)
3549 operand *left = IC_LEFT(ic);
3550 operand *right = IC_RIGHT(ic);
3551 operand *result= IC_RESULT(ic);
3554 /* assign the amsops */
3555 pic16_aopOp (left,ic,FALSE);
3556 pic16_aopOp (right,ic,FALSE);
3557 pic16_aopOp (result,ic,TRUE);
3559 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3561 /* special cases first *
3563 if (AOP_TYPE(left) == AOP_CRY
3564 && AOP_TYPE(right)== AOP_CRY) {
3565 genMultbits(left,right,result);
3569 /* if both are of size == 1 */
3570 if(AOP_SIZE(left) == 1
3571 && AOP_SIZE(right) == 1) {
3572 genMultOneByte(left,right,result);
3577 /* if both are of size == 2 */
3578 if(AOP_SIZE(left) == 2
3579 && AOP_SIZE(right) == 2) {
3580 genMultOneWord(left, right, result);
3584 /* if both are of size == 4 */
3585 if(AOP_SIZE(left) == 4
3586 && AOP_SIZE(right) == 4) {
3587 genMultOneLong(left, right, result);
3592 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3593 assert( !"Multiplication should have been transformed into function call!" );
3595 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3598 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3599 /* should have been converted to function call */
3603 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3604 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3605 pic16_freeAsmop(result,NULL,ic,TRUE);
3609 /*-----------------------------------------------------------------*/
3610 /* genDivbits :- division of bits */
3611 /*-----------------------------------------------------------------*/
3612 static void genDivbits (operand *left,
3619 /* the result must be bit */
3620 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3621 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3625 pic16_emitcode("div","ab");
3626 pic16_emitcode("rrc","a");
3627 pic16_aopPut(AOP(result),"c",0);
3630 /*-----------------------------------------------------------------*/
3631 /* genDivOneByte : 8 bit division */
3632 /*-----------------------------------------------------------------*/
3633 static void genDivOneByte (operand *left,
3637 sym_link *opetype = operandType(result);
3642 /* result = divident / divisor
3643 * - divident may be a register or a literal,
3644 * - divisor may be a register or a literal,
3645 * so there are 3 cases (literal / literal is optimized
3646 * by the front-end) to handle.
3647 * In addition we must handle signed and unsigned, which
3648 * result in 6 final different cases -- VR */
3652 size = AOP_SIZE(result) - 1;
3654 /* signed or unsigned */
3655 if (SPEC_USIGN(opetype)) {
3656 pCodeOp *pct1, /* count */
3659 symbol *label1, *label2, *label3;;
3662 /* unsigned is easy */
3664 pct1 = pic16_popGetTempReg(1);
3665 pct2 = pic16_popGetTempReg(1);
3666 pct3 = pic16_popGetTempReg(1);
3668 label1 = newiTempLabel(NULL);
3669 label2 = newiTempLabel(NULL);
3670 label3 = newiTempLabel(NULL);
3672 /* the following algorithm is extracted from divuint.c */
3674 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3675 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3677 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3679 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3681 pic16_emitpLabel(label1->key);
3684 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3688 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3692 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3694 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3695 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3697 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3698 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3699 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3701 pic16_emitpLabel( label3->key );
3702 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3703 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3707 pic16_emitpLabel(label2->key);
3708 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3709 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3710 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3712 /* result is in wreg */
3713 if(AOP_TYPE(result) != AOP_ACC)
3714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3716 pic16_popReleaseTempReg( pct3, 1);
3717 pic16_popReleaseTempReg( pct2, 1);
3718 pic16_popReleaseTempReg( pct1, 1);
3723 /* signed is a little bit more difficult */
3725 /* save the signs of the operands */
3726 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3728 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3729 pic16_emitcode("push","acc"); /* save it on the stack */
3731 /* now sign adjust for both left & right */
3732 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3734 lbl = newiTempLabel(NULL);
3735 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3736 pic16_emitcode("cpl","a");
3737 pic16_emitcode("inc","a");
3738 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3739 pic16_emitcode("mov","b,a");
3741 /* sign adjust left side */
3742 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3745 lbl = newiTempLabel(NULL);
3746 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3747 pic16_emitcode("cpl","a");
3748 pic16_emitcode("inc","a");
3749 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3751 /* now the division */
3752 pic16_emitcode("div","ab");
3753 /* we are interested in the lower order
3755 pic16_emitcode("mov","b,a");
3756 lbl = newiTempLabel(NULL);
3757 pic16_emitcode("pop","acc");
3758 /* if there was an over flow we don't
3759 adjust the sign of the result */
3760 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3761 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3763 pic16_emitcode("clr","a");
3764 pic16_emitcode("subb","a,b");
3765 pic16_emitcode("mov","b,a");
3766 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3768 /* now we are done */
3769 pic16_aopPut(AOP(result),"b",0);
3771 pic16_emitcode("mov","c,b.7");
3772 pic16_emitcode("subb","a,acc");
3775 pic16_aopPut(AOP(result),"a",offset++);
3780 /*-----------------------------------------------------------------*/
3781 /* genDiv - generates code for division */
3782 /*-----------------------------------------------------------------*/
3783 static void genDiv (iCode *ic)
3785 operand *left = IC_LEFT(ic);
3786 operand *right = IC_RIGHT(ic);
3787 operand *result= IC_RESULT(ic);
3789 int leftVal = 0, rightVal = 0;
3791 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3794 /* Division is a very lengthy algorithm, so it is better
3795 * to call support routines than inlining algorithm.
3796 * Division functions written here just in case someone
3797 * wants to inline and not use the support libraries -- VR */
3801 /* assign the amsops */
3802 pic16_aopOp (left,ic,FALSE);
3803 pic16_aopOp (right,ic,FALSE);
3804 pic16_aopOp (result,ic,TRUE);
3808 else if (ic->op == '%')
3811 assert( !"invalid operation requested in genDivMod" );
3813 /* get literal values */
3814 if (IS_VALOP(left)) {
3815 leftVal = (int) ulFromVal ( OP_VALUE(left) );
3816 assert( leftVal >= -128 && leftVal < 256 );
3817 if (leftVal < 0) { signedLits++; }
3819 if (IS_VALOP(right)) {
3820 rightVal = (int) ulFromVal ( OP_VALUE(right) );
3821 assert( rightVal >= -128 && rightVal < 256 );
3822 if (rightVal < 0) { signedLits++; }
3825 /* We should only come here to convert all
3826 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3827 * with exactly one operand being s8_t into
3828 * u8_t x u8_t -> u8_t. All other cases should have been
3829 * turned into calls to support routines beforehand... */
3830 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3831 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3833 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3834 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3836 /* Both operands are signed or negative, use _divschar
3837 * instead of _divuchar */
3838 pushaop(AOP(right), 0);
3839 pushaop(AOP(left), 0);
3841 /* call _divschar */
3842 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3846 sym = newSymbol( functions[op][0], 0 );
3848 strcpy(sym->rname, functions[op][0]);
3849 checkAddSym(&externs, sym);
3853 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3854 if (AOP_SIZE(result) > 1)
3856 pic16_emitpcode(POC_MOVFF,
3857 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3858 pic16_popGet(AOP(result), 1)));
3860 pic16_addSign(result, 2, 1);
3863 /* clean up stack */
3864 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3865 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3870 /* push right operand */
3871 if (IS_VALOP(right)) {
3873 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3876 pushaop(AOP(right), 0);
3878 } else if (!IS_UNSIGNED(operandType(right))) {
3879 pic16_mov2w(AOP(right), 0);
3880 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3881 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3882 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3885 pushaop(AOP(right), 0);
3888 /* push left operand */
3889 if (IS_VALOP(left)) {
3891 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3894 pushaop(AOP(left), 0);
3896 } else if (!IS_UNSIGNED(operandType(left))) {
3897 pic16_mov2w(AOP(left),0);
3898 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3899 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3900 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3903 pushaop(AOP(left), 0);
3906 /* call _divuchar */
3907 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3911 sym = newSymbol( functions[op][1], 0 );
3913 strcpy(sym->rname, functions[op][1]);
3914 checkAddSym(&externs, sym);
3917 /* Revert negation(s) from above.
3918 * This is inefficient: if both operands are negative, this
3919 * should not touch WREG. However, determining that exactly
3920 * one operand was negated costs at least 3 instructions,
3921 * so there is nothing to be gained here, is there?
3923 * I negate WREG because either operand might share registers with
3924 * result, so assigning first might destroy an operand. */
3926 /* For the modulus operator, (a/b)*b == a shall hold.
3927 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3928 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
3929 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
3930 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
3931 * Only invert the result if the left operand is negative (sigh).
3933 if (AOP_SIZE(result) <= 1 || !negated)
3937 if (IS_VALOP(right)) {
3939 /* we negated this operand above */
3940 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3942 } else if (!IS_UNSIGNED(operandType(right))) {
3943 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3944 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3948 if (IS_VALOP(left)) {
3950 /* we negated this operand above */
3951 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3953 } else if (!IS_UNSIGNED(operandType(left))) {
3954 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3955 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3958 /* Move result to destination. */
3959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3961 /* Zero-extend: no operand was signed (or result is just a byte). */
3962 pic16_addSign(result, 1, 0);
3964 assert( AOP_SIZE(result) > 1 );
3965 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3968 if (IS_VALOP(right)) {
3970 /* we negated this operand above */
3971 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3973 } else if (!IS_UNSIGNED(operandType(right))) {
3974 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3975 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3979 if (IS_VALOP(left)) {
3981 /* we negated this operand above */
3982 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3984 } else if (!IS_UNSIGNED(operandType(left))) {
3985 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3986 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3989 /* Move result to destination. */
3990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3992 /* Negate result if required. */
3993 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
3994 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
3997 pic16_addSign(result, 2, 1);
4000 /* clean up stack */
4001 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4002 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4007 /* special cases first */
4009 if (AOP_TYPE(left) == AOP_CRY &&
4010 AOP_TYPE(right)== AOP_CRY) {
4011 genDivbits(left,right,result);
4015 /* if both are of size == 1 */
4016 if (AOP_SIZE(left) == 1 &&
4017 AOP_SIZE(right) == 1 ) {
4018 genDivOneByte(left,right,result);
4023 /* should have been converted to function call */
4026 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4027 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4028 pic16_freeAsmop(result,NULL,ic,TRUE);
4032 /*-----------------------------------------------------------------*/
4033 /* genModbits :- modulus of bits */
4034 /*-----------------------------------------------------------------*/
4035 static void genModbits (operand *left,
4043 werror(W_POSSBUG2, __FILE__, __LINE__);
4044 /* the result must be bit */
4045 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4046 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4050 pic16_emitcode("div","ab");
4051 pic16_emitcode("mov","a,b");
4052 pic16_emitcode("rrc","a");
4053 pic16_aopPut(AOP(result),"c",0);
4056 /*-----------------------------------------------------------------*/
4057 /* genModOneByte : 8 bit modulus */
4058 /*-----------------------------------------------------------------*/
4059 static void genModOneByte (operand *left,
4063 sym_link *opetype = operandType(result);
4068 werror(W_POSSBUG2, __FILE__, __LINE__);
4070 /* signed or unsigned */
4071 if (SPEC_USIGN(opetype)) {
4072 /* unsigned is easy */
4073 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4074 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4076 pic16_emitcode("div","ab");
4077 pic16_aopPut(AOP(result),"b",0);
4081 /* signed is a little bit more difficult */
4083 /* save the signs of the operands */
4084 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4087 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4088 pic16_emitcode("push","acc"); /* save it on the stack */
4090 /* now sign adjust for both left & right */
4091 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4094 lbl = newiTempLabel(NULL);
4095 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4096 pic16_emitcode("cpl","a");
4097 pic16_emitcode("inc","a");
4098 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4099 pic16_emitcode("mov","b,a");
4101 /* sign adjust left side */
4102 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4105 lbl = newiTempLabel(NULL);
4106 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4107 pic16_emitcode("cpl","a");
4108 pic16_emitcode("inc","a");
4109 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4111 /* now the multiplication */
4112 pic16_emitcode("div","ab");
4113 /* we are interested in the lower order
4115 lbl = newiTempLabel(NULL);
4116 pic16_emitcode("pop","acc");
4117 /* if there was an over flow we don't
4118 adjust the sign of the result */
4119 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4120 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4122 pic16_emitcode("clr","a");
4123 pic16_emitcode("subb","a,b");
4124 pic16_emitcode("mov","b,a");
4125 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4127 /* now we are done */
4128 pic16_aopPut(AOP(result),"b",0);
4133 /*-----------------------------------------------------------------*/
4134 /* genMod - generates code for division */
4135 /*-----------------------------------------------------------------*/
4136 static void genMod (iCode *ic)
4138 /* Task deferred to genDiv */
4141 operand *left = IC_LEFT(ic);
4142 operand *right = IC_RIGHT(ic);
4143 operand *result= IC_RESULT(ic);
4147 /* assign the amsops */
4148 pic16_aopOp (left,ic,FALSE);
4149 pic16_aopOp (right,ic,FALSE);
4150 pic16_aopOp (result,ic,TRUE);
4152 /* special cases first */
4154 if (AOP_TYPE(left) == AOP_CRY &&
4155 AOP_TYPE(right)== AOP_CRY) {
4156 genModbits(left,right,result);
4160 /* if both are of size == 1 */
4161 if (AOP_SIZE(left) == 1 &&
4162 AOP_SIZE(right) == 1 ) {
4163 genModOneByte(left,right,result);
4167 /* should have been converted to function call */
4171 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4172 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173 pic16_freeAsmop(result,NULL,ic,TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* genIfxJump :- will create a jump depending on the ifx */
4179 /*-----------------------------------------------------------------*/
4181 note: May need to add parameter to indicate when a variable is in bit space.
4183 static void genIfxJump (iCode *ic, char *jval)
4187 /* if true label then we jump if condition
4189 if ( IC_TRUE(ic) ) {
4191 if(strcmp(jval,"a") == 0)
4193 else if (strcmp(jval,"c") == 0)
4196 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4197 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4200 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4201 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4205 /* false label is present */
4206 if(strcmp(jval,"a") == 0)
4208 else if (strcmp(jval,"c") == 0)
4211 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4212 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4215 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4216 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4221 /* mark the icode as generated */
4225 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4229 /* if true label then we jump if condition
4231 if ( IC_TRUE(ic) ) {
4232 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4233 pic16_emitpcode(POC_BTFSC, jop);
4235 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4236 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4239 /* false label is present */
4240 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4241 pic16_emitpcode(POC_BTFSS, jop);
4243 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4244 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4248 /* mark the icode as generated */
4255 /*-----------------------------------------------------------------*/
4257 /*-----------------------------------------------------------------*/
4258 static void genSkip(iCode *ifx,int status_bit)
4260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4264 if ( IC_TRUE(ifx) ) {
4265 switch(status_bit) {
4280 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4281 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4285 switch(status_bit) {
4299 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4300 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4307 /*-----------------------------------------------------------------*/
4309 /*-----------------------------------------------------------------*/
4310 static void genSkipc(resolvedIfx *rifx)
4312 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4322 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4323 rifx->generated = 1;
4326 /*-----------------------------------------------------------------*/
4327 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4328 /* aop (if it's NOT a literal) or from lit (if */
4329 /* aop is a literal) */
4330 /*-----------------------------------------------------------------*/
4331 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4332 if (aop->type == AOP_LIT) {
4333 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4335 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4339 /*-----------------------------------------------------------------*/
4340 /* genCmp :- greater or less than comparison */
4341 /*-----------------------------------------------------------------*/
4343 /* genCmp performs a left < right comparison, stores
4344 * the outcome in result (if != NULL) and generates
4345 * control flow code for the ifx (if != NULL).
4347 * This version leaves in sequences like
4348 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4349 * which should be optmized by the peephole
4350 * optimizer - RN 2005-01-01 */
4351 static void genCmp (operand *left,operand *right,
4352 operand *result, iCode *ifx, int sign)
4365 assert (left && right);
4366 assert (AOP_SIZE(left) == AOP_SIZE(right));
4368 size = AOP_SIZE(right) - 1;
4369 mask = (0x100UL << (size*8)) - 1;
4370 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4375 resolveIfx (&rIfx, ifx);
4377 /* handle for special cases */
4378 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4381 /**********************************************************************
4382 * handle bits - bit compares are promoted to int compares seemingly! *
4383 **********************************************************************/
4385 // THIS IS COMPLETELY UNTESTED!
4386 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4387 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4388 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4389 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4392 // 1 < {0,1} is false --> clear C by skipping the next instruction
4393 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4394 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4395 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4396 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4397 emitCLRC; // only skipped for left=0 && right=1
4399 goto correct_result_in_carry;
4403 /*************************************************
4404 * make sure that left is register (or the like) *
4405 *************************************************/
4406 if (!isAOP_REGlike(left)) {
4407 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4408 assert (isAOP_LIT(left));
4409 assert (isAOP_REGlike(right));
4410 // swap left and right
4411 // left < right <==> right > left <==> (right >= left + 1)
4412 lit = ulFromVal (AOP(left)->aopu.aop_lit);
4414 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4415 // MAXVALUE < right? always false
4416 if (performedLt) emitCLRC; else emitSETC;
4417 goto correct_result_in_carry;
4420 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4421 // that's why we handled it above.
4428 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4429 } else if (isAOP_LIT(right)) {
4430 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4433 assert (isAOP_REGlike(left)); // left must be register or the like
4434 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4436 /*************************************************
4437 * special cases go here *
4438 *************************************************/
4440 if (isAOP_LIT(right)) {
4442 // unsigned comparison to a literal
4443 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4445 // unsigned left < 0? always false
4446 if (performedLt) emitCLRC; else emitSETC;
4447 goto correct_result_in_carry;
4450 // signed comparison to a literal
4451 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4452 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4453 // signed left < 0x80000000? always false
4454 if (performedLt) emitCLRC; else emitSETC;
4455 goto correct_result_in_carry;
4456 } else if (lit == 0) {
4457 // compare left < 0; set CARRY if SIGNBIT(left) is set
4458 if (performedLt) emitSETC; else emitCLRC;
4459 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4460 if (performedLt) emitCLRC; else emitSETC;
4461 goto correct_result_in_carry;
4464 } // right is literal
4466 /*************************************************
4467 * perform a general case comparison *
4468 * make sure we get CARRY==1 <==> left >= right *
4469 *************************************************/
4470 // compare most significant bytes
4471 //DEBUGpc ("comparing bytes at offset %d", size);
4473 // unsigned comparison
4474 mov2w_regOrLit (AOP(right), lit, size);
4475 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4477 // signed comparison
4478 // (add 2^n to both operands then perform an unsigned comparison)
4479 if (isAOP_LIT(right)) {
4480 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4481 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4483 if (litbyte == 0x80) {
4484 // left >= 0x80 -- always true, but more bytes to come
4485 pic16_mov2w (AOP(left), size);
4486 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4489 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4490 pic16_mov2w (AOP(left), size);
4491 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4492 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4495 /* using PRODL as a temporary register here */
4496 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4497 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4498 pic16_mov2w (AOP(left), size);
4499 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4500 pic16_emitpcode (POC_MOVWF, pctemp);
4501 pic16_mov2w (AOP(right), size);
4502 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4503 pic16_emitpcode (POC_SUBFW, pctemp);
4504 //pic16_popReleaseTempReg(pctemp, 1);
4508 // compare remaining bytes (treat as unsigned case from above)
4509 templbl = newiTempLabel ( NULL );
4512 //DEBUGpc ("comparing bytes at offset %d", offs);
4513 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4514 mov2w_regOrLit (AOP(right), lit, offs);
4515 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4517 pic16_emitpLabel (templbl->key);
4518 goto result_in_carry;
4522 /****************************************************
4523 * now CARRY contains the result of the comparison: *
4524 * SUBWF sets CARRY iff *
4525 * F-W >= 0 <==> F >= W <==> !(F < W) *
4526 * (F=left, W=right) *
4527 ****************************************************/
4530 if (result && AOP_TYPE(result) != AOP_CRY) {
4531 // value will be stored
4534 // value wil only be used in the following genSkipc()
4535 rIfx.condition ^= 1;
4539 correct_result_in_carry:
4541 // assign result to variable (if neccessary)
4542 if (result && AOP_TYPE(result) != AOP_CRY) {
4543 //DEBUGpc ("assign result");
4544 size = AOP_SIZE(result);
4546 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4548 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4551 // perform conditional jump
4553 //DEBUGpc ("generate control flow");
4559 /*-----------------------------------------------------------------*/
4560 /* genCmpGt :- greater than comparison */
4561 /*-----------------------------------------------------------------*/
4562 static void genCmpGt (iCode *ic, iCode *ifx)
4564 operand *left, *right, *result;
4565 sym_link *letype , *retype;
4571 right= IC_RIGHT(ic);
4572 result = IC_RESULT(ic);
4574 letype = getSpec(operandType(left));
4575 retype =getSpec(operandType(right));
4576 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4577 /* assign the amsops */
4578 pic16_aopOp (left,ic,FALSE);
4579 pic16_aopOp (right,ic,FALSE);
4580 pic16_aopOp (result,ic,TRUE);
4582 genCmp(right, left, result, ifx, sign);
4584 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4585 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4586 pic16_freeAsmop(result,NULL,ic,TRUE);
4589 /*-----------------------------------------------------------------*/
4590 /* genCmpLt - less than comparisons */
4591 /*-----------------------------------------------------------------*/
4592 static void genCmpLt (iCode *ic, iCode *ifx)
4594 operand *left, *right, *result;
4595 sym_link *letype , *retype;
4601 right= IC_RIGHT(ic);
4602 result = IC_RESULT(ic);
4604 letype = getSpec(operandType(left));
4605 retype =getSpec(operandType(right));
4606 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4608 /* assign the amsops */
4609 pic16_aopOp (left,ic,FALSE);
4610 pic16_aopOp (right,ic,FALSE);
4611 pic16_aopOp (result,ic,TRUE);
4613 genCmp(left, right, result, ifx, sign);
4615 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4616 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4617 pic16_freeAsmop(result,NULL,ic,TRUE);
4620 /*-----------------------------------------------------------------*/
4621 /* pic16_isLitOp - check if operand has to be treated as literal */
4622 /*-----------------------------------------------------------------*/
4623 bool pic16_isLitOp(operand *op)
4625 return ((AOP_TYPE(op) == AOP_LIT)
4626 || ( (AOP_TYPE(op) == AOP_PCODE)
4627 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4628 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4631 /*-----------------------------------------------------------------*/
4632 /* pic16_isLitAop - check if operand has to be treated as literal */
4633 /*-----------------------------------------------------------------*/
4634 bool pic16_isLitAop(asmop *aop)
4636 return ((aop->type == AOP_LIT)
4637 || ( (aop->type == AOP_PCODE)
4638 && ( (aop->aopu.pcop->type == PO_LITERAL)
4639 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4644 /*-----------------------------------------------------------------*/
4645 /* genCmpEq - generates code for equal to */
4646 /*-----------------------------------------------------------------*/
4647 static void genCmpEq (iCode *ic, iCode *ifx)
4649 operand *left, *right, *result;
4650 symbol *falselbl = newiTempLabel(NULL);
4651 symbol *donelbl = newiTempLabel(NULL);
4653 int preserve_result = 0;
4654 int generate_result = 0;
4656 unsigned long lit = -1;
4660 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4661 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4662 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4664 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4666 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4668 werror(W_POSSBUG2, __FILE__, __LINE__);
4669 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4670 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4674 if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4676 operand *tmp = right ;
4681 if (AOP_TYPE(right) == AOP_LIT) {
4682 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4685 if ( regsInCommon(left, result) || regsInCommon(right, result) )
4686 preserve_result = 1;
4688 if(result && AOP_SIZE(result))
4689 generate_result = 1;
4691 if(generate_result && !preserve_result)
4693 for(i = 0; i < AOP_SIZE(result); i++)
4694 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4697 assert( AOP_SIZE(left) == AOP_SIZE(right) );
4698 for(i=0; i < AOP_SIZE(left); i++)
4700 if(AOP_TYPE(left) != AOP_ACC)
4702 if(pic16_isLitOp(left))
4703 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4705 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4707 if(pic16_isLitOp(right)) {
4708 if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4709 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4712 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4714 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4719 if(generate_result && preserve_result)
4721 for(i = 0; i < AOP_SIZE(result); i++)
4722 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4726 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4728 if(generate_result && preserve_result)
4729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4731 if(ifx && IC_TRUE(ifx))
4732 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4734 if(ifx && IC_FALSE(ifx))
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4737 pic16_emitpLabel(falselbl->key);
4741 if(ifx && IC_FALSE(ifx))
4742 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4744 if(generate_result && preserve_result)
4746 for(i = 0; i < AOP_SIZE(result); i++)
4747 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4750 pic16_emitpLabel(donelbl->key);
4756 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4757 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4758 pic16_freeAsmop(result,NULL,ic,TRUE);
4764 // old version kept for reference
4766 /*-----------------------------------------------------------------*/
4767 /* genCmpEq - generates code for equal to */
4768 /*-----------------------------------------------------------------*/
4769 static void genCmpEq (iCode *ic, iCode *ifx)
4771 operand *left, *right, *result;
4772 unsigned long lit = 0L;
4774 symbol *falselbl = newiTempLabel(NULL);
4777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4780 DEBUGpic16_emitcode ("; ifx is non-null","");
4782 DEBUGpic16_emitcode ("; ifx is null","");
4784 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4785 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4786 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4788 size = max(AOP_SIZE(left),AOP_SIZE(right));
4790 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4792 /* if literal, literal on the right or
4793 if the right is in a pointer register and left
4795 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4796 operand *tmp = right ;
4802 if(ifx && !AOP_SIZE(result)){
4804 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
4805 /* if they are both bit variables */
4806 if (AOP_TYPE(left) == AOP_CRY &&
4807 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4808 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
4809 if(AOP_TYPE(right) == AOP_LIT){
4810 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4812 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4813 pic16_emitcode("cpl","c");
4814 } else if(lit == 1L) {
4815 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4817 pic16_emitcode("clr","c");
4819 /* AOP_TYPE(right) == AOP_CRY */
4821 symbol *lbl = newiTempLabel(NULL);
4822 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4823 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4824 pic16_emitcode("cpl","c");
4825 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4827 /* if true label then we jump if condition
4829 tlbl = newiTempLabel(NULL);
4830 if ( IC_TRUE(ifx) ) {
4831 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4832 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4834 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4835 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4837 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4840 /* left and right are both bit variables, result is carry */
4843 resolveIfx(&rIfx,ifx);
4845 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4846 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4847 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4848 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4853 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
4855 /* They're not both bit variables. Is the right a literal? */
4856 if(AOP_TYPE(right) == AOP_LIT) {
4857 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4862 switch(lit & 0xff) {
4864 if ( IC_TRUE(ifx) ) {
4865 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4867 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4869 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4870 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4874 if ( IC_TRUE(ifx) ) {
4875 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4877 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4879 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4880 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4884 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4886 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4891 /* end of size == 1 */
4895 genc16bit2lit(left,lit,offset);
4898 /* end of size == 2 */
4903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4904 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4905 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4906 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4909 /* search for patterns that can be optimized */
4911 genc16bit2lit(left,lit,0);
4915 emitSKPZ; // if hi word unequal
4917 emitSKPNZ; // if hi word equal
4919 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4920 genc16bit2lit(left,lit,2);
4923 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4924 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4928 pic16_emitpLabel(falselbl->key);
4937 } else if(AOP_TYPE(right) == AOP_CRY ) {
4938 /* we know the left is not a bit, but that the right is */
4939 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4940 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4941 pic16_popGet(AOP(right),offset));
4942 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4944 /* if the two are equal, then W will be 0 and the Z bit is set
4945 * we could test Z now, or go ahead and check the high order bytes if
4946 * the variable we're comparing is larger than a byte. */
4949 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4951 if ( IC_TRUE(ifx) ) {
4953 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4954 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4957 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4958 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4962 /* They're both variables that are larger than bits */
4965 tlbl = newiTempLabel(NULL);
4968 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4969 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4971 if ( IC_TRUE(ifx) ) {
4975 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4977 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4978 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4982 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
4985 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4986 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4991 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
4993 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4994 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4998 if(s>1 && IC_TRUE(ifx)) {
4999 pic16_emitpLabel(tlbl->key);
5000 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5004 /* mark the icode as generated */
5009 /* if they are both bit variables */
5010 if (AOP_TYPE(left) == AOP_CRY &&
5011 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5012 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5013 if(AOP_TYPE(right) == AOP_LIT){
5014 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5016 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5017 pic16_emitcode("cpl","c");
5018 } else if(lit == 1L) {
5019 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5021 pic16_emitcode("clr","c");
5023 /* AOP_TYPE(right) == AOP_CRY */
5025 symbol *lbl = newiTempLabel(NULL);
5026 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5027 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5028 pic16_emitcode("cpl","c");
5029 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5032 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5033 pic16_outBitC(result);
5037 genIfxJump (ifx,"c");
5040 /* if the result is used in an arithmetic operation
5041 then put the result in place */
5042 pic16_outBitC(result);
5045 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5046 gencjne(left,right,result,ifx);
5049 gencjne(left,right,newiTempLabel(NULL));
5051 if(IC_TRUE(ifx)->key)
5052 gencjne(left,right,IC_TRUE(ifx)->key);
5054 gencjne(left,right,IC_FALSE(ifx)->key);
5058 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5059 pic16_aopPut(AOP(result),"a",0);
5064 genIfxJump (ifx,"a");
5068 /* if the result is used in an arithmetic operation
5069 then put the result in place */
5071 if (AOP_TYPE(result) != AOP_CRY)
5072 pic16_outAcc(result);
5074 /* leave the result in acc */
5078 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5079 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5080 pic16_freeAsmop(result,NULL,ic,TRUE);
5084 /*-----------------------------------------------------------------*/
5085 /* ifxForOp - returns the icode containing the ifx for operand */
5086 /*-----------------------------------------------------------------*/
5087 static iCode *ifxForOp ( operand *op, iCode *ic )
5091 /* if true symbol then needs to be assigned */
5092 if (IS_TRUE_SYMOP(op))
5095 /* if this has register type condition and
5096 the next instruction is ifx with the same operand
5097 and live to of the operand is upto the ifx only then */
5099 && ic->next->op == IFX
5100 && IC_COND(ic->next)->key == op->key
5101 && OP_SYMBOL(op)->liveTo <= ic->next->seq
5103 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5109 ic->next->op == IFX &&
5110 IC_COND(ic->next)->key == op->key) {
5111 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5116 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5118 ic->next->op == IFX)
5119 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5122 ic->next->op == IFX &&
5123 IC_COND(ic->next)->key == op->key) {
5124 DEBUGpic16_emitcode ("; "," key is okay");
5125 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5126 OP_SYMBOL(op)->liveTo,
5131 /* the code below is completely untested
5132 * it just allows ulong2fs.c compile -- VR */
5135 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5136 __FILE__, __FUNCTION__, __LINE__);
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 )
5148 ic->next->op == IFX &&
5149 IC_COND(ic->next)->key == op->key) {
5150 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5154 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5155 __FILE__, __FUNCTION__, __LINE__);
5157 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
5162 /*-----------------------------------------------------------------*/
5163 /* genAndOp - for && operation */
5164 /*-----------------------------------------------------------------*/
5165 static void genAndOp (iCode *ic)
5167 operand *left,*right, *result;
5172 /* note here that && operations that are in an
5173 if statement are taken away by backPatchLabels
5174 only those used in arthmetic operations remain */
5175 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5176 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5177 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5179 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5181 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5182 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5183 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5185 /* if both are bit variables */
5186 /* if (AOP_TYPE(left) == AOP_CRY && */
5187 /* AOP_TYPE(right) == AOP_CRY ) { */
5188 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5189 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5190 /* pic16_outBitC(result); */
5192 /* tlbl = newiTempLabel(NULL); */
5193 /* pic16_toBoolean(left); */
5194 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5195 /* pic16_toBoolean(right); */
5196 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5197 /* pic16_outBitAcc(result); */
5200 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5201 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5202 pic16_freeAsmop(result,NULL,ic,TRUE);
5206 /*-----------------------------------------------------------------*/
5207 /* genOrOp - for || operation */
5208 /*-----------------------------------------------------------------*/
5211 modified this code, but it doesn't appear to ever get called
5214 static void genOrOp (iCode *ic)
5216 operand *left,*right, *result;
5221 /* note here that || operations that are in an
5222 if statement are taken away by backPatchLabels
5223 only those used in arthmetic operations remain */
5224 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5225 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5226 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5228 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5230 /* if both are bit variables */
5231 if (AOP_TYPE(left) == AOP_CRY &&
5232 AOP_TYPE(right) == AOP_CRY ) {
5233 pic16_emitcode("clrc","");
5234 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5235 AOP(left)->aopu.aop_dir,
5236 AOP(left)->aopu.aop_dir);
5237 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5238 AOP(right)->aopu.aop_dir,
5239 AOP(right)->aopu.aop_dir);
5240 pic16_emitcode("setc","");
5243 tlbl = newiTempLabel(NULL);
5244 pic16_toBoolean(left);
5246 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5247 pic16_toBoolean(right);
5248 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5250 pic16_outBitAcc(result);
5253 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5254 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5255 pic16_freeAsmop(result,NULL,ic,TRUE);
5258 /*-----------------------------------------------------------------*/
5259 /* isLiteralBit - test if lit == 2^n */
5260 /*-----------------------------------------------------------------*/
5261 static int isLiteralBit(unsigned long lit)
5263 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5264 0x100L,0x200L,0x400L,0x800L,
5265 0x1000L,0x2000L,0x4000L,0x8000L,
5266 0x10000L,0x20000L,0x40000L,0x80000L,
5267 0x100000L,0x200000L,0x400000L,0x800000L,
5268 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5269 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5272 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5273 for(idx = 0; idx < 32; idx++)
5279 /*-----------------------------------------------------------------*/
5280 /* continueIfTrue - */
5281 /*-----------------------------------------------------------------*/
5282 static void continueIfTrue (iCode *ic)
5286 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5290 /*-----------------------------------------------------------------*/
5292 /*-----------------------------------------------------------------*/
5293 static void jumpIfTrue (iCode *ic)
5297 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5301 /*-----------------------------------------------------------------*/
5302 /* jmpTrueOrFalse - */
5303 /*-----------------------------------------------------------------*/
5304 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5306 // ugly but optimized by peephole
5309 symbol *nlbl = newiTempLabel(NULL);
5310 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5311 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5312 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5313 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5315 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5316 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5321 /*-----------------------------------------------------------------*/
5322 /* genAnd - code for and */
5323 /*-----------------------------------------------------------------*/
5324 static void genAnd (iCode *ic, iCode *ifx)
5326 operand *left, *right, *result;
5327 int size, offset = 0;
5328 unsigned long lit = 0L;
5333 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5334 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5335 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5337 resolveIfx (&rIfx, ifx);
5339 /* if left is a literal & right is not then exchange them */
5340 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5341 AOP_NEEDSACC (left))
5343 operand *tmp = right;
5348 /* if result = right then exchange them */
5349 if (pic16_sameRegs (AOP (result), AOP (right)))
5351 operand *tmp = right;
5356 /* if right is bit then exchange them */
5357 if (AOP_TYPE (right) == AOP_CRY &&
5358 AOP_TYPE (left) != AOP_CRY)
5360 operand *tmp = right;
5365 if (AOP_TYPE (right) == AOP_LIT)
5366 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5368 size = AOP_SIZE (result);
5370 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5373 // result = bit & yy;
5374 if (AOP_TYPE(left) == AOP_CRY){
5375 // c = bit & literal;
5376 if(AOP_TYPE(right) == AOP_LIT){
5378 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5381 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5384 if(size && (AOP_TYPE(result) == AOP_CRY)){
5385 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5388 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5392 pic16_emitcode("clr","c");
5395 if (AOP_TYPE(right) == AOP_CRY){
5397 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5398 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5401 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5403 pic16_emitcode("rrc","a");
5404 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5410 pic16_outBitC(result);
5412 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5413 genIfxJump(ifx, "c");
5417 // if (val & 0xZZ) - size = 0, ifx != FALSE -
5418 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5419 if ((AOP_TYPE (right) == AOP_LIT) &&
5420 (AOP_TYPE (result) == AOP_CRY) &&
5421 (AOP_TYPE (left) != AOP_CRY))
5423 symbol *tlbl = newiTempLabel (NULL);
5424 int sizel = AOP_SIZE (left);
5431 /* get number of non null bytes in literal */
5434 if (lit & (0xff << (sizel * 8)))
5438 emitBra = nonnull || rIfx.condition;
5440 for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5442 unsigned char bytelit = lit;
5450 /* patch provided by Aaron Colwell */
5451 if ((posbit = isLiteralBit (bytelit)) != 0)
5455 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5456 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5460 pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5465 if (bytelit == 0xff)
5467 /* Aaron had a MOVF instruction here, changed to MOVFW cause
5468 * a peephole could optimize it out -- VR */
5469 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5473 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5474 pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5481 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5485 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5490 /* last non null byte */
5500 // bit = left & literal
5504 pic16_emitpLabel (tlbl->key);
5507 // if(left & literal)
5513 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
5516 pic16_emitpLabel (tlbl->key);
5519 pic16_outBitC (result);
5523 /* if left is same as result */
5524 if(pic16_sameRegs(AOP(result),AOP(left))){
5526 for(;size--; offset++,lit>>=8) {
5527 if(AOP_TYPE(right) == AOP_LIT){
5528 switch(lit & 0xff) {
5530 /* and'ing with 0 has clears the result */
5531 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5532 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5535 /* and'ing with 0xff is a nop when the result and left are the same */
5540 int p = pic16_my_powof2( (~lit) & 0xff );
5542 /* only one bit is set in the literal, so use a bcf instruction */
5543 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5544 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5547 pic16_emitcode("movlw","0x%x", (lit & 0xff));
5548 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5549 if(know_W != (lit&0xff))
5550 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5552 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5557 if (AOP_TYPE(left) == AOP_ACC) {
5558 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5560 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5561 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5568 // left & result in different registers
5569 if(AOP_TYPE(result) == AOP_CRY){
5571 // if(size), result in bit
5572 // if(!size && ifx), conditional oper: if(left & right)
5573 symbol *tlbl = newiTempLabel(NULL);
5574 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5576 pic16_emitcode("setb","c");
5578 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5579 pic16_emitcode("anl","a,%s",
5580 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5581 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5586 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5587 pic16_outBitC(result);
5589 jmpTrueOrFalse(ifx, tlbl);
5591 for(;(size--);offset++) {
5593 // result = left & right
5594 if(AOP_TYPE(right) == AOP_LIT){
5595 int t = (lit >> (offset*8)) & 0x0FFL;
5598 pic16_emitcode("clrf","%s",
5599 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5600 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5603 pic16_emitcode("movf","%s,w",
5604 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5605 pic16_emitcode("movwf","%s",
5606 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5607 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5608 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5611 pic16_emitcode("movlw","0x%x",t);
5612 pic16_emitcode("andwf","%s,w",
5613 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5614 pic16_emitcode("movwf","%s",
5615 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5617 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5618 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5619 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5624 if (AOP_TYPE(left) == AOP_ACC) {
5625 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5626 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5628 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5629 pic16_emitcode("andwf","%s,w",
5630 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5631 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5632 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5634 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5635 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5641 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5642 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5643 pic16_freeAsmop(result,NULL,ic,TRUE);
5646 /*-----------------------------------------------------------------*/
5647 /* genOr - code for or */
5648 /*-----------------------------------------------------------------*/
5649 static void genOr (iCode *ic, iCode *ifx)
5651 operand *left, *right, *result;
5652 int size, offset = 0;
5653 unsigned long lit = 0L;
5658 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5659 pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5660 pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5662 resolveIfx (&rIfx, ifx);
5664 /* if left is a literal & right is not then exchange them */
5665 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5666 AOP_NEEDSACC (left))
5668 operand *tmp = right;
5673 /* if result = right then exchange them */
5674 if (pic16_sameRegs (AOP (result), AOP (right)))
5676 operand *tmp = right;
5681 /* if right is bit then exchange them */
5682 if (AOP_TYPE (right) == AOP_CRY &&
5683 AOP_TYPE (left) != AOP_CRY)
5685 operand *tmp = right;
5690 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5692 if (AOP_TYPE (right) == AOP_LIT)
5693 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5695 size = AOP_SIZE (result);
5699 if (AOP_TYPE(left) == AOP_CRY){
5700 if(AOP_TYPE(right) == AOP_LIT){
5701 // c = bit & literal;
5703 // lit != 0 => result = 1
5704 if(AOP_TYPE(result) == AOP_CRY){
5706 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5707 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5708 // AOP(result)->aopu.aop_dir,
5709 // AOP(result)->aopu.aop_dir);
5711 continueIfTrue(ifx);
5715 // lit == 0 => result = left
5716 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5718 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5721 if (AOP_TYPE(right) == AOP_CRY){
5722 if(pic16_sameRegs(AOP(result),AOP(left))){
5724 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5725 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5726 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5728 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5729 AOP(result)->aopu.aop_dir,
5730 AOP(result)->aopu.aop_dir);
5731 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5732 AOP(right)->aopu.aop_dir,
5733 AOP(right)->aopu.aop_dir);
5734 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5735 AOP(result)->aopu.aop_dir,
5736 AOP(result)->aopu.aop_dir);
5738 if( AOP_TYPE(result) == AOP_ACC) {
5739 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5740 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5741 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5742 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5746 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5747 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5748 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5749 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5751 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5752 AOP(result)->aopu.aop_dir,
5753 AOP(result)->aopu.aop_dir);
5754 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5755 AOP(right)->aopu.aop_dir,
5756 AOP(right)->aopu.aop_dir);
5757 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5758 AOP(left)->aopu.aop_dir,
5759 AOP(left)->aopu.aop_dir);
5760 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5761 AOP(result)->aopu.aop_dir,
5762 AOP(result)->aopu.aop_dir);
5767 symbol *tlbl = newiTempLabel(NULL);
5768 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5771 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5772 if( AOP_TYPE(right) == AOP_ACC) {
5773 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5775 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5776 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5781 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5782 pic16_emitcode(";XXX setb","c");
5783 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5784 AOP(left)->aopu.aop_dir,tlbl->key+100);
5785 pic16_toBoolean(right);
5786 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5787 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5788 jmpTrueOrFalse(ifx, tlbl);
5792 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5799 pic16_outBitC(result);
5801 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5802 genIfxJump(ifx, "c");
5806 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5807 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5808 if ((AOP_TYPE (right) == AOP_LIT) &&
5809 (AOP_TYPE (result) == AOP_CRY) &&
5810 (AOP_TYPE (left) != AOP_CRY))
5815 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5824 /* if left is same as result */
5825 if(pic16_sameRegs(AOP(result),AOP(left))){
5827 for(;size--; offset++,lit>>=8) {
5828 if(AOP_TYPE(right) == AOP_LIT){
5829 if((lit & 0xff) == 0)
5830 /* or'ing with 0 has no effect */
5833 int p = pic16_my_powof2(lit & 0xff);
5835 /* only one bit is set in the literal, so use a bsf instruction */
5836 pic16_emitpcode(POC_BSF,
5837 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5839 if(know_W != (lit & 0xff))
5840 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5841 know_W = lit & 0xff;
5842 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5847 if (AOP_TYPE(left) == AOP_ACC) {
5848 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
5849 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5851 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5852 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5854 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5855 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5861 // left & result in different registers
5862 if(AOP_TYPE(result) == AOP_CRY){
5864 // if(size), result in bit
5865 // if(!size && ifx), conditional oper: if(left | right)
5866 symbol *tlbl = newiTempLabel(NULL);
5867 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5868 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5872 pic16_emitcode(";XXX setb","c");
5874 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5875 pic16_emitcode(";XXX orl","a,%s",
5876 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5877 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5882 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5883 pic16_outBitC(result);
5885 jmpTrueOrFalse(ifx, tlbl);
5886 } else for(;(size--);offset++){
5888 // result = left & right
5889 if(AOP_TYPE(right) == AOP_LIT){
5890 int t = (lit >> (offset*8)) & 0x0FFL;
5893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
5894 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5896 // pic16_emitcode("movf","%s,w",
5897 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5898 // pic16_emitcode("movwf","%s",
5899 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5902 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5903 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5906 // pic16_emitcode("movlw","0x%x",t);
5907 // pic16_emitcode("iorwf","%s,w",
5908 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5909 // pic16_emitcode("movwf","%s",
5910 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5916 // faster than result <- left, anl result,right
5917 // and better if result is SFR
5918 if (AOP_TYPE(left) == AOP_ACC) {
5919 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
5920 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5922 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5923 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5925 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5926 // pic16_emitcode("iorwf","%s,w",
5927 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5930 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5935 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5936 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5937 pic16_freeAsmop(result,NULL,ic,TRUE);
5940 /*-----------------------------------------------------------------*/
5941 /* genXor - code for xclusive or */
5942 /*-----------------------------------------------------------------*/
5943 static void genXor (iCode *ic, iCode *ifx)
5945 operand *left, *right, *result;
5946 int size, offset = 0;
5947 unsigned long lit = 0L;
5952 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5953 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5954 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5956 resolveIfx (&rIfx,ifx);
5958 /* if left is a literal & right is not ||
5959 if left needs acc & right does not */
5960 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5961 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5963 operand *tmp = right;
5968 /* if result = right then exchange them */
5969 if (pic16_sameRegs (AOP (result), AOP (right)))
5971 operand *tmp = right ;
5976 /* if right is bit then exchange them */
5977 if (AOP_TYPE (right) == AOP_CRY &&
5978 AOP_TYPE (left) != AOP_CRY)
5980 operand *tmp = right ;
5985 if (AOP_TYPE (right) == AOP_LIT)
5986 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5988 size = AOP_SIZE (result);
5992 if (AOP_TYPE(left) == AOP_CRY)
5994 if (AOP_TYPE(right) == AOP_LIT)
5996 // c = bit & literal;
5999 // lit>>1 != 0 => result = 1
6000 if (AOP_TYPE(result) == AOP_CRY)
6004 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
6005 pic16_emitcode("setb", "%s", AOP(result)->aopu.aop_dir);
6008 continueIfTrue(ifx);
6011 pic16_emitcode("setb", "c");
6018 // lit == 0, result = left
6019 if (size && pic16_sameRegs(AOP(result), AOP(left)))
6021 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6025 // lit == 1, result = not(left)
6026 if (size && pic16_sameRegs(AOP(result), AOP(left)))
6028 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6029 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6030 pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6035 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6036 pic16_emitcode("cpl", "c");
6044 symbol *tlbl = newiTempLabel(NULL);
6045 if (AOP_TYPE(right) == AOP_CRY)
6048 pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6052 int sizer = AOP_SIZE(right);
6054 // if val>>1 != 0, result = 1
6055 pic16_emitcode("setb", "c");
6058 MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6060 // test the msb of the lsb
6061 pic16_emitcode("anl", "a,#0xfe");
6062 pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6066 pic16_emitcode("rrc", "a");
6068 pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6069 pic16_emitcode("cpl", "c");
6070 pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6075 pic16_outBitC(result);
6077 else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6078 genIfxJump(ifx, "c");
6082 // if(val ^ 0xZZ) - size = 0, ifx != FALSE -
6083 // bit = val ^ 0xZZ - size = 1, ifx = FALSE -
6084 if ((AOP_TYPE (right) == AOP_LIT) &&
6085 (AOP_TYPE (result) == AOP_CRY) &&
6086 (AOP_TYPE (left) != AOP_CRY))
6088 symbol *tlbl = newiTempLabel (NULL);
6094 for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6096 unsigned char bytelit = lit;
6101 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6105 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6109 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6110 pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6118 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6122 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6127 /* last non null byte */
6135 // bit = left ^ literal
6139 pic16_emitpLabel (tlbl->key);
6141 // if (left ^ literal)
6146 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
6149 pic16_emitpLabel (tlbl->key);
6153 pic16_outBitC (result);
6157 if (pic16_sameRegs(AOP(result), AOP(left)))
6159 /* if left is same as result */
6160 for (; size--; offset++)
6162 if (AOP_TYPE(right) == AOP_LIT)
6164 int t = (lit >> (offset * 8)) & 0x0FFL;
6169 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6170 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6175 if (AOP_TYPE(left) == AOP_ACC)
6176 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6180 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6187 // left ^ result in different registers
6188 if (AOP_TYPE(result) == AOP_CRY)
6191 // if(size), result in bit
6192 // if(!size && ifx), conditional oper: if(left ^ right)
6193 symbol *tlbl = newiTempLabel(NULL);
6194 int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6196 pic16_emitcode("setb", "c");
6199 if ((AOP_TYPE(right) == AOP_LIT) &&
6200 (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6202 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6206 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6207 pic16_emitcode("xrl", "a,%s",
6208 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6210 pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6216 pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6217 pic16_outBitC(result);
6220 jmpTrueOrFalse(ifx, tlbl);
6224 for (; (size--); offset++)
6227 // result = left ^ right
6228 if (AOP_TYPE(right) == AOP_LIT)
6230 int t = (lit >> (offset * 8)) & 0x0FFL;
6234 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6235 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6236 pic16_emitcode("movf", "%s,w",
6237 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6238 pic16_emitcode("movwf", "%s",
6239 pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6243 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6244 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6245 pic16_emitcode("comf", "%s,w",
6246 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6247 pic16_emitcode("movwf", "%s",
6248 pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6252 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6253 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6255 pic16_emitcode("movlw", "0x%x", t);
6256 pic16_emitcode("xorwf", "%s,w",
6257 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6258 pic16_emitcode("movwf", "%s",
6259 pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6265 // faster than result <- left, anl result,right
6266 // and better if result is SFR
6267 if (AOP_TYPE(left) == AOP_ACC)
6269 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6270 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6274 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6275 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6276 pic16_emitcode("movf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6277 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6279 if ( AOP_TYPE(result) != AOP_ACC)
6281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6282 pic16_emitcode("movwf", "%s", pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6289 pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6290 pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6291 pic16_freeAsmop(result, NULL, ic, TRUE);
6294 /*-----------------------------------------------------------------*/
6295 /* genInline - write the inline code out */
6296 /*-----------------------------------------------------------------*/
6297 static void genInline (iCode *ic)
6299 char *buffer, *bp, *bp1;
6300 bool inComment = FALSE;
6302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6304 _G.inLine += (!options.asmpeep);
6306 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6308 while((bp1=strstr(bp, "\\n"))) {
6316 /* This is an experimental code for #pragma inline
6317 and is temporarily disabled for 2.5.0 release */
6325 cbuf = Safe_strdup(buffer);
6326 cblen = strlen(buffer)+1;
6327 memset(cbuf, 0, cblen);
6332 if(*bp != '%')*bp1++ = *bp++;
6338 if(i>elementsInSet(asmInlineMap))break;
6341 s = indexSet(asmInlineMap, i);
6342 DEBUGpc("searching symbol s = `%s'", s);
6343 sym = findSym(SymbolTab, NULL, s);
6346 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6348 strcat(bp1, sym->rname);
6354 if(strlen(bp1) > cblen - 16) {
6355 int i = strlen(cbuf);
6357 cbuf = realloc(cbuf, cblen);
6358 memset(cbuf+i, 0, 50);
6364 buffer = Safe_strdup( cbuf );
6371 /* emit each line as a code */
6385 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6390 /* Add \n for labels, not dirs such as c:\mydir */
6391 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6396 /* print label, use this special format with NULL directive
6397 * to denote that the argument should not be indented with tab */
6398 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6407 if ((bp1 != bp) && *bp1)
6408 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6412 _G.inLine -= (!options.asmpeep);
6415 /*-----------------------------------------------------------------*/
6416 /* genRRC - rotate right with carry */
6417 /*-----------------------------------------------------------------*/
6418 static void genRRC (iCode *ic)
6420 operand *left , *result ;
6421 int size, offset = 0, same;
6423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6425 /* rotate right with carry */
6427 result=IC_RESULT(ic);
6428 pic16_aopOp (left,ic,FALSE);
6429 pic16_aopOp (result,ic,TRUE);
6431 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6433 same = pic16_sameRegs(AOP(result),AOP(left));
6435 size = AOP_SIZE(result);
6437 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6439 /* get the lsb and put it into the carry */
6440 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6447 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6450 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6456 pic16_freeAsmop(left,NULL,ic,TRUE);
6457 pic16_freeAsmop(result,NULL,ic,TRUE);
6460 /*-----------------------------------------------------------------*/
6461 /* genRLC - generate code for rotate left with carry */
6462 /*-----------------------------------------------------------------*/
6463 static void genRLC (iCode *ic)
6465 operand *left , *result ;
6466 int size, offset = 0;
6469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6470 /* rotate right with carry */
6472 result=IC_RESULT(ic);
6473 pic16_aopOp (left,ic,FALSE);
6474 pic16_aopOp (result,ic,TRUE);
6476 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6478 same = pic16_sameRegs(AOP(result),AOP(left));
6480 /* move it to the result */
6481 size = AOP_SIZE(result);
6483 /* get the msb and put it into the carry */
6484 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6491 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6493 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6501 pic16_freeAsmop(left,NULL,ic,TRUE);
6502 pic16_freeAsmop(result,NULL,ic,TRUE);
6506 /* gpasm can get the highest order bit with HIGH/UPPER
6507 * so the following probably is not needed -- VR */
6509 /*-----------------------------------------------------------------*/
6510 /* genGetHbit - generates code get highest order bit */
6511 /*-----------------------------------------------------------------*/
6512 static void genGetHbit (iCode *ic)
6514 operand *left, *result;
6516 result=IC_RESULT(ic);
6517 pic16_aopOp (left,ic,FALSE);
6518 pic16_aopOp (result,ic,FALSE);
6520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6521 /* get the highest order byte into a */
6522 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6523 if(AOP_TYPE(result) == AOP_CRY){
6524 pic16_emitcode("rlc","a");
6525 pic16_outBitC(result);
6528 pic16_emitcode("rl","a");
6529 pic16_emitcode("anl","a,#0x01");
6530 pic16_outAcc(result);
6534 pic16_freeAsmop(left,NULL,ic,TRUE);
6535 pic16_freeAsmop(result,NULL,ic,TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* AccRol - rotate left accumulator by known count */
6541 /*-----------------------------------------------------------------*/
6542 static void AccRol (int shCount)
6544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6545 shCount &= 0x0007; // shCount : 0..7
6550 pic16_emitcode("rl","a");
6553 pic16_emitcode("rl","a");
6554 pic16_emitcode("rl","a");
6557 pic16_emitcode("swap","a");
6558 pic16_emitcode("rr","a");
6561 pic16_emitcode("swap","a");
6564 pic16_emitcode("swap","a");
6565 pic16_emitcode("rl","a");
6568 pic16_emitcode("rr","a");
6569 pic16_emitcode("rr","a");
6572 pic16_emitcode("rr","a");
6578 /*-----------------------------------------------------------------*/
6579 /* AccLsh - left shift accumulator by known count */
6580 /*-----------------------------------------------------------------*/
6581 static void AccLsh (int shCount, int doMask)
6583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6589 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6592 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6593 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6596 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6600 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6603 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6604 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6607 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6611 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6615 /* no masking is required in genPackBits */
6616 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6620 /*-----------------------------------------------------------------*/
6621 /* AccRsh - right shift accumulator by known count */
6622 /*-----------------------------------------------------------------*/
6623 static void AccRsh (int shCount, int andmask)
6625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6626 assert ((shCount >= 0) && (shCount <= 8));
6631 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6634 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6635 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6638 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6639 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6642 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6645 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6646 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6649 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6650 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6653 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6656 // Rotating by 8 is a NOP.
6661 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6663 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6666 /*-----------------------------------------------------------------*/
6667 /* shiftR1Left2Result - shift right one byte from left to result */
6668 /*-----------------------------------------------------------------*/
6669 static void shiftR1Left2ResultSigned (operand *left, int offl,
6670 operand *result, int offr,
6675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6676 assert ((shCount >= 0) && (shCount <= 8));
6678 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6680 /* Do NOT use result for intermediate results, it might be an SFR!. */
6684 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6685 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6690 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6692 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6694 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6700 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6701 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6702 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6703 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6704 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6709 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6710 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6711 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6712 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6713 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6718 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6719 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6720 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6721 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6722 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6726 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6727 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6728 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6729 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6730 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6735 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6736 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6737 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6738 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6739 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6740 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6744 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6745 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6746 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6751 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6756 /*-----------------------------------------------------------------*/
6757 /* shiftR1Left2Result - shift right one byte from left to result */
6758 /*-----------------------------------------------------------------*/
6759 static void shiftR1Left2Result (operand *left, int offl,
6760 operand *result, int offr,
6761 int shCount, int sign)
6765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6766 assert ((shCount >= 0) && (shCount <= 8));
6768 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6770 /* Copy the msb into the carry if signed. */
6772 shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6776 /* Do NOT use result for intermediate results, it might be an SFR!. */
6780 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6788 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6790 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6791 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6797 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6798 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6799 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6800 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6804 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6805 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6806 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6807 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6811 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6812 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6813 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6817 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6818 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6819 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6820 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6824 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6825 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6826 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6827 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6831 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6832 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6833 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6837 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6842 /*-----------------------------------------------------------------*/
6843 /* shiftL1Left2Result - shift left one byte from left to result */
6844 /*-----------------------------------------------------------------*/
6845 static void shiftL1Left2Result (operand *left, int offl,
6846 operand *result, int offr, int shCount)
6850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6851 assert ((shCount >= 0) && (shCount <= 8));
6853 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6855 /* Do NOT use result for intermediate results, it might be an SFR!. */
6859 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6869 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6870 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6871 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6876 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6877 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6878 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6879 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6883 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6884 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6885 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6886 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6890 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6891 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6892 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6896 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6897 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6898 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6899 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6903 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6904 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6905 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6906 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6910 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6911 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6912 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6916 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6921 /*-----------------------------------------------------------------*/
6922 /* movLeft2Result - move byte from left to result */
6923 /*-----------------------------------------------------------------*/
6924 static void movLeft2Result (operand *left, int offl,
6925 operand *result, int offr)
6927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6928 if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6929 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6934 /*-----------------------------------------------------------------*/
6935 /* shiftL2Left2Result - shift left two bytes from left to result */
6936 /*-----------------------------------------------------------------*/
6937 static void shiftL2Left2Result (operand *left, int offl,
6938 operand *result, int offr, int shCount)
6940 int same = pic16_sameRegs(AOP(result), AOP(left));
6943 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6945 if (same && (offl != offr)) { // shift bytes
6948 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6949 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6951 } else { // just treat as different later on
6964 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6965 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6966 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6970 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6971 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6977 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6978 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6979 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6980 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6981 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6982 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6983 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6985 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6986 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6990 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6991 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6992 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6993 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6994 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6995 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6996 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6997 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6998 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6999 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7002 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7003 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7004 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7005 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7006 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7016 /* note, use a mov/add for the shift since the mov has a
7017 chance of getting optimized out */
7018 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7020 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7021 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7026 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7027 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7033 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7034 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7035 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7036 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7038 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
7039 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7040 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7044 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7045 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7049 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7050 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7051 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7054 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7055 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7056 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7057 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7058 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7059 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7060 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7061 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7064 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7065 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7066 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7067 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7068 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7073 /*-----------------------------------------------------------------*/
7074 /* shiftR2Left2Result - shift right two bytes from left to result */
7075 /*-----------------------------------------------------------------*/
7076 static void shiftR2Left2Result (operand *left, int offl,
7077 operand *result, int offr,
7078 int shCount, int sign)
7080 int same = pic16_sameRegs(AOP(result), AOP(left));
7082 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7084 if (same && (offl != offr)) { // shift right bytes
7087 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7088 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7090 } else { // just treat as different later on
7101 /* obtain sign from left operand */
7103 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7108 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7109 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7111 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7112 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7113 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7114 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7119 /* now get sign from already assigned result (avoid BANKSEL) */
7120 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7123 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7124 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7132 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7133 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7135 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7136 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7137 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7138 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7140 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7141 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7142 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7144 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7146 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7147 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7148 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7152 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7153 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7157 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7158 pic16_emitpcode(POC_BTFSC,
7159 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7160 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7169 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7171 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7172 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7173 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7174 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7176 pic16_emitpcode(POC_BTFSC,
7177 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7178 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7180 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7181 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7182 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7183 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7187 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7189 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7190 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7192 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7194 pic16_emitpcode(POC_BTFSC,
7195 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7196 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7198 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7199 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7206 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7207 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7209 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7212 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7214 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7219 /*-----------------------------------------------------------------*/
7220 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7221 /*-----------------------------------------------------------------*/
7222 static void shiftLLeftOrResult (operand *left, int offl,
7223 operand *result, int offr, int shCount)
7225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7227 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7228 /* shift left accumulator */
7230 /* or with result */
7231 /* back to result */
7232 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7235 /*-----------------------------------------------------------------*/
7236 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7237 /*-----------------------------------------------------------------*/
7238 static void shiftRLeftOrResult (operand *left, int offl,
7239 operand *result, int offr, int shCount)
7241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7243 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7244 /* shift right accumulator */
7246 /* or with result */
7247 /* back to result */
7248 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7251 /*-----------------------------------------------------------------*/
7252 /* genlshOne - left shift a one byte quantity by known count */
7253 /*-----------------------------------------------------------------*/
7254 static void genlshOne (operand *result, operand *left, int shCount)
7256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7257 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7260 /*-----------------------------------------------------------------*/
7261 /* genlshTwo - left shift two bytes by known amount != 0 */
7262 /*-----------------------------------------------------------------*/
7263 static void genlshTwo (operand *result,operand *left, int shCount)
7267 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7268 size = pic16_getDataSize(result);
7270 /* if shCount >= 8 */
7276 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7278 movLeft2Result(left, LSB, result, MSB16);
7280 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7283 /* 1 <= shCount <= 7 */
7286 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7288 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7292 /*-----------------------------------------------------------------*/
7293 /* shiftLLong - shift left one long from left to result */
7294 /* offr = LSB or MSB16 */
7295 /*-----------------------------------------------------------------*/
7296 static void shiftLLong (operand *left, operand *result, int offr )
7298 int size = AOP_SIZE(result);
7299 int same = pic16_sameRegs(AOP(left),AOP(result));
7302 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7304 if (same && (offr == MSB16)) { //shift one byte
7305 for(i=size-1;i>=MSB16;i--) {
7306 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7307 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7310 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7313 if (size > LSB+offr ){
7315 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7317 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7318 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7322 if(size > MSB16+offr){
7324 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7326 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7327 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7331 if(size > MSB24+offr){
7333 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7335 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7336 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7340 if(size > MSB32+offr){
7342 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7344 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7345 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7349 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7353 /*-----------------------------------------------------------------*/
7354 /* genlshFour - shift four byte by a known amount != 0 */
7355 /*-----------------------------------------------------------------*/
7356 static void genlshFour (operand *result, operand *left, int shCount)
7360 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7361 size = AOP_SIZE(result);
7363 /* if shifting more that 3 bytes */
7364 if (shCount >= 24 ) {
7367 /* lowest order of left goes to the highest
7368 order of the destination */
7369 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7371 movLeft2Result(left, LSB, result, MSB32);
7373 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7374 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7375 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7380 /* more than two bytes */
7381 else if ( shCount >= 16 ) {
7382 /* lower order two bytes goes to higher order two bytes */
7384 /* if some more remaining */
7386 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7388 movLeft2Result(left, MSB16, result, MSB32);
7389 movLeft2Result(left, LSB, result, MSB24);
7391 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7392 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7396 /* if more than 1 byte */
7397 else if ( shCount >= 8 ) {
7398 /* lower order three bytes goes to higher order three bytes */
7402 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7404 movLeft2Result(left, LSB, result, MSB16);
7406 else{ /* size = 4 */
7408 movLeft2Result(left, MSB24, result, MSB32);
7409 movLeft2Result(left, MSB16, result, MSB24);
7410 movLeft2Result(left, LSB, result, MSB16);
7411 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7413 else if(shCount == 1)
7414 shiftLLong(left, result, MSB16);
7416 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7417 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7418 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7419 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7424 /* 1 <= shCount <= 7 */
7425 else if(shCount <= 3)
7427 shiftLLong(left, result, LSB);
7428 while(--shCount >= 1)
7429 shiftLLong(result, result, LSB);
7431 /* 3 <= shCount <= 7, optimize */
7433 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7434 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7435 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7439 /*-----------------------------------------------------------------*/
7440 /* genLeftShiftLiteral - left shifting by known count */
7441 /*-----------------------------------------------------------------*/
7442 void pic16_genLeftShiftLiteral (operand *left,
7447 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7451 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7452 pic16_freeAsmop(right,NULL,ic,TRUE);
7454 pic16_aopOp(left,ic,FALSE);
7455 pic16_aopOp(result,ic,TRUE);
7457 size = getSize(operandType(result));
7460 pic16_emitcode("; shift left ","result %d, left %d",size,
7464 /* I suppose that the left size >= result size */
7467 movLeft2Result(left, size, result, size);
7471 else if(shCount >= (size * 8))
7473 pic16_aopPut(AOP(result),zero,size);
7477 genlshOne (result,left,shCount);
7482 genlshTwo (result,left,shCount);
7486 genlshFour (result,left,shCount);
7490 pic16_freeAsmop(left,NULL,ic,TRUE);
7491 pic16_freeAsmop(result,NULL,ic,TRUE);
7494 /*-----------------------------------------------------------------*
7495 * genMultiAsm - repeat assembly instruction for size of register.
7496 * if endian == 1, then the high byte (i.e base address + size of
7497 * register) is used first else the low byte is used first;
7498 *-----------------------------------------------------------------*/
7499 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7517 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7523 /*-----------------------------------------------------------------*/
7524 /* genrshOne - right shift a one byte quantity by known count */
7525 /*-----------------------------------------------------------------*/
7526 static void genrshOne (operand *result, operand *left,
7527 int shCount, int sign)
7529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7530 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7533 /*-----------------------------------------------------------------*/
7534 /* genrshTwo - right shift two bytes by known amount != 0 */
7535 /*-----------------------------------------------------------------*/
7536 static void genrshTwo (operand *result,operand *left,
7537 int shCount, int sign)
7539 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7540 /* if shCount >= 8 */
7544 shiftR1Left2Result(left, MSB16, result, LSB,
7547 movLeft2Result(left, MSB16, result, LSB);
7549 pic16_addSign (result, 1, sign);
7552 /* 1 <= shCount <= 7 */
7554 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7557 /*-----------------------------------------------------------------*/
7558 /* shiftRLong - shift right one long from left to result */
7559 /* offl = LSB or MSB16 */
7560 /*-----------------------------------------------------------------*/
7561 static void shiftRLong (operand *left, int offl,
7562 operand *result, int sign)
7564 int size = AOP_SIZE(result);
7565 int same = pic16_sameRegs(AOP(left),AOP(result));
7567 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7569 if (same && (offl == MSB16)) { //shift one byte right
7570 for(i=MSB16;i<size;i++) {
7571 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7572 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7577 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7583 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7585 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7586 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7590 /* add sign of "a" */
7591 pic16_addSign(result, MSB32, sign);
7595 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7597 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7598 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7602 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7604 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7605 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7609 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7612 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7613 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7618 /*-----------------------------------------------------------------*/
7619 /* genrshFour - shift four byte by a known amount != 0 */
7620 /*-----------------------------------------------------------------*/
7621 static void genrshFour (operand *result, operand *left,
7622 int shCount, int sign)
7624 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7625 /* if shifting more that 3 bytes */
7626 if(shCount >= 24 ) {
7629 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7631 movLeft2Result(left, MSB32, result, LSB);
7633 pic16_addSign(result, MSB16, sign);
7635 else if(shCount >= 16){
7638 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7640 movLeft2Result(left, MSB24, result, LSB);
7641 movLeft2Result(left, MSB32, result, MSB16);
7643 pic16_addSign(result, MSB24, sign);
7645 else if(shCount >= 8){
7648 shiftRLong(left, MSB16, result, sign);
7649 else if(shCount == 0){
7650 movLeft2Result(left, MSB16, result, LSB);
7651 movLeft2Result(left, MSB24, result, MSB16);
7652 movLeft2Result(left, MSB32, result, MSB24);
7653 pic16_addSign(result, MSB32, sign);
7655 else{ //shcount >= 2
7656 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7657 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7658 /* the last shift is signed */
7659 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7660 pic16_addSign(result, MSB32, sign);
7663 else{ /* 1 <= shCount <= 7 */
7665 shiftRLong(left, LSB, result, sign);
7667 shiftRLong(result, LSB, result, sign);
7670 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7671 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7672 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7677 /*-----------------------------------------------------------------*/
7678 /* genRightShiftLiteral - right shifting by known count */
7679 /*-----------------------------------------------------------------*/
7680 static void genRightShiftLiteral (operand *left,
7686 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7689 pic16_freeAsmop(right,NULL,ic,TRUE);
7691 pic16_aopOp(left,ic,FALSE);
7692 pic16_aopOp(result,ic,TRUE);
7694 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7697 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7701 lsize = pic16_getDataSize(left);
7702 res_size = pic16_getDataSize(result);
7703 /* test the LEFT size !!! */
7705 /* I suppose that the left size >= result size */
7707 assert (res_size <= lsize);
7708 while (res_size--) {
7709 pic16_mov2f (AOP(result), AOP(left), res_size);
7711 } else if (shCount >= (lsize * 8)) {
7718 * even for 8-bit operands; result might be an SFR.
7720 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7721 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7722 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7723 while (res_size--) {
7724 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7726 } else { // unsigned
7727 while (res_size--) {
7728 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7731 } else { // 0 < shCount < 8*lsize
7734 genrshOne (result,left,shCount,sign);
7738 genrshTwo (result,left,shCount,sign);
7742 genrshFour (result,left,shCount,sign);
7749 pic16_freeAsmop(left,NULL,ic,TRUE);
7750 pic16_freeAsmop(result,NULL,ic,TRUE);
7753 /*-----------------------------------------------------------------*/
7754 /* genGenericShift - generates code for left or right shifting */
7755 /*-----------------------------------------------------------------*/
7756 static void genGenericShift (iCode *ic, int isShiftLeft)
7758 operand *left,*right, *result;
7760 int sign, signedCount;
7761 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7762 PIC_OPCODE pos_shift, neg_shift;
7766 right = IC_RIGHT(ic);
7768 result = IC_RESULT(ic);
7770 pic16_aopOp(right,ic,FALSE);
7771 pic16_aopOp(left,ic,FALSE);
7772 pic16_aopOp(result,ic,TRUE);
7774 sign = !SPEC_USIGN(operandType (left));
7775 signedCount = !SPEC_USIGN(operandType (right));
7777 /* if the shift count is known then do it
7778 as efficiently as possible */
7779 if (AOP_TYPE(right) == AOP_LIT) {
7780 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7781 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7782 // we should modify right->aopu.aop_lit here!
7783 // Instead we use abs(shCount) in genXXXShiftLiteral()...
7784 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7786 pic16_genLeftShiftLiteral (left,right,result,ic);
7788 genRightShiftLiteral (left,right,result,ic, sign);
7791 } // if (right is literal)
7793 /* shift count is unknown then we have to form a loop.
7794 * Note: we take only the lower order byte since shifting
7795 * more than 32 bits make no sense anyway, ( the
7796 * largest size of an object can be only 32 bits )
7797 * Note: we perform arithmetic shifts if the left operand is
7798 * signed and we do an (effective) right shift, i. e. we
7799 * shift in the sign bit from the left. */
7801 label_complete = newiTempLabel ( NULL );
7802 label_loop_pos = newiTempLabel ( NULL );
7803 label_loop_neg = NULL;
7804 label_negative = NULL;
7805 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7806 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7809 // additional labels needed
7810 label_loop_neg = newiTempLabel ( NULL );
7811 label_negative = newiTempLabel ( NULL );
7814 // copy source to result -- this will effectively truncate the left operand to the size of result!
7815 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7816 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7817 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7818 pic16_mov2f (AOP(result),AOP(left), offset);
7821 // if result is longer than left, fill with zeros (or sign)
7822 if (AOP_SIZE(left) < AOP_SIZE(result)) {
7823 if (sign && AOP_SIZE(left) > 0) {
7824 // shift signed operand -- fill with sign
7825 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7826 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7827 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7828 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7829 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7832 // shift unsigned operand -- fill result with zeros
7833 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7834 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7837 } // if (size mismatch)
7839 pic16_mov2w (AOP(right), 0);
7840 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7841 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7844 // perform a shift by one (shift count is positive)
7845 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7846 // 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])
7847 pic16_emitpLabel (label_loop_pos->key);
7849 if (sign && (pos_shift == POC_RRCF)) {
7850 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7853 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7854 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7855 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7857 // perform a shift by one (shift count is positive)
7858 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7859 // 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])
7860 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7861 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7863 pic16_emitpLabel (label_loop_pos->key);
7864 if (sign && (pos_shift == POC_RRCF)) {
7865 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7868 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7869 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7870 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7871 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7875 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7877 pic16_emitpLabel (label_negative->key);
7878 // perform a shift by -1 (shift count is negative)
7879 // 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)
7881 pic16_emitpLabel (label_loop_neg->key);
7882 if (sign && (neg_shift == POC_RRCF)) {
7883 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7886 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7887 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7888 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7889 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7890 } // if (signedCount)
7892 pic16_emitpLabel (label_complete->key);
7895 pic16_freeAsmop (right,NULL,ic,TRUE);
7896 pic16_freeAsmop(left,NULL,ic,TRUE);
7897 pic16_freeAsmop(result,NULL,ic,TRUE);
7900 static void genLeftShift (iCode *ic) {
7901 genGenericShift (ic, 1);
7904 static void genRightShift (iCode *ic) {
7905 genGenericShift (ic, 0);
7909 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7910 void pic16_loadFSR0(operand *op, int lit)
7912 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7913 if (AOP_TYPE(op) == AOP_LIT) {
7914 /* handle 12 bit integers correctly */
7915 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7916 if ((val & 0x0fff) != val) {
7917 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7918 val, (val & 0x0fff) );
7921 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7923 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7926 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7927 // set up FSR0 with address of result
7928 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7929 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7933 /*----------------------------------------------------------------*/
7934 /* pic16_derefPtr - move one byte from the location ptr points to */
7935 /* to WREG (doWrite == 0) or one byte from WREG */
7936 /* to the location ptr points to (doWrite != 0) */
7937 /*----------------------------------------------------------------*/
7938 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7940 if (!IS_PTR(operandType(ptr)))
7942 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7943 else pic16_mov2w (AOP(ptr), 0);
7947 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7948 /* We might determine pointer type right here: */
7949 p_type = DCL_TYPE(operandType(ptr));
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));
7966 if (AOP(ptr)->aopu.aop_reg[2]) {
7967 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7968 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7969 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7970 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7971 pic16_mov2w(AOP(ptr), 2);
7972 pic16_callGenericPointerRW(doWrite, 1);
7974 // data pointer (just 2 byte given)
7975 if (!fsr0_setup || !*fsr0_setup)
7977 pic16_loadFSR0( ptr, 0 );
7978 if (fsr0_setup) *fsr0_setup = 1;
7981 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7983 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7988 assert (0 && "invalid pointer type specified");
7993 /*-----------------------------------------------------------------*/
7994 /* genUnpackBits - generates code for unpacking bits */
7995 /*-----------------------------------------------------------------*/
7996 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7999 sym_link *etype, *letype;
8005 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8006 etype = getSpec(operandType(result));
8007 letype = getSpec(operandType(left));
8009 // if(IS_BITFIELD(etype)) {
8010 blen = SPEC_BLEN(etype);
8011 bstr = SPEC_BSTR(etype);
8014 lbstr = SPEC_BSTR( letype );
8016 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
8017 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
8020 if((blen == 1) && (bstr < 8)
8021 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
8022 /* it is a single bit, so use the appropriate bit instructions */
8023 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
8025 same = pic16_sameRegs(AOP(left),AOP(result));
8026 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
8027 pic16_emitpcode(POC_CLRF, op);
8029 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8030 /* workaround to reduce the extra lfsr instruction */
8031 pic16_emitpcode(POC_BTFSC,
8032 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
8034 assert (PIC_IS_DATA_PTR (operandType(left)));
8035 pic16_loadFSR0 (left, 0);
8036 pic16_emitpcode(POC_BTFSC,
8037 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8040 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8041 /* unsigned bitfields result in either 0 or 1 */
8042 pic16_emitpcode(POC_INCF, op);
8044 /* signed bitfields result in either 0 or -1 */
8045 pic16_emitpcode(POC_DECF, op);
8048 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8051 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8057 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8058 // access symbol directly
8059 pic16_mov2w (AOP(left), 0);
8061 pic16_derefPtr (left, ptype, 0, NULL);
8064 /* if we have bitdisplacement then it fits */
8065 /* into this byte completely or if length is */
8066 /* less than a byte */
8067 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
8069 /* shift right acc */
8072 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8073 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8075 /* VR -- normally I would use the following, but since we use the hack,
8076 * to avoid the masking from AccRsh, why not mask it right now? */
8079 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8082 /* extend signed bitfields to 8 bits */
8083 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8085 assert (blen + bstr > 0);
8086 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8087 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8090 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8092 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8096 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8097 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8104 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8106 int size, offset = 0, leoffset=0 ;
8108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8109 pic16_aopOp(result, ic, TRUE);
8113 size = AOP_SIZE(result);
8114 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8118 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8119 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8120 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8125 if(AOP(left)->aopu.pcop->type == PO_DIR)
8126 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8128 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8131 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8133 // pic16_DumpOp("(result)",result);
8134 if(pic16_isLitAop(AOP(result))) {
8135 pic16_mov2w(AOP(left), offset); // patch 8
8136 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8138 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8139 pic16_popGet(AOP(left), offset), //patch 8
8140 pic16_popGet(AOP(result), offset)));
8148 pic16_freeAsmop(result,NULL,ic,TRUE);
8153 /*-----------------------------------------------------------------*/
8154 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8155 /*-----------------------------------------------------------------*/
8156 static void genNearPointerGet (operand *left,
8160 // asmop *aop = NULL;
8161 //regs *preg = NULL ;
8162 sym_link *rtype, *retype;
8163 sym_link *ltype, *letype;
8167 rtype = operandType(result);
8168 retype= getSpec(rtype);
8169 ltype = operandType(left);
8170 letype= getSpec(ltype);
8172 pic16_aopOp(left,ic,FALSE);
8174 // pic16_DumpOp("(left)",left);
8175 // pic16_DumpOp("(result)",result);
8177 /* if left is rematerialisable and
8178 * result is not bit variable type and
8179 * the left is pointer to data space i.e
8180 * lower 128 bytes of space */
8182 if (AOP_TYPE(left) == AOP_PCODE
8183 && !IS_BITFIELD(retype)
8184 && DCL_TYPE(ltype) == POINTER) {
8186 genDataPointerGet (left,result,ic);
8187 pic16_freeAsmop(left, NULL, ic, TRUE);
8191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8192 pic16_aopOp (result,ic,TRUE);
8194 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8197 if(IS_BITFIELD( retype )
8198 && (SPEC_BLEN(operandType(result))==1)
8202 int bitstrt, bytestrt;
8204 /* if this is bitfield of size 1, see if we are checking the value
8205 * of a single bit in an if-statement,
8206 * if yes, then don't generate usual code, but execute the
8207 * genIfx directly -- VR */
8211 /* CHECK: if next iCode is IFX
8212 * and current result operand is nextic's conditional operand
8213 * and current result operand live ranges ends at nextic's key number
8215 if((nextic->op == IFX)
8216 && (result == IC_COND(nextic))
8217 && (OP_LIVETO(result) == nextic->seq)
8218 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
8220 /* everything is ok then */
8221 /* find a way to optimize the genIfx iCode */
8223 bytestrt = SPEC_BSTR(operandType(result))/8;
8224 bitstrt = SPEC_BSTR(operandType(result))%8;
8226 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8228 genIfxpCOpJump(nextic, jop);
8230 pic16_freeAsmop(left, NULL, ic, TRUE);
8231 pic16_freeAsmop(result, NULL, ic, TRUE);
8237 /* if bitfield then unpack the bits */
8238 if (IS_BITFIELD(letype))
8239 genUnpackBits (result, left, NULL, POINTER);
8241 /* we have can just get the values */
8242 int size = AOP_SIZE(result);
8245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8247 pic16_loadFSR0( left, 0 );
8251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8252 pic16_popGet(AOP(result), offset++)));
8254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8255 pic16_popGet(AOP(result), offset++)));
8261 /* now some housekeeping stuff */
8263 /* we had to allocate for this iCode */
8264 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8265 pic16_freeAsmop(NULL,aop,ic,TRUE);
8267 /* we did not allocate which means left
8268 * already in a pointer register, then
8269 * if size > 0 && this could be used again
8270 * we have to point it back to where it
8272 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8273 if (AOP_SIZE(result) > 1
8274 && !OP_SYMBOL(left)->remat
8275 && ( OP_SYMBOL(left)->liveTo > ic->seq
8277 // int size = AOP_SIZE(result) - 1;
8279 // pic16_emitcode("dec","%s",rname);
8285 pic16_freeAsmop(left,NULL,ic,TRUE);
8286 pic16_freeAsmop(result,NULL,ic,TRUE);
8289 /*-----------------------------------------------------------------*/
8290 /* genGenPointerGet - gget value from generic pointer space */
8291 /*-----------------------------------------------------------------*/
8292 static void genGenPointerGet (operand *left,
8293 operand *result, iCode *ic)
8296 sym_link *letype = getSpec(operandType(left));
8298 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8299 pic16_aopOp(left,ic,FALSE);
8300 pic16_aopOp(result,ic,TRUE);
8301 size = AOP_SIZE(result);
8303 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8305 /* if bit then unpack */
8306 if (IS_BITFIELD(letype)) {
8307 genUnpackBits(result,left,"BAD",GPOINTER);
8311 /* set up WREG:PRODL:FSR0L with address from left */
8312 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8313 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8314 pic16_mov2w(AOP(left), 2);
8315 pic16_callGenericPointerRW(0, size);
8317 assignResultValue(result, size, 1);
8320 pic16_freeAsmop(left,NULL,ic,TRUE);
8321 pic16_freeAsmop(result,NULL,ic,TRUE);
8324 /*-----------------------------------------------------------------*/
8325 /* genConstPointerGet - get value from const generic pointer space */
8326 /*-----------------------------------------------------------------*/
8327 static void genConstPointerGet (operand *left,
8328 operand *result, iCode *ic)
8330 //sym_link *retype = getSpec(operandType(result));
8331 // symbol *albl = newiTempLabel(NULL); // patch 15
8332 // symbol *blbl = newiTempLabel(NULL); //
8333 // PIC_OPCODE poc; // patch 15
8337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8338 pic16_aopOp(left,ic,FALSE);
8339 pic16_aopOp(result,ic,TRUE);
8340 size = AOP_SIZE(result);
8342 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8344 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8346 // set up table pointer
8347 if( (AOP_TYPE(left) == AOP_PCODE)
8348 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8349 || (AOP(left)->aopu.pcop->type == PO_DIR)))
8351 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8352 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8353 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8354 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8355 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8356 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8358 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8359 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8360 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8364 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8365 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8369 pic16_freeAsmop(left,NULL,ic,TRUE);
8370 pic16_freeAsmop(result,NULL,ic,TRUE);
8374 /*-----------------------------------------------------------------*/
8375 /* genPointerGet - generate code for pointer get */
8376 /*-----------------------------------------------------------------*/
8377 static void genPointerGet (iCode *ic)
8379 operand *left, *result ;
8380 sym_link *type, *etype;
8386 result = IC_RESULT(ic) ;
8388 /* depending on the type of pointer we need to
8389 move it to the correct pointer register */
8390 type = operandType(left);
8391 etype = getSpec(type);
8394 if (IS_PTR_CONST(type))
8396 if (IS_CODEPTR(type))
8398 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8400 /* if left is of type of pointer then it is simple */
8401 if (IS_PTR(type) && !IS_FUNC(type->next))
8402 p_type = DCL_TYPE(type);
8404 /* we have to go by the storage class */
8405 p_type = PTR_TYPE(SPEC_OCLS(etype));
8407 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8409 if (SPEC_OCLS(etype)->codesp ) {
8410 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8411 //p_type = CPOINTER ;
8413 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8414 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8415 /*p_type = FPOINTER ;*/
8417 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8418 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8419 /* p_type = PPOINTER; */
8421 if (SPEC_OCLS(etype) == idata ) {
8422 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8423 /* p_type = IPOINTER; */
8425 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8426 /* p_type = POINTER ; */
8430 /* now that we have the pointer type we assign
8431 the pointer values */
8436 genNearPointerGet (left,result,ic);
8440 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8442 genPagedPointerGet(left,result,ic);
8446 genFarPointerGet (left,result,ic);
8451 genConstPointerGet (left,result,ic);
8452 //pic16_emitcodePointerGet (left,result,ic);
8457 if (IS_PTR_CONST(type))
8458 genConstPointerGet (left,result,ic);
8461 genGenPointerGet (left,result,ic);
8465 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8466 "genPointerGet: illegal pointer type");
8471 /*-----------------------------------------------------------------*/
8472 /* genPackBits - generates code for packed bit storage */
8473 /*-----------------------------------------------------------------*/
8474 static void genPackBits (sym_link *etype , operand *result,
8476 char *rname, int p_type)
8482 int shifted_and_masked = 0;
8483 unsigned long lit = (unsigned long)-1;
8486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8487 blen = SPEC_BLEN(etype);
8488 bstr = SPEC_BSTR(etype);
8490 retype = getSpec(operandType(right));
8492 if(AOP_TYPE(right) == AOP_LIT) {
8493 lit = ulFromVal (AOP(right)->aopu.aop_lit);
8495 if((blen == 1) && (bstr < 8)) {
8496 /* it is a single bit, so use the appropriate bit instructions */
8498 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8500 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8501 /* workaround to reduce the extra lfsr instruction */
8503 pic16_emitpcode(POC_BSF,
8504 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8506 pic16_emitpcode(POC_BCF,
8507 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8510 if (PIC_IS_DATA_PTR(operandType(result))) {
8511 pic16_loadFSR0(result, 0);
8512 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8513 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8516 pic16_derefPtr (result, p_type, 0, NULL);
8517 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8518 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8519 /* write back new value */
8520 pic16_derefPtr (result, p_type, 1, NULL);
8526 /* IORLW below is more efficient */
8527 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8528 lit = (lit & ((1UL << blen) - 1)) << bstr;
8529 shifted_and_masked = 1;
8532 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8533 && IS_BITFIELD(retype)
8534 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8538 rblen = SPEC_BLEN( retype );
8539 rbstr = SPEC_BSTR( retype );
8541 if(IS_BITFIELD(etype)) {
8542 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8543 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8545 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8548 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8550 if(IS_BITFIELD(etype)) {
8551 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8553 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8560 /* move right to W */
8561 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8564 /* if the bit length is less than or */
8565 /* it exactly fits a byte then */
8566 if((shCnt=SPEC_BSTR(etype))
8567 || SPEC_BLEN(etype) <= 8 ) {
8570 if (blen != 8 || (bstr % 8) != 0) {
8571 // we need to combine the value with the old value
8572 if(!shifted_and_masked)
8574 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8576 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8577 SPEC_BSTR(etype), SPEC_BLEN(etype));
8579 /* shift left acc, do NOT mask the result again */
8582 /* using PRODH as a temporary register here */
8583 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8586 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8587 || IS_DIRECT(result)) {
8588 /* access symbol directly */
8589 pic16_mov2w (AOP(result), 0);
8592 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8595 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8596 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8597 (unsigned char)(0xff >> (8-bstr))) ));
8598 if (!shifted_and_masked) {
8599 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8601 /* We have the shifted and masked (literal) right value in `lit' */
8603 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8605 } else { // if (blen == 8 && (bstr % 8) == 0)
8606 if (shifted_and_masked) {
8607 // move right (literal) to WREG (only case where right is not yet in WREG)
8608 pic16_mov2w(AOP(right), (bstr / 8));
8612 /* write new value back */
8613 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8614 || IS_DIRECT(result)) {
8615 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8617 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8626 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8627 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8632 pic16_loadFSR0(result, 0); // load FSR0 with address of result
8633 rLen = SPEC_BLEN(etype)-8;
8635 /* now generate for lengths greater than one byte */
8639 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8645 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8651 pic16_emitcode("movx","@dptr,a");
8656 DEBUGpic16_emitcode(";lcall","__gptrput");
8664 pic16_mov2w(AOP(right), offset++);
8667 /* last last was not complete */
8669 /* save the byte & read byte */
8672 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8673 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8678 pic16_emitcode ("mov","b,a");
8679 pic16_emitcode("movx","a,@dptr");
8683 pic16_emitcode ("push","b");
8684 pic16_emitcode ("push","acc");
8685 pic16_emitcode ("lcall","__gptrget");
8686 pic16_emitcode ("pop","b");
8692 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8693 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8694 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8695 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8696 // pic16_emitcode ("orl","a,b");
8699 // if (p_type == GPOINTER)
8700 // pic16_emitcode("pop","b");
8705 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8706 // pic16_emitcode("mov","@%s,a",rname);
8710 pic16_emitcode("movx","@dptr,a");
8714 DEBUGpic16_emitcode(";lcall","__gptrput");
8721 // pic16_freeAsmop(right, NULL, ic, TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genDataPointerSet - remat pointer to data space */
8726 /*-----------------------------------------------------------------*/
8727 static void genDataPointerSet(operand *right,
8731 int size, offset = 0, resoffset=0 ;
8733 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8734 pic16_aopOp(right,ic,FALSE);
8736 size = AOP_SIZE(right);
8738 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8741 if ( AOP_TYPE(result) == AOP_PCODE) {
8742 fprintf(stderr,"genDataPointerSet %s, %d\n",
8743 AOP(result)->aopu.pcop->name,
8744 (AOP(result)->aopu.pcop->type == PO_DIR)?
8745 PCOR(AOP(result)->aopu.pcop)->instance:
8746 PCOI(AOP(result)->aopu.pcop)->offset);
8750 if(AOP(result)->aopu.pcop->type == PO_DIR)
8751 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8754 if (AOP_TYPE(right) == AOP_LIT) {
8755 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8756 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8758 pic16_mov2w(AOP(right), offset);
8759 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8765 pic16_freeAsmop(right,NULL,ic,TRUE);
8770 /*-----------------------------------------------------------------*/
8771 /* genNearPointerSet - pic16_emitcode for near pointer put */
8772 /*-----------------------------------------------------------------*/
8773 static void genNearPointerSet (operand *right,
8779 sym_link *ptype = operandType(result);
8782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8783 retype= getSpec(operandType(right));
8784 resetype = getSpec(operandType(result));
8786 pic16_aopOp(result,ic,FALSE);
8788 /* if the result is rematerializable &
8789 * in data space & not a bit variable */
8791 /* and result is not a bit variable */
8792 if (AOP_TYPE(result) == AOP_PCODE
8793 && DCL_TYPE(ptype) == POINTER
8794 && !IS_BITFIELD(retype)
8795 && !IS_BITFIELD(resetype)) {
8797 genDataPointerSet (right,result,ic);
8798 pic16_freeAsmop(result,NULL,ic,TRUE);
8802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8803 pic16_aopOp(right,ic,FALSE);
8804 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8806 /* if bitfield then unpack the bits */
8807 if (IS_BITFIELD(resetype)) {
8808 genPackBits (resetype, result, right, NULL, POINTER);
8810 /* we have can just get the values */
8811 int size = AOP_SIZE(right);
8814 pic16_loadFSR0(result, 0);
8816 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8818 if (pic16_isLitOp(right)) {
8819 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8821 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8823 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8825 } else { // no literal
8827 pic16_emitpcode(POC_MOVFF,
8828 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8829 pic16_popCopyReg(&pic16_pc_postinc0)));
8831 pic16_emitpcode(POC_MOVFF,
8832 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8833 pic16_popCopyReg(&pic16_pc_indf0)));
8841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8842 /* now some housekeeping stuff */
8844 /* we had to allocate for this iCode */
8845 pic16_freeAsmop(NULL,aop,ic,TRUE);
8847 /* we did not allocate which means left
8848 * already in a pointer register, then
8849 * if size > 0 && this could be used again
8850 * we have to point it back to where it
8852 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8853 if (AOP_SIZE(right) > 1
8854 && !OP_SYMBOL(result)->remat
8855 && ( OP_SYMBOL(result)->liveTo > ic->seq
8858 int size = AOP_SIZE(right) - 1;
8861 pic16_emitcode("decf","fsr0,f");
8862 //pic16_emitcode("dec","%s",rname);
8866 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8869 pic16_freeAsmop(right,NULL,ic,TRUE);
8870 pic16_freeAsmop(result,NULL,ic,TRUE);
8873 /*-----------------------------------------------------------------*/
8874 /* genGenPointerSet - set value from generic pointer space */
8875 /*-----------------------------------------------------------------*/
8876 static void genGenPointerSet (operand *right,
8877 operand *result, iCode *ic)
8880 sym_link *retype = getSpec(operandType(result));
8882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8884 pic16_aopOp(result,ic,FALSE);
8885 pic16_aopOp(right,ic,FALSE);
8886 size = AOP_SIZE(right);
8888 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8891 /* if bit then unpack */
8892 if (IS_BITFIELD(retype)) {
8893 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8894 genPackBits(retype,result,right,"dptr",GPOINTER);
8898 size = AOP_SIZE(right);
8900 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
8903 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8905 /* value of right+0 is placed on stack, which will be retrieved
8906 * by the support function thus restoring the stack. The important
8907 * thing is that there is no need to manually restore stack pointer
8909 pushaop(AOP(right), 0);
8910 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8911 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8912 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8913 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8915 /* load address to write to in WREG:FSR0H:FSR0L */
8916 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8917 pic16_popCopyReg(&pic16_pc_fsr0l)));
8918 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8919 pic16_popCopyReg(&pic16_pc_prodl)));
8920 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8922 pic16_callGenericPointerRW(1, size);
8925 pic16_freeAsmop(right,NULL,ic,TRUE);
8926 pic16_freeAsmop(result,NULL,ic,TRUE);
8929 /*-----------------------------------------------------------------*/
8930 /* genPointerSet - stores the value into a pointer location */
8931 /*-----------------------------------------------------------------*/
8932 static void genPointerSet (iCode *ic)
8934 operand *right, *result ;
8935 sym_link *type, *etype;
8940 right = IC_RIGHT(ic);
8941 result = IC_RESULT(ic) ;
8943 /* depending on the type of pointer we need to
8944 move it to the correct pointer register */
8945 type = operandType(result);
8946 etype = getSpec(type);
8948 /* if left is of type of pointer then it is simple */
8949 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8950 p_type = DCL_TYPE(type);
8953 /* we have to go by the storage class */
8954 p_type = PTR_TYPE(SPEC_OCLS(etype));
8956 /* if (SPEC_OCLS(etype)->codesp ) { */
8957 /* p_type = CPOINTER ; */
8960 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8961 /* p_type = FPOINTER ; */
8963 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8964 /* p_type = PPOINTER ; */
8966 /* if (SPEC_OCLS(etype) == idata ) */
8967 /* p_type = IPOINTER ; */
8969 /* p_type = POINTER ; */
8972 /* now that we have the pointer type we assign
8973 the pointer values */
8978 genNearPointerSet (right,result,ic);
8982 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8984 genPagedPointerSet (right,result,ic);
8988 genFarPointerSet (right,result,ic);
8993 genGenPointerSet (right,result,ic);
8997 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8998 "genPointerSet: illegal pointer type");
9002 /*-----------------------------------------------------------------*/
9003 /* genIfx - generate code for Ifx statement */
9004 /*-----------------------------------------------------------------*/
9005 static void genIfx (iCode *ic, iCode *popIc)
9007 operand *cond = IC_COND(ic);
9012 pic16_aopOp(cond,ic,FALSE);
9014 /* get the value into acc */
9015 if (AOP_TYPE(cond) != AOP_CRY)
9016 pic16_toBoolean(cond);
9019 /* the result is now in the accumulator */
9020 pic16_freeAsmop(cond,NULL,ic,TRUE);
9022 /* if there was something to be popped then do it */
9026 /* if the condition is a bit variable */
9027 if (isbit && IS_ITEMP(cond) &&
9030 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9032 if (isbit && !IS_ITEMP(cond))
9033 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9040 /*-----------------------------------------------------------------*/
9041 /* genAddrOf - generates code for address of */
9042 /*-----------------------------------------------------------------*/
9043 static void genAddrOf (iCode *ic)
9045 operand *result, *left;
9047 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
9048 pCodeOp *pcop0, *pcop1, *pcop2;
9052 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9054 sym = OP_SYMBOL( IC_LEFT(ic) );
9057 /* get address of symbol on stack */
9058 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9060 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9061 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9064 // operands on stack are accessible via "FSR2 + index" with index
9065 // starting at 2 for arguments and growing from 0 downwards for
9066 // local variables (index == 0 is not assigned so we add one here)
9068 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9075 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9076 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9077 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9078 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9079 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9080 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9081 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9087 // if(pic16_debug_verbose) {
9088 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9089 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9092 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9093 size = AOP_SIZE(IC_RESULT(ic));
9095 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9096 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9097 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9100 pic16_emitpcode(POC_MOVLW, pcop0);
9101 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9102 pic16_emitpcode(POC_MOVLW, pcop1);
9103 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9104 pic16_emitpcode(POC_MOVLW, pcop2);
9105 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9108 pic16_emitpcode(POC_MOVLW, pcop0);
9109 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9110 pic16_emitpcode(POC_MOVLW, pcop1);
9111 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9113 pic16_emitpcode(POC_MOVLW, pcop0);
9114 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9117 pic16_freeAsmop(left, NULL, ic, FALSE);
9119 pic16_freeAsmop(result,NULL,ic,TRUE);
9123 /*-----------------------------------------------------------------*/
9124 /* genAssign - generate code for assignment */
9125 /*-----------------------------------------------------------------*/
9126 static void genAssign (iCode *ic)
9128 operand *result, *right;
9129 sym_link *restype, *rtype;
9130 int size, offset,know_W;
9131 unsigned long lit = 0L;
9133 result = IC_RESULT(ic);
9134 right = IC_RIGHT(ic) ;
9138 /* if they are the same */
9139 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9142 /* reversed order operands are aopOp'ed so that result operand
9143 * is effective in case right is a stack symbol. This maneauver
9144 * allows to use the _G.resDirect flag later */
9145 pic16_aopOp(result,ic,TRUE);
9146 pic16_aopOp(right,ic,FALSE);
9148 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9150 /* if they are the same registers */
9151 if (pic16_sameRegs(AOP(right),AOP(result)))
9154 /* if the result is a bit */
9155 if (AOP_TYPE(result) == AOP_CRY) {
9156 /* if the right size is a literal then
9157 we know what the value is */
9158 if (AOP_TYPE(right) == AOP_LIT) {
9160 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9161 pic16_popGet(AOP(result),0));
9163 if (((int) operandLitValue(right)))
9164 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9165 AOP(result)->aopu.aop_dir,
9166 AOP(result)->aopu.aop_dir);
9168 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9169 AOP(result)->aopu.aop_dir,
9170 AOP(result)->aopu.aop_dir);
9175 /* the right is also a bit variable */
9176 if (AOP_TYPE(right) == AOP_CRY) {
9177 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9178 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9179 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9185 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9186 pic16_toBoolean(right);
9188 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9189 //pic16_aopPut(AOP(result),"a",0);
9193 /* bit variables done */
9195 size = AOP_SIZE(result);
9198 /* bit variables done */
9200 size = AOP_SIZE(result);
9201 restype = operandType(result);
9202 rtype = operandType(right);
9205 if(AOP_TYPE(right) == AOP_LIT) {
9206 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9208 lit = ulFromVal (AOP(right)->aopu.aop_lit);
9210 /* patch tag for literals that are cast to pointers */
9211 if (IS_CODEPTR(restype)) {
9212 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9213 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9215 if (IS_GENPTR(restype))
9217 if (IS_CODEPTR(rtype)) {
9218 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9219 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9220 } else if (PIC_IS_DATA_PTR(rtype)) {
9221 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9222 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9223 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9224 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9225 } else if (IS_PTR(rtype)) {
9226 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9227 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9233 unsigned long lit_int;
9238 if(IS_FIXED16X16(operandType(right))) {
9239 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9241 /* take care if literal is a float */
9242 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9248 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9249 // sizeof(unsigned long int), sizeof(float));
9252 if (AOP_TYPE(right) == AOP_REG) {
9253 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9255 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9260 /* when do we have to read the program memory?
9261 * - if right itself is a symbol in code space
9262 * (we don't care what it points to if it's a pointer)
9263 * - AND right is not a function (we would want its address)
9265 if(AOP_TYPE(right) != AOP_LIT
9266 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9267 && !IS_FUNC(OP_SYM_TYPE(right))
9268 && !IS_ITEMP(right)) {
9270 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9271 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9273 // set up table pointer
9274 if(pic16_isLitOp(right)) {
9275 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9276 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9277 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9278 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9279 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9280 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9281 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9283 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9284 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9285 pic16_popCopyReg(&pic16_pc_tblptrl)));
9286 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9287 pic16_popCopyReg(&pic16_pc_tblptrh)));
9288 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9289 pic16_popCopyReg(&pic16_pc_tblptru)));
9292 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9293 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9295 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9296 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9297 pic16_popGet(AOP(result),offset)));
9301 /* FIXME: for pointers we need to extend differently (according
9302 * to pointer type DATA/CODE/EEPROM/... :*/
9303 size = getSize(OP_SYM_TYPE(right));
9304 if(AOP_SIZE(result) > size) {
9305 size = AOP_SIZE(result) - size;
9307 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9315 /* VR - What is this?! */
9316 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9319 if(aopIdx(AOP(result),0) == 4) {
9320 /* this is a workaround to save value of right into wreg too,
9321 * value of wreg is going to be used later */
9322 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9323 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9328 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9332 size = AOP_SIZE(right);
9333 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9336 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
9337 if(AOP_TYPE(right) == AOP_LIT) {
9339 if(know_W != (lit&0xff))
9340 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9342 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9344 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9348 } else if (AOP_TYPE(right) == AOP_CRY) {
9349 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9351 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9352 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9353 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9355 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9356 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9357 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9359 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9361 if(!_G.resDirect) { /* use this aopForSym feature */
9362 if(AOP_TYPE(result) == AOP_ACC) {
9363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9365 if(AOP_TYPE(right) == AOP_ACC) {
9366 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9368 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9375 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9378 pic16_freeAsmop (right,NULL,ic,FALSE);
9379 pic16_freeAsmop (result,NULL,ic,TRUE);
9382 /*-----------------------------------------------------------------*/
9383 /* genJumpTab - generates code for jump table */
9384 /*-----------------------------------------------------------------*/
9385 static void genJumpTab (iCode *ic)
9390 pCodeOp *jt_offs_hi;
9395 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9396 /* get the condition into accumulator */
9397 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9399 /* multiply by three */
9400 pic16_emitcode("add","a,acc");
9401 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9403 jtab = newiTempLabel(NULL);
9404 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9405 pic16_emitcode("jmp","@a+dptr");
9406 pic16_emitcode("","%05d_DS_:",jtab->key+100);
9409 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9410 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9412 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9413 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9414 pic16_emitpLabel(jtab->key);
9418 jt_offs = pic16_popGetTempReg(0);
9419 jt_offs_hi = pic16_popGetTempReg(1);
9420 jt_label = pic16_popGetLabel (jtab->key);
9421 //fprintf (stderr, "Creating jump table...\n");
9423 // calculate offset into jump table (idx * sizeof (GOTO))
9424 pic16_emitpcode(POC_CLRF , jt_offs_hi);
9425 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9426 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9427 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9428 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9429 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9430 pic16_emitpcode(POC_MOVWF , jt_offs);
9432 // prepare PCLATx (set to first entry in jump table)
9433 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9434 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9435 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9436 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9437 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9439 // set PCLATx to selected entry (new PCL is stored in jt_offs)
9440 pic16_emitpcode(POC_ADDWF , jt_offs);
9441 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9442 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9444 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
9446 // release temporaries and prepare jump into table (new PCL --> WREG)
9447 pic16_emitpcode(POC_MOVFW , jt_offs);
9448 pic16_popReleaseTempReg (jt_offs_hi, 1);
9449 pic16_popReleaseTempReg (jt_offs, 0);
9451 // jump into the table
9452 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9454 pic16_emitpLabelFORCE(jtab->key);
9457 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9458 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9460 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9461 /* now generate the jump labels */
9462 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9463 jtab = setNextItem(IC_JTLABELS(ic))) {
9464 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9465 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9468 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9472 /*-----------------------------------------------------------------*/
9473 /* genMixedOperation - gen code for operators between mixed types */
9474 /*-----------------------------------------------------------------*/
9476 TSD - Written for the PIC port - but this unfortunately is buggy.
9477 This routine is good in that it is able to efficiently promote
9478 types to different (larger) sizes. Unfortunately, the temporary
9479 variables that are optimized out by this routine are sometimes
9480 used in other places. So until I know how to really parse the
9481 iCode tree, I'm going to not be using this routine :(.
9483 static int genMixedOperation (iCode *ic)
9486 operand *result = IC_RESULT(ic);
9487 sym_link *ctype = operandType(IC_LEFT(ic));
9488 operand *right = IC_RIGHT(ic);
9494 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9496 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9502 nextright = IC_RIGHT(nextic);
9503 nextleft = IC_LEFT(nextic);
9504 nextresult = IC_RESULT(nextic);
9506 pic16_aopOp(right,ic,FALSE);
9507 pic16_aopOp(result,ic,FALSE);
9508 pic16_aopOp(nextright, nextic, FALSE);
9509 pic16_aopOp(nextleft, nextic, FALSE);
9510 pic16_aopOp(nextresult, nextic, FALSE);
9512 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9518 pic16_emitcode(";remove right +","");
9520 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9526 pic16_emitcode(";remove left +","");
9530 big = AOP_SIZE(nextleft);
9531 small = AOP_SIZE(nextright);
9533 switch(nextic->op) {
9536 pic16_emitcode(";optimize a +","");
9537 /* if unsigned or not an integral type */
9538 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9539 pic16_emitcode(";add a bit to something","");
9542 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9544 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9545 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9546 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9548 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9556 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9557 pic16_emitcode("movf","%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) );
9561 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9563 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9564 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9565 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9566 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9567 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9570 pic16_emitcode("rlf","known_zero,w");
9577 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9578 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9579 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9581 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9591 pic16_freeAsmop(right,NULL,ic,TRUE);
9592 pic16_freeAsmop(result,NULL,ic,TRUE);
9593 pic16_freeAsmop(nextright,NULL,ic,TRUE);
9594 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9596 nextic->generated = 1;
9603 /*-----------------------------------------------------------------*/
9604 /* genCast - gen code for casting */
9605 /*-----------------------------------------------------------------*/
9606 static void genCast (iCode *ic)
9608 operand *result = IC_RESULT(ic);
9609 sym_link *ctype = operandType(IC_LEFT(ic));
9610 sym_link *rtype = operandType(IC_RIGHT(ic));
9611 sym_link *restype = operandType(IC_RESULT(ic));
9612 operand *right = IC_RIGHT(ic);
9618 /* if they are equivalent then do nothing */
9619 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9622 pic16_aopOp(result,ic,FALSE);
9623 pic16_aopOp(right,ic,FALSE) ;
9625 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9628 /* if the result is a bit */
9629 if (AOP_TYPE(result) == AOP_CRY) {
9631 /* if the right size is a literal then
9632 * we know what the value is */
9633 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9635 if (AOP_TYPE(right) == AOP_LIT) {
9636 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9637 pic16_popGet(AOP(result),0));
9639 if (((int) operandLitValue(right)))
9640 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9641 AOP(result)->aopu.aop_dir,
9642 AOP(result)->aopu.aop_dir);
9644 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9645 AOP(result)->aopu.aop_dir,
9646 AOP(result)->aopu.aop_dir);
9650 /* the right is also a bit variable */
9651 if (AOP_TYPE(right) == AOP_CRY) {
9653 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9655 pic16_emitcode("clrc","");
9656 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9657 AOP(right)->aopu.aop_dir,
9658 AOP(right)->aopu.aop_dir);
9659 pic16_aopPut(AOP(result),"c",0);
9664 if (AOP_TYPE(right) == AOP_REG) {
9665 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9666 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9667 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9669 pic16_toBoolean(right);
9670 pic16_aopPut(AOP(result),"a",0);
9674 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9677 size = AOP_SIZE(result);
9679 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9681 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9682 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9683 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9686 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9691 if(IS_BITFIELD(getSpec(restype))
9692 && IS_BITFIELD(getSpec(rtype))) {
9693 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9696 /* port from pic14 to cope with generic pointers */
9697 if (PIC_IS_TAGGED(restype))
9699 operand *result = IC_RESULT(ic);
9700 //operand *left = IC_LEFT(ic);
9701 operand *right = IC_RIGHT(ic);
9704 /* copy common part */
9705 int max, size = AOP_SIZE(result);
9706 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9707 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9712 pic16_mov2w (AOP(right), size);
9713 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9716 /* upcast into generic pointer type? */
9717 if (IS_GENPTR(restype)
9718 && !PIC_IS_TAGGED(rtype)
9719 && (AOP_SIZE(result) > max))
9721 /* determine appropriate tag for right */
9722 if (PIC_IS_DATA_PTR(rtype))
9723 tag = GPTR_TAG_DATA;
9724 else if (IS_CODEPTR(rtype))
9725 tag = GPTR_TAG_CODE;
9726 else if (PIC_IS_DATA_PTR(ctype)) {
9727 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9728 tag = GPTR_TAG_DATA;
9729 } else if (IS_CODEPTR(ctype)) {
9730 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9731 tag = GPTR_TAG_CODE;
9732 } else if (IS_PTR(rtype)) {
9733 PERFORM_ONCE(weirdcast,
9734 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9736 tag = GPTR_TAG_DATA;
9738 PERFORM_ONCE(weirdcast,
9739 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9741 tag = GPTR_TAG_DATA;
9744 assert (AOP_SIZE(result) == 3);
9745 /* zero-extend address... */
9746 for (size = max; size < AOP_SIZE(result)-1; size++)
9747 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9748 /* ...and add tag */
9749 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9750 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9751 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9752 for (size = max; size < AOP_SIZE(result)-1; size++)
9753 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9754 /* add __code tag */
9755 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9756 } else if (AOP_SIZE(result) > max) {
9757 /* extend non-pointers */
9758 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9759 pic16_addSign(result, max, 0);
9764 /* if they are the same size : or less */
9765 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9767 /* if they are in the same place */
9768 if (pic16_sameRegs(AOP(right),AOP(result)))
9771 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9773 if (IS_PTR_CONST(rtype))
9775 if (IS_CODEPTR(rtype))
9777 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9780 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9782 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9784 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9786 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9787 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9790 if(AOP_SIZE(result) < 2) {
9791 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9793 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9794 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9797 /* if they in different places then copy */
9798 size = AOP_SIZE(result);
9801 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9802 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9809 /* if the result is of type pointer */
9810 if (IS_PTR(ctype)) {
9812 sym_link *type = operandType(right);
9813 sym_link *etype = getSpec(type);
9815 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
9817 /* pointer to generic pointer */
9818 if (IS_GENPTR(ctype)) {
9822 p_type = DCL_TYPE(type);
9824 /* we have to go by the storage class */
9825 p_type = PTR_TYPE(SPEC_OCLS(etype));
9827 /* if (SPEC_OCLS(etype)->codesp ) */
9828 /* p_type = CPOINTER ; */
9830 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9831 /* p_type = FPOINTER ; */
9833 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9834 /* p_type = PPOINTER; */
9836 /* if (SPEC_OCLS(etype) == idata ) */
9837 /* p_type = IPOINTER ; */
9839 /* p_type = POINTER ; */
9842 /* the first two bytes are known */
9843 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
9844 size = GPTRSIZE - 1;
9847 if(offset < AOP_SIZE(right)) {
9848 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9849 pic16_mov2f(AOP(result), AOP(right), offset);
9851 if ((AOP_TYPE(right) == AOP_PCODE) &&
9852 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9853 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9857 pic16_aopPut(AOP(result),
9858 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9863 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9866 /* the last byte depending on type */
9871 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9875 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9879 pic16_emitcode(";BUG!? ","%d",__LINE__);
9884 if (GPTRSIZE > AOP_SIZE(right)) {
9885 // assume __data pointer... THIS MIGHT BE WRONG!
9886 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9888 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9893 /* this should never happen */
9894 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9895 "got unknown pointer type");
9898 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9904 /* just copy the pointers */
9905 size = AOP_SIZE(result);
9908 pic16_aopPut(AOP(result),
9909 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9918 /* so we now know that the size of destination is greater
9919 than the size of the source.
9920 Now, if the next iCode is an operator then we might be
9921 able to optimize the operation without performing a cast.
9923 if(genMixedOperation(ic))
9926 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9928 /* we move to result for the size of source */
9929 size = AOP_SIZE(right);
9934 pic16_mov2f(AOP(result), AOP(right), offset);
9938 /* now depending on the sign of the destination */
9939 size = AOP_SIZE(result) - AOP_SIZE(right);
9940 /* if unsigned or not an integral type */
9941 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9943 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9945 /* we need to extend the sign :( */
9948 /* Save one instruction of casting char to int */
9949 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9950 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9951 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
9953 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9956 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9958 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9960 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
9968 pic16_freeAsmop(right,NULL,ic,TRUE);
9969 pic16_freeAsmop(result,NULL,ic,TRUE);
9973 /*-----------------------------------------------------------------*/
9974 /* genDjnz - generate decrement & jump if not zero instrucion */
9975 /*-----------------------------------------------------------------*/
9976 static int genDjnz (iCode *ic, iCode *ifx)
9979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9984 /* if the if condition has a false label
9985 then we cannot save */
9989 /* if the minus is not of the form
9991 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9992 !IS_OP_LITERAL(IC_RIGHT(ic)))
9995 if (operandLitValue(IC_RIGHT(ic)) != 1)
9998 /* if the size of this greater than one then no
10000 if (getSize(operandType(IC_RESULT(ic))) > 1)
10003 /* otherwise we can save BIG */
10004 lbl = newiTempLabel(NULL);
10005 lbl1= newiTempLabel(NULL);
10007 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10009 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10012 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10013 ifx->generated = 1;
10017 /*-----------------------------------------------------------------*/
10018 /* genReceive - generate code for a receive iCode */
10019 /*-----------------------------------------------------------------*/
10020 static void genReceive (iCode *ic)
10026 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
10027 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
10029 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
10031 if (isOperandInFarSpace(IC_RESULT(ic))
10032 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
10033 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10035 int size = getSize(operandType(IC_RESULT(ic)));
10036 int offset = pic16_fReturnSizePic - size;
10040 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10041 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10045 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10047 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10048 size = AOP_SIZE(IC_RESULT(ic));
10051 pic16_emitcode ("pop","acc");
10052 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10055 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10057 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10060 /* set pseudo stack pointer to where it should be - dw*/
10061 GpsuedoStkPtr = ic->parmBytes;
10063 /* setting GpsuedoStkPtr has side effects here: */
10064 /* FIXME: What's the correct size of the return(ed) value?
10065 * For now, assuming '4' as before... */
10066 assignResultValue(IC_RESULT(ic), 4, 0);
10069 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10072 /*-----------------------------------------------------------------*/
10073 /* genDummyRead - generate code for dummy read of volatiles */
10074 /*-----------------------------------------------------------------*/
10076 genDummyRead (iCode * ic)
10082 if (op && IS_SYMOP(op)) {
10083 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10084 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10087 pic16_aopOp (op, ic, FALSE);
10088 for (i=0; i < AOP_SIZE(op); i++) {
10089 // may need to protect this from the peepholer -- this is not nice but works...
10090 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
10091 pic16_mov2w (AOP(op),i);
10092 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
10094 pic16_freeAsmop (op, NULL, ic, TRUE);
10096 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10100 /*-----------------------------------------------------------------*/
10101 /* genpic16Code - generate code for pic16 based controllers */
10102 /*-----------------------------------------------------------------*/
10104 * At this point, ralloc.c has gone through the iCode and attempted
10105 * to optimize in a way suitable for a PIC. Now we've got to generate
10106 * PIC instructions that correspond to the iCode.
10108 * Once the instructions are generated, we'll pass through both the
10109 * peep hole optimizer and the pCode optimizer.
10110 *-----------------------------------------------------------------*/
10112 void genpic16Code (iCode *lic)
10117 lineHead = lineCurr = NULL;
10119 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10120 pic16_addpBlock(pb);
10123 /* if debug information required */
10124 if (options.debug && currFunc) {
10126 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10131 for (ic = lic ; ic ; ic = ic->next ) {
10133 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10134 if ( cln != ic->lineno ) {
10135 if ( options.debug ) {
10136 debugFile->writeCLine (ic);
10139 if(!options.noCcodeInAsm) {
10140 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10141 printCLine(ic->filename, ic->lineno)));
10147 if(options.iCodeInAsm) {
10150 /* insert here code to print iCode as comment */
10151 iLine = printILine(ic);
10152 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10156 /* if the result is marked as
10157 * spilt and rematerializable or code for
10158 * this has already been generated then
10160 if (resultRemat(ic) || ic->generated )
10163 /* depending on the operation */
10182 /* IPOP happens only when trying to restore a
10183 * spilt live range, if there is an ifx statement
10184 * following this pop then the if statement might
10185 * be using some of the registers being popped which
10186 * would destroy the contents of the register so
10187 * we need to check for this condition and handle it */
10189 && ic->next->op == IFX
10190 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10191 genIfx (ic->next,ic);
10209 genEndFunction (ic);
10225 pic16_genPlus (ic) ;
10229 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10230 pic16_genMinus (ic);
10246 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10250 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10256 /* note these two are xlated by algebraic equivalence
10257 * during parsing SDCC.y */
10258 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10259 "got '>=' or '<=' shouldn't have come here");
10263 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10275 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10279 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10283 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10307 genRightShift (ic);
10310 case GET_VALUE_AT_ADDRESS:
10315 if (POINTER_SET(ic))
10342 addSet(&_G.sendSet,ic);
10345 case DUMMY_READ_VOLATILE:
10355 /* now we are ready to call the
10356 peep hole optimizer */
10357 if (!options.nopeep)
10358 peepHole (&lineHead);
10360 /* now do the actual printing */
10361 printLine (lineHead, codeOutBuf);
10364 DFPRINTF((stderr,"printing pBlock\n\n"));
10365 pic16_printpBlock(stdout,pb);