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_mov2w_volatile (asmop *aop)
2003 if(!pic16_isLitAop(aop)) {
2004 // may need to protect this from the peepholer -- this is not nice but works...
2005 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2006 for (i = 0; i < aop->size; i++) {
2008 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2010 pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2012 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2016 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2018 if(pic16_isLitAop(src)) {
2019 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2020 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2022 if(pic16_sameRegsOfs(src, dst, offset))return;
2023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2024 pic16_popGet(dst, offset)));
2028 static void pic16_movLit2f(pCodeOp *pc, int lit)
2030 if (0 == (lit & 0x00ff))
2032 pic16_emitpcode (POC_CLRF, pc);
2033 } else if (0xff == (lit & 0x00ff))
2035 pic16_emitpcode (POC_SETF, pc);
2037 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2038 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2042 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2044 if(pic16_isLitAop(src)) {
2045 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2046 pic16_emitpcode(POC_MOVWF, dst);
2048 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2052 void pic16_testStackOverflow(void)
2054 #define GSTACK_TEST_NAME "_gstack_test"
2056 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2061 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2062 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2063 // strcpy(sym->rname, GSTACK_TEST_NAME);
2064 checkAddSym(&externs, sym);
2069 /* push pcop into stack */
2070 void pic16_pushpCodeOp(pCodeOp *pcop)
2072 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2073 if (pcop->type == PO_LITERAL) {
2074 pic16_emitpcode(POC_MOVLW, pcop);
2075 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2077 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2079 if(pic16_options.gstack)
2080 pic16_testStackOverflow();
2084 /* pop pcop from stack */
2085 void pic16_poppCodeOp(pCodeOp *pcop)
2087 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2088 if(pic16_options.gstack)
2089 pic16_testStackOverflow();
2093 /*-----------------------------------------------------------------*/
2094 /* pushw - pushes wreg to stack */
2095 /*-----------------------------------------------------------------*/
2098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2099 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2100 if(pic16_options.gstack)
2101 pic16_testStackOverflow();
2105 /*-----------------------------------------------------------------*/
2106 /* pushaop - pushes aop to stack */
2107 /*-----------------------------------------------------------------*/
2108 void pushaop(asmop *aop, int offset)
2110 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2112 if(_G.resDirect)return;
2114 if(pic16_isLitAop(aop)) {
2115 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2116 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2118 pic16_emitpcode(POC_MOVFF,
2119 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2122 if(pic16_options.gstack)
2123 pic16_testStackOverflow();
2126 /*-----------------------------------------------------------------*/
2127 /* popaop - pops aop from stack */
2128 /*-----------------------------------------------------------------*/
2129 void popaop(asmop *aop, int offset)
2131 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2132 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2133 if(pic16_options.gstack)
2134 pic16_testStackOverflow();
2137 void popaopidx(asmop *aop, int offset, int index)
2141 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2143 if(STACK_MODEL_LARGE)ofs++;
2145 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2146 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2147 if(pic16_options.gstack)
2148 pic16_testStackOverflow();
2151 /*-----------------------------------------------------------------*/
2152 /* pic16_getDataSize - get the operand data size */
2153 /*-----------------------------------------------------------------*/
2154 int pic16_getDataSize(operand *op)
2156 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2159 return AOP_SIZE(op);
2161 // tsd- in the pic port, the genptr size is 1, so this code here
2162 // fails. ( in the 8051 port, the size was 4).
2165 size = AOP_SIZE(op);
2166 if (size == GPTRSIZE)
2168 sym_link *type = operandType(op);
2169 if (IS_GENPTR(type))
2171 /* generic pointer; arithmetic operations
2172 * should ignore the high byte (pointer type).
2175 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2182 /*-----------------------------------------------------------------*/
2183 /* pic16_outAcc - output Acc */
2184 /*-----------------------------------------------------------------*/
2185 void pic16_outAcc(operand *result)
2188 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2189 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2192 size = pic16_getDataSize(result);
2194 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2197 /* unsigned or positive */
2199 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2204 /*-----------------------------------------------------------------*/
2205 /* pic16_outBitC - output a bit C */
2206 /* Move to result the value of Carry flag -- VR */
2207 /*-----------------------------------------------------------------*/
2208 void pic16_outBitC(operand *result)
2212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2214 /* if the result is bit */
2215 if (AOP_TYPE(result) == AOP_CRY) {
2216 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2217 pic16_aopPut(AOP(result),"c",0);
2220 i = AOP_SIZE(result);
2222 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2224 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2228 /*-----------------------------------------------------------------*/
2229 /* pic16_outBitOp - output a bit from Op */
2230 /* Move to result the value of set/clr op -- VR */
2231 /*-----------------------------------------------------------------*/
2232 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2236 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2238 /* if the result is bit */
2239 if (AOP_TYPE(result) == AOP_CRY) {
2240 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2241 pic16_aopPut(AOP(result),"c",0);
2244 i = AOP_SIZE(result);
2246 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2248 pic16_emitpcode(POC_RRCF, pcop);
2249 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2253 /*-----------------------------------------------------------------*/
2254 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2255 /*-----------------------------------------------------------------*/
2256 void pic16_toBoolean(operand *oper)
2258 int size = AOP_SIZE(oper) - 1;
2261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2263 if ( AOP_TYPE(oper) != AOP_ACC) {
2264 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2267 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2271 /*-----------------------------------------------------------------*/
2272 /* genUminusFloat - unary minus for floating points */
2273 /*-----------------------------------------------------------------*/
2274 static void genUminusFloat(operand *op,operand *result)
2276 int size ,offset =0 ;
2279 /* for this we just need to flip the
2280 first it then copy the rest in place */
2281 size = AOP_SIZE(op);
2282 assert( size == AOP_SIZE(result) );
2285 pic16_mov2f(AOP(result), AOP(op), offset);
2289 /* toggle the MSB's highest bit */
2290 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2293 /*-----------------------------------------------------------------*/
2294 /* genUminus - unary minus code generation */
2295 /*-----------------------------------------------------------------*/
2296 static void genUminus (iCode *ic)
2299 sym_link *optype, *rtype;
2306 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2307 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2309 /* if both in bit space then special case */
2310 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2311 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2313 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2314 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2315 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2319 optype = operandType(IC_LEFT(ic));
2320 rtype = operandType(IC_RESULT(ic));
2323 /* if float then do float stuff */
2324 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2325 if(IS_FIXED(optype))
2326 debugf("implement fixed16x16 type\n", 0);
2328 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2332 /* otherwise subtract from zero by taking the 2's complement */
2333 size = AOP_SIZE(IC_LEFT(ic));
2334 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2335 label = newiTempLabel ( NULL );
2337 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2338 for (i=size-1; i > 0; i--) {
2339 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2341 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2342 for (i=1; i < size; i++) {
2343 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2344 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2347 for (i=size-1; i >= 0; i--) {
2348 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2349 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2352 for (i=0; i < size-2; i++) {
2353 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2354 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2356 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2358 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2361 pic16_emitpLabel (label->key);
2364 /* release the aops */
2365 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2366 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2369 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2371 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2372 pic16_emitpcode(POC_MOVFW, src);
2373 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2375 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2376 src, pic16_popGet(AOP(op), offset)));
2381 /*-----------------------------------------------------------------*/
2382 /* assignResultValue - assign results to oper, rescall==1 is */
2383 /* called from genCall() or genPcall() */
2384 /*-----------------------------------------------------------------*/
2385 static void assignResultValue(operand * oper, int res_size, int rescall)
2387 int size = AOP_SIZE(oper);
2391 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2392 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2395 /* assign result from a call/pcall function() */
2397 /* function results are stored in a special order,
2398 * see top of file with Function return policy, or manual */
2401 /* 8-bits, result in WREG */
2402 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2404 if(size > 1 && res_size > 1) {
2405 /* 16-bits, result in PRODL:WREG */
2406 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2409 if(size > 2 && res_size > 2) {
2410 /* 24-bits, result in PRODH:PRODL:WREG */
2411 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2414 if(size > 3 && res_size > 3) {
2415 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2416 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2419 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2422 /* >32-bits, result on stack, and FSR0 points to beginning.
2423 * Fix stack when done */
2425 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2427 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2428 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2430 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2435 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2436 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2437 if(STACK_MODEL_LARGE) {
2439 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2443 int areg = 0; /* matching argument register */
2445 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2446 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2449 /* its called from genReceive (probably) -- VR */
2450 /* I hope this code will not be called from somewhere else in the future!
2451 * We manually set the pseudo stack pointer in genReceive. - dw
2453 if(!GpsuedoStkPtr && _G.useWreg) {
2454 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2456 /* The last byte in the assignment is in W */
2457 if(areg <= GpsuedoStkPtr) {
2459 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2461 // debugf("receive from WREG\n", 0);
2463 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2466 _G.stack_lat = AOP_SIZE(oper)-1;
2471 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2472 // debugf("receive from STACK\n", 0);
2479 /*-----------------------------------------------------------------*/
2480 /* genIpush - generate code for pushing this gets a little complex */
2481 /*-----------------------------------------------------------------*/
2482 static void genIpush (iCode *ic)
2484 // int size, offset=0;
2487 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2490 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2492 /* send to stack as normal */
2493 addSet(&_G.sendSet,ic);
2494 // addSetHead(&_G.sendSet,ic);
2495 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2500 int size, offset = 0 ;
2504 /* if this is not a parm push : ie. it is spill push
2505 and spill push is always done on the local stack */
2506 if (!ic->parmPush) {
2508 /* and the item is spilt then do nothing */
2509 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2512 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2513 size = AOP_SIZE(IC_LEFT(ic));
2514 /* push it on the stack */
2516 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2521 pic16_emitcode("push","%s",l);
2526 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2530 /*-----------------------------------------------------------------*/
2531 /* genIpop - recover the registers: can happen only for spilling */
2532 /*-----------------------------------------------------------------*/
2533 static void genIpop (iCode *ic)
2536 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2541 /* if the temp was not pushed then */
2542 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2545 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2546 size = AOP_SIZE(IC_LEFT(ic));
2549 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2552 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2556 static int wparamCmp(void *p1, void *p2)
2558 return (!strcmp((char *)p1, (char *)p2));
2561 int inWparamList(char *s)
2563 return isinSetWith(wparamList, s, wparamCmp);
2567 /*-----------------------------------------------------------------*/
2568 /* genCall - generates a call statement */
2569 /*-----------------------------------------------------------------*/
2570 static void genCall (iCode *ic)
2580 ftype = OP_SYM_TYPE(IC_LEFT(ic));
2581 /* if caller saves & we have not saved then */
2582 // if (!ic->regsSaved)
2583 // saveRegisters(ic);
2585 /* initialise stackParms for IPUSH pushes */
2586 // stackParms = psuedoStkPtr;
2587 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2588 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2589 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2592 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2595 /* if send set is not empty the assign */
2598 int psuedoStkPtr=-1;
2599 int firstTimeThruLoop = 1;
2602 /* reverse sendSet if function is not reentrant */
2603 if(!IFFUNC_ISREENT(ftype))
2604 _G.sendSet = reverseSet(_G.sendSet);
2606 /* First figure how many parameters are getting passed */
2610 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2614 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2615 size = AOP_SIZE(IC_LEFT(sic));
2619 /* pass the last byte through WREG */
2623 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2624 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2625 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2627 if(!firstTimeThruLoop) {
2628 /* If this is not the first time we've been through the loop
2629 * then we need to save the parameter in a temporary
2630 * register. The last byte of the last parameter is
2634 // --psuedoStkPtr; // sanity check
2638 firstTimeThruLoop=0;
2640 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2645 /* all arguments are passed via stack */
2649 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2650 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2651 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2653 // pushaop(AOP(IC_LEFT(sic)), size);
2654 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2661 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2665 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2666 pushw(); /* save last parameter to stack if functions has varargs */
2670 } else use_wreg = 0;
2672 _G.stackRegSet = _G.sendSet;
2677 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2681 /* if we need to assign a result value */
2682 if ((IS_ITEMP(IC_RESULT(ic))
2683 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2684 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2685 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2688 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2691 /* Must not assign an 8-bit result to a 16-bit variable;
2692 * this would use (used...) the uninitialized PRODL! */
2693 /* FIXME: Need a proper way to obtain size of function result type,
2694 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2695 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2697 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2698 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2700 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2703 if(!stackParms && ic->parmBytes) {
2704 stackParms = ic->parmBytes;
2707 stackParms -= use_wreg;
2710 if(stackParms == 1) {
2711 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
2713 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2714 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2716 if(STACK_MODEL_LARGE) {
2718 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2723 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2726 /* adjust the stack for parameters if required */
2727 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2730 /* if register bank was saved then pop them */
2732 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2734 /* if we hade saved some registers then unsave them */
2735 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2736 unsaveRegisters (ic);
2742 /*-----------------------------------------------------------------*/
2743 /* genPcall - generates a call by pointer statement */
2744 /* new version, created from genCall - HJD */
2745 /*-----------------------------------------------------------------*/
2746 static void genPcall (iCode *ic)
2750 symbol *retlbl = newiTempLabel(NULL);
2751 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2755 fntype = operandType( IC_LEFT(ic) )->next;
2757 /* if send set is not empty the assign */
2760 int psuedoStkPtr=-1;
2762 /* reverse sendSet if function is not reentrant */
2763 if(!IFFUNC_ISREENT(fntype))
2764 _G.sendSet = reverseSet(_G.sendSet);
2768 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2771 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2772 size = AOP_SIZE(IC_LEFT(sic));
2775 /* all parameters are passed via stack, since WREG is clobbered
2776 * by the calling sequence */
2778 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2779 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2780 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2782 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2786 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2789 _G.stackRegSet = _G.sendSet;
2793 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2795 // push return address
2796 // push $ on return stack, then replace with retlbl
2798 /* Thanks to Thorsten Klose for pointing out that the following
2799 * snippet should be interrupt safe */
2800 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2801 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2803 pic16_emitpcodeNULLop(POC_PUSH);
2805 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2806 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2807 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2808 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2809 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2810 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2813 /* restore interrupt control register */
2814 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2815 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2817 /* make the call by writing the pointer into pc */
2818 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2819 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2821 // note: MOVFF to PCL not allowed
2822 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2823 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2826 /* return address is here: (X) */
2827 pic16_emitpLabelFORCE(retlbl->key);
2829 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2832 /* if we need assign a result value */
2833 if ((IS_ITEMP(IC_RESULT(ic))
2834 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2835 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2836 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2839 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2842 /* FIXME: Need proper way to obtain the function result's type.
2843 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2844 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2846 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2847 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2849 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2852 // stackParms -= use_wreg;
2855 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2856 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2857 if(STACK_MODEL_LARGE) {
2859 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2864 /*-----------------------------------------------------------------*/
2865 /* resultRemat - result is rematerializable */
2866 /*-----------------------------------------------------------------*/
2867 static int resultRemat (iCode *ic)
2869 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2870 if (SKIP_IC(ic) || ic->op == IFX)
2873 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2874 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2875 if (sym->remat && !POINTER_SET(ic))
2883 /*-----------------------------------------------------------------*/
2884 /* inExcludeList - return 1 if the string is in exclude Reg list */
2885 /*-----------------------------------------------------------------*/
2886 static bool inExcludeList(char *s)
2888 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2892 if (options.excludeRegs[i] &&
2893 STRCASECMP(options.excludeRegs[i],"none") == 0)
2896 for ( i = 0 ; options.excludeRegs[i]; i++) {
2897 if (options.excludeRegs[i] &&
2898 STRCASECMP(s,options.excludeRegs[i]) == 0)
2905 /*-----------------------------------------------------------------*/
2906 /* genFunction - generated code for function entry */
2907 /*-----------------------------------------------------------------*/
2908 static void genFunction (iCode *ic)
2914 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2916 pic16_labelOffset += (max_key+4);
2921 ftype = operandType(IC_LEFT(ic));
2922 sym = OP_SYMBOL(IC_LEFT(ic));
2924 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2925 /* create an absolute section at the interrupt vector:
2926 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2931 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2933 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2934 sprintf(asymname, "ivec_%s", sym->name);
2936 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2938 /* when an interrupt is declared as naked, do not emit the special
2939 * wrapper segment at vector address. The user should take care for
2940 * this instead. -- VR */
2942 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2943 asym = newSymbol(asymname, 0);
2944 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2945 pic16_addpBlock( apb );
2947 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2948 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2949 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2950 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2951 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2953 /* mark the end of this tiny function */
2954 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2956 sprintf(asymname, "%s", sym->rname);
2962 abSym = Safe_calloc(1, sizeof(absSym));
2963 strcpy(abSym->name, asymname);
2965 switch( FUNC_INTNO(sym->type) ) {
2966 case 0: abSym->address = 0x000000; break;
2967 case 1: abSym->address = 0x000008; break;
2968 case 2: abSym->address = 0x000018; break;
2971 // fprintf(stderr, "no interrupt number is given\n");
2972 abSym->address = -1; break;
2975 /* relocate interrupt vectors if needed */
2976 if(abSym->address != -1)
2977 abSym->address += pic16_options.ivt_loc;
2979 addSet(&absSymSet, abSym);
2983 /* create the function header */
2984 pic16_emitcode(";","-----------------------------------------");
2985 pic16_emitcode(";"," function %s",sym->name);
2986 pic16_emitcode(";","-----------------------------------------");
2988 /* prevent this symbol from being emitted as 'extern' */
2989 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2991 pic16_emitcode("","%s:",sym->rname);
2992 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2997 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2998 if(!strcmp(ab->name, sym->rname)) {
2999 pic16_pBlockConvert2Absolute(pb);
3005 if(IFFUNC_ISNAKED(ftype)) {
3006 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3010 /* if critical function then turn interrupts off */
3011 if (IFFUNC_ISCRITICAL(ftype)) {
3012 //pic16_emitcode("clr","ea");
3015 currFunc = sym; /* update the currFunc symbol */
3016 _G.fregsUsed = sym->regsUsed;
3017 _G.sregsAlloc = newBitVect(128);
3020 /* if this is an interrupt service routine then
3021 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3022 if (IFFUNC_ISISR(sym->type)) {
3023 _G.usefastretfie = 1; /* use shadow registers by default */
3025 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3026 if(!FUNC_ISSHADOWREGS(sym->type)) {
3027 /* do not save WREG,STATUS,BSR for high priority interrupts
3028 * because they are stored in the hardware shadow registers already */
3029 _G.usefastretfie = 0;
3030 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3031 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3032 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3035 /* these should really be optimized somehow, because not all
3036 * interrupt handlers modify them */
3037 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3038 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3039 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3040 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3041 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3042 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3044 // pic16_pBlockConvert2ISR(pb);
3047 /* emit code to setup stack frame if user enabled,
3048 * and function is not main() */
3050 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3051 if(strcmp(sym->name, "main")) {
3053 || !options.ommitFramePtr
3055 || IFFUNC_ARGS(sym->type)
3056 || FUNC_HASSTACKPARM(sym->etype)
3058 /* setup the stack frame */
3059 if(STACK_MODEL_LARGE)
3060 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3061 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3063 if(STACK_MODEL_LARGE)
3064 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3065 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3069 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3072 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3074 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3075 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3077 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3080 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3081 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3088 /* if callee-save to be used for this function
3089 * then save the registers being used in this function */
3090 // if (IFFUNC_CALLEESAVES(sym->type))
3091 if(strcmp(sym->name, "main")) {
3094 /* if any registers used */
3095 if (sym->regsUsed) {
3096 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3099 /* save the registers used */
3100 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3101 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3102 if (bitVectBitValue(sym->regsUsed,i)) {
3104 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3106 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3109 if(!pic16_regWithIdx(i)->wasUsed) {
3110 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3111 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3112 pic16_regWithIdx(i)->wasUsed = 1;
3119 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3120 for(i=0;i<sym->regsUsed->size;i++) {
3121 if(bitVectBitValue(sym->regsUsed, i)) {
3126 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3129 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3134 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3135 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3138 /*-----------------------------------------------------------------*/
3139 /* genEndFunction - generates epilogue for functions */
3140 /*-----------------------------------------------------------------*/
3141 static void genEndFunction (iCode *ic)
3143 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3147 if(IFFUNC_ISNAKED(sym->type)) {
3148 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3154 /* add code for ISCRITICAL */
3155 if(IFFUNC_ISCRITICAL(sym->type)) {
3156 /* if critical function, turn on interrupts */
3158 /* TODO: add code here -- VR */
3161 // sym->regsUsed = _G.fregsUsed;
3163 /* now we need to restore the registers */
3164 /* if any registers used */
3166 /* first restore registers that might be used for stack access */
3167 if(_G.sregsAllocSet) {
3170 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3171 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3172 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3176 if (strcmp(sym->name, "main") && sym->regsUsed) {
3179 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3180 /* restore registers used */
3181 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3182 for ( i = sym->regsUsed->size; i >= 0; i--) {
3183 if (bitVectBitValue(sym->regsUsed,i)) {
3184 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3188 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3193 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3195 if (sym->stack == 1) {
3196 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3197 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3199 // we have to add more than one...
3200 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3201 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3202 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3204 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3205 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3206 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3210 if(strcmp(sym->name, "main")) {
3212 || !options.ommitFramePtr
3214 || IFFUNC_ARGS(sym->type)
3215 || FUNC_HASSTACKPARM(sym->etype)
3217 /* restore stack frame */
3218 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3219 if(STACK_MODEL_LARGE)
3220 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3226 if (IFFUNC_ISISR(sym->type)) {
3227 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3228 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3229 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3230 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3231 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3232 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3234 if(!FUNC_ISSHADOWREGS(sym->type)) {
3235 /* do not restore interrupt vector for WREG,STATUS,BSR
3236 * for high priority interrupt, see genFunction */
3237 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3238 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3239 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3241 // _G.interruptvector = 0; /* sanity check */
3244 /* if debug then send end of function */
3245 /* if (options.debug && currFunc) */
3247 debugFile->writeEndFunction (currFunc, ic, 1);
3250 if(_G.usefastretfie)
3251 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3253 pic16_emitpcodeNULLop(POC_RETFIE);
3255 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3257 _G.usefastretfie = 0;
3261 if (IFFUNC_ISCRITICAL(sym->type)) {
3262 pic16_emitcode("setb","ea");
3265 /* if debug then send end of function */
3267 debugFile->writeEndFunction (currFunc, ic, 1);
3270 /* insert code to restore stack frame, if user enabled it
3271 * and function is not main() */
3274 pic16_emitpcodeNULLop(POC_RETURN);
3276 /* Mark the end of a function */
3277 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3281 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3283 unsigned long lit=1;
3288 // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3289 if(AOP_TYPE(op) == AOP_LIT) {
3290 if(!IS_FLOAT(operandType( op ))) {
3291 lit = ulFromVal (AOP(op)->aopu.aop_lit);
3294 unsigned long lit_int;
3298 /* take care if literal is a float */
3299 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3304 if (AOP_TYPE(op) == AOP_LIT) {
3305 /* FIXME: broken for
3306 * char __at(0x456) foo;
3308 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3309 pic16_movLit2f(dest, (lit >> (8ul*offset)));
3310 } else if (AOP_TYPE(op) == AOP_PCODE
3311 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3312 /* char *s= "aaa"; return s; */
3313 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3314 * that the generic pointer is interpreted correctly
3315 * as referring to __code space, but this is fragile! */
3316 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3317 /* XXX: should check that dest != WREG */
3318 pic16_emitpcode(POC_MOVWF, dest);
3320 if(dest->type == PO_WREG && (offset == 0)) {
3321 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3324 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3328 /*-----------------------------------------------------------------*/
3329 /* genRet - generate code for return statement */
3330 /*-----------------------------------------------------------------*/
3331 static void genRet (iCode *ic)
3337 /* if we have no return value then
3338 * just generate the "ret" */
3343 /* we have something to return then
3344 * move the return value into place */
3345 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3346 size = AOP_SIZE(IC_LEFT(ic));
3350 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3353 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3356 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3358 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3361 /* >32-bits, setup stack and FSR0 */
3363 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3364 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3366 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3368 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3373 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3374 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3376 if(STACK_MODEL_LARGE) {
3377 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3378 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3380 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3384 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3387 /* generate a jump to the return label
3388 * if the next is not the return statement */
3389 if (!(ic->next && ic->next->op == LABEL
3390 && IC_LABEL(ic->next) == returnLabel)) {
3392 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3393 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3397 /*-----------------------------------------------------------------*/
3398 /* genLabel - generates a label */
3399 /*-----------------------------------------------------------------*/
3400 static void genLabel (iCode *ic)
3404 /* special case never generate */
3405 if (IC_LABEL(ic) == entryLabel)
3408 pic16_emitpLabel(IC_LABEL(ic)->key);
3409 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3412 /*-----------------------------------------------------------------*/
3413 /* genGoto - generates a goto */
3414 /*-----------------------------------------------------------------*/
3416 static void genGoto (iCode *ic)
3419 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3420 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3424 /*-----------------------------------------------------------------*/
3425 /* genMultbits :- multiplication of bits */
3426 /*-----------------------------------------------------------------*/
3427 static void genMultbits (operand *left,
3433 if(!pic16_sameRegs(AOP(result),AOP(right)))
3434 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3436 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3437 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3438 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3443 /*-----------------------------------------------------------------*/
3444 /* genMultOneByte : 8 bit multiplication & division */
3445 /*-----------------------------------------------------------------*/
3446 static void genMultOneByte (operand *left,
3452 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3453 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3455 /* (if two literals, the value is computed before) */
3456 /* if one literal, literal on the right */
3457 if (AOP_TYPE(left) == AOP_LIT){
3463 /* size is already checked in genMult == 1 */
3464 // size = AOP_SIZE(result);
3466 if (AOP_TYPE(right) == AOP_LIT){
3467 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3468 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3469 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3470 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3472 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3473 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3474 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3475 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3478 pic16_genMult8X8_n (left, right,result);
3482 /*-----------------------------------------------------------------*/
3483 /* genMultOneWord : 16 bit multiplication */
3484 /*-----------------------------------------------------------------*/
3485 static void genMultOneWord (operand *left,
3490 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3491 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3493 /* (if two literals, the value is computed before)
3494 * if one literal, literal on the right */
3495 if (AOP_TYPE(left) == AOP_LIT){
3501 /* size is checked already == 2 */
3502 // size = AOP_SIZE(result);
3504 if (AOP_TYPE(right) == AOP_LIT) {
3505 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3506 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3507 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3508 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3510 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3511 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3512 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3513 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3516 pic16_genMult16X16_16(left, right,result);
3521 /*-----------------------------------------------------------------*/
3522 /* genMultOneLong : 32 bit multiplication */
3523 /*-----------------------------------------------------------------*/
3524 static void genMultOneLong (operand *left,
3529 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3530 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3532 /* (if two literals, the value is computed before)
3533 * if one literal, literal on the right */
3534 if (AOP_TYPE(left) == AOP_LIT){
3540 /* size is checked already == 4 */
3541 // size = AOP_SIZE(result);
3543 if (AOP_TYPE(right) == AOP_LIT) {
3544 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3545 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3546 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3547 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3549 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3550 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3551 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3552 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3555 pic16_genMult32X32_32(left, right,result);
3561 /*-----------------------------------------------------------------*/
3562 /* genMult - generates code for multiplication */
3563 /*-----------------------------------------------------------------*/
3564 static void genMult (iCode *ic)
3566 operand *left = IC_LEFT(ic);
3567 operand *right = IC_RIGHT(ic);
3568 operand *result= IC_RESULT(ic);
3571 /* assign the amsops */
3572 pic16_aopOp (left,ic,FALSE);
3573 pic16_aopOp (right,ic,FALSE);
3574 pic16_aopOp (result,ic,TRUE);
3576 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3578 /* special cases first *
3580 if (AOP_TYPE(left) == AOP_CRY
3581 && AOP_TYPE(right)== AOP_CRY) {
3582 genMultbits(left,right,result);
3586 /* if both are of size == 1 */
3587 if(AOP_SIZE(left) == 1
3588 && AOP_SIZE(right) == 1) {
3589 genMultOneByte(left,right,result);
3594 /* if both are of size == 2 */
3595 if(AOP_SIZE(left) == 2
3596 && AOP_SIZE(right) == 2) {
3597 genMultOneWord(left, right, result);
3601 /* if both are of size == 4 */
3602 if(AOP_SIZE(left) == 4
3603 && AOP_SIZE(right) == 4) {
3604 genMultOneLong(left, right, result);
3609 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3610 assert( !"Multiplication should have been transformed into function call!" );
3612 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3615 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3616 /* should have been converted to function call */
3620 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3621 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3622 pic16_freeAsmop(result,NULL,ic,TRUE);
3626 /*-----------------------------------------------------------------*/
3627 /* genDivbits :- division of bits */
3628 /*-----------------------------------------------------------------*/
3629 static void genDivbits (operand *left,
3636 /* the result must be bit */
3637 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3638 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3642 pic16_emitcode("div","ab");
3643 pic16_emitcode("rrc","a");
3644 pic16_aopPut(AOP(result),"c",0);
3647 /*-----------------------------------------------------------------*/
3648 /* genDivOneByte : 8 bit division */
3649 /*-----------------------------------------------------------------*/
3650 static void genDivOneByte (operand *left,
3654 sym_link *opetype = operandType(result);
3659 /* result = divident / divisor
3660 * - divident may be a register or a literal,
3661 * - divisor may be a register or a literal,
3662 * so there are 3 cases (literal / literal is optimized
3663 * by the front-end) to handle.
3664 * In addition we must handle signed and unsigned, which
3665 * result in 6 final different cases -- VR */
3669 size = AOP_SIZE(result) - 1;
3671 /* signed or unsigned */
3672 if (SPEC_USIGN(opetype)) {
3673 pCodeOp *pct1, /* count */
3676 symbol *label1, *label2, *label3;;
3679 /* unsigned is easy */
3681 pct1 = pic16_popGetTempReg(1);
3682 pct2 = pic16_popGetTempReg(1);
3683 pct3 = pic16_popGetTempReg(1);
3685 label1 = newiTempLabel(NULL);
3686 label2 = newiTempLabel(NULL);
3687 label3 = newiTempLabel(NULL);
3689 /* the following algorithm is extracted from divuint.c */
3691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3692 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3694 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3696 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3698 pic16_emitpLabel(label1->key);
3701 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3705 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3709 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3711 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3712 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3714 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3715 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3716 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3718 pic16_emitpLabel( label3->key );
3719 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3720 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3724 pic16_emitpLabel(label2->key);
3725 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3726 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3727 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3729 /* result is in wreg */
3730 if(AOP_TYPE(result) != AOP_ACC)
3731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3733 pic16_popReleaseTempReg( pct3, 1);
3734 pic16_popReleaseTempReg( pct2, 1);
3735 pic16_popReleaseTempReg( pct1, 1);
3740 /* signed is a little bit more difficult */
3742 /* save the signs of the operands */
3743 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3745 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3746 pic16_emitcode("push","acc"); /* save it on the stack */
3748 /* now sign adjust for both left & right */
3749 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3751 lbl = newiTempLabel(NULL);
3752 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3753 pic16_emitcode("cpl","a");
3754 pic16_emitcode("inc","a");
3755 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3756 pic16_emitcode("mov","b,a");
3758 /* sign adjust left side */
3759 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3762 lbl = newiTempLabel(NULL);
3763 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3764 pic16_emitcode("cpl","a");
3765 pic16_emitcode("inc","a");
3766 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3768 /* now the division */
3769 pic16_emitcode("div","ab");
3770 /* we are interested in the lower order
3772 pic16_emitcode("mov","b,a");
3773 lbl = newiTempLabel(NULL);
3774 pic16_emitcode("pop","acc");
3775 /* if there was an over flow we don't
3776 adjust the sign of the result */
3777 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3778 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3780 pic16_emitcode("clr","a");
3781 pic16_emitcode("subb","a,b");
3782 pic16_emitcode("mov","b,a");
3783 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3785 /* now we are done */
3786 pic16_aopPut(AOP(result),"b",0);
3788 pic16_emitcode("mov","c,b.7");
3789 pic16_emitcode("subb","a,acc");
3792 pic16_aopPut(AOP(result),"a",offset++);
3797 /*-----------------------------------------------------------------*/
3798 /* genDiv - generates code for division */
3799 /*-----------------------------------------------------------------*/
3800 static void genDiv (iCode *ic)
3802 operand *left = IC_LEFT(ic);
3803 operand *right = IC_RIGHT(ic);
3804 operand *result= IC_RESULT(ic);
3806 int leftVal = 0, rightVal = 0;
3808 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3811 /* Division is a very lengthy algorithm, so it is better
3812 * to call support routines than inlining algorithm.
3813 * Division functions written here just in case someone
3814 * wants to inline and not use the support libraries -- VR */
3818 /* assign the amsops */
3819 pic16_aopOp (left,ic,FALSE);
3820 pic16_aopOp (right,ic,FALSE);
3821 pic16_aopOp (result,ic,TRUE);
3825 else if (ic->op == '%')
3828 assert( !"invalid operation requested in genDivMod" );
3830 /* get literal values */
3831 if (IS_VALOP(left)) {
3832 leftVal = (int) ulFromVal ( OP_VALUE(left) );
3833 assert( leftVal >= -128 && leftVal < 256 );
3834 if (leftVal < 0) { signedLits++; }
3836 if (IS_VALOP(right)) {
3837 rightVal = (int) ulFromVal ( OP_VALUE(right) );
3838 assert( rightVal >= -128 && rightVal < 256 );
3839 if (rightVal < 0) { signedLits++; }
3842 /* We should only come here to convert all
3843 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3844 * with exactly one operand being s8_t into
3845 * u8_t x u8_t -> u8_t. All other cases should have been
3846 * turned into calls to support routines beforehand... */
3847 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3848 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3850 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3851 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3853 /* Both operands are signed or negative, use _divschar
3854 * instead of _divuchar */
3855 pushaop(AOP(right), 0);
3856 pushaop(AOP(left), 0);
3858 /* call _divschar */
3859 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3863 sym = newSymbol( functions[op][0], 0 );
3865 strcpy(sym->rname, functions[op][0]);
3866 checkAddSym(&externs, sym);
3870 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3871 if (AOP_SIZE(result) > 1)
3873 pic16_emitpcode(POC_MOVFF,
3874 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3875 pic16_popGet(AOP(result), 1)));
3877 pic16_addSign(result, 2, 1);
3880 /* clean up stack */
3881 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3882 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3887 /* push right operand */
3888 if (IS_VALOP(right)) {
3890 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3893 pushaop(AOP(right), 0);
3895 } else if (!IS_UNSIGNED(operandType(right))) {
3896 pic16_mov2w(AOP(right), 0);
3897 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3898 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3899 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3902 pushaop(AOP(right), 0);
3905 /* push left operand */
3906 if (IS_VALOP(left)) {
3908 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3911 pushaop(AOP(left), 0);
3913 } else if (!IS_UNSIGNED(operandType(left))) {
3914 pic16_mov2w(AOP(left),0);
3915 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3916 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3917 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3920 pushaop(AOP(left), 0);
3923 /* call _divuchar */
3924 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3928 sym = newSymbol( functions[op][1], 0 );
3930 strcpy(sym->rname, functions[op][1]);
3931 checkAddSym(&externs, sym);
3934 /* Revert negation(s) from above.
3935 * This is inefficient: if both operands are negative, this
3936 * should not touch WREG. However, determining that exactly
3937 * one operand was negated costs at least 3 instructions,
3938 * so there is nothing to be gained here, is there?
3940 * I negate WREG because either operand might share registers with
3941 * result, so assigning first might destroy an operand. */
3943 /* For the modulus operator, (a/b)*b == a shall hold.
3944 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3945 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
3946 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
3947 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
3948 * Only invert the result if the left operand is negative (sigh).
3950 if (AOP_SIZE(result) <= 1 || !negated)
3954 if (IS_VALOP(right)) {
3956 /* we negated this operand above */
3957 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3959 } else if (!IS_UNSIGNED(operandType(right))) {
3960 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3961 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3965 if (IS_VALOP(left)) {
3967 /* we negated this operand above */
3968 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3970 } else if (!IS_UNSIGNED(operandType(left))) {
3971 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3972 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3975 /* Move result to destination. */
3976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3978 /* Zero-extend: no operand was signed (or result is just a byte). */
3979 pic16_addSign(result, 1, 0);
3981 assert( AOP_SIZE(result) > 1 );
3982 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3985 if (IS_VALOP(right)) {
3987 /* we negated this operand above */
3988 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3990 } else if (!IS_UNSIGNED(operandType(right))) {
3991 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3992 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3996 if (IS_VALOP(left)) {
3998 /* we negated this operand above */
3999 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4001 } else if (!IS_UNSIGNED(operandType(left))) {
4002 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4003 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4006 /* Move result to destination. */
4007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4009 /* Negate result if required. */
4010 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4011 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4014 pic16_addSign(result, 2, 1);
4017 /* clean up stack */
4018 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4019 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4024 /* special cases first */
4026 if (AOP_TYPE(left) == AOP_CRY &&
4027 AOP_TYPE(right)== AOP_CRY) {
4028 genDivbits(left,right,result);
4032 /* if both are of size == 1 */
4033 if (AOP_SIZE(left) == 1 &&
4034 AOP_SIZE(right) == 1 ) {
4035 genDivOneByte(left,right,result);
4040 /* should have been converted to function call */
4043 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4044 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4045 pic16_freeAsmop(result,NULL,ic,TRUE);
4049 /*-----------------------------------------------------------------*/
4050 /* genModbits :- modulus of bits */
4051 /*-----------------------------------------------------------------*/
4052 static void genModbits (operand *left,
4060 werror(W_POSSBUG2, __FILE__, __LINE__);
4061 /* the result must be bit */
4062 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4063 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4067 pic16_emitcode("div","ab");
4068 pic16_emitcode("mov","a,b");
4069 pic16_emitcode("rrc","a");
4070 pic16_aopPut(AOP(result),"c",0);
4073 /*-----------------------------------------------------------------*/
4074 /* genModOneByte : 8 bit modulus */
4075 /*-----------------------------------------------------------------*/
4076 static void genModOneByte (operand *left,
4080 sym_link *opetype = operandType(result);
4085 werror(W_POSSBUG2, __FILE__, __LINE__);
4087 /* signed or unsigned */
4088 if (SPEC_USIGN(opetype)) {
4089 /* unsigned is easy */
4090 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4091 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4093 pic16_emitcode("div","ab");
4094 pic16_aopPut(AOP(result),"b",0);
4098 /* signed is a little bit more difficult */
4100 /* save the signs of the operands */
4101 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4104 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4105 pic16_emitcode("push","acc"); /* save it on the stack */
4107 /* now sign adjust for both left & right */
4108 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4111 lbl = newiTempLabel(NULL);
4112 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4113 pic16_emitcode("cpl","a");
4114 pic16_emitcode("inc","a");
4115 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4116 pic16_emitcode("mov","b,a");
4118 /* sign adjust left side */
4119 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4122 lbl = newiTempLabel(NULL);
4123 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4124 pic16_emitcode("cpl","a");
4125 pic16_emitcode("inc","a");
4126 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4128 /* now the multiplication */
4129 pic16_emitcode("div","ab");
4130 /* we are interested in the lower order
4132 lbl = newiTempLabel(NULL);
4133 pic16_emitcode("pop","acc");
4134 /* if there was an over flow we don't
4135 adjust the sign of the result */
4136 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4137 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4139 pic16_emitcode("clr","a");
4140 pic16_emitcode("subb","a,b");
4141 pic16_emitcode("mov","b,a");
4142 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4144 /* now we are done */
4145 pic16_aopPut(AOP(result),"b",0);
4150 /*-----------------------------------------------------------------*/
4151 /* genMod - generates code for division */
4152 /*-----------------------------------------------------------------*/
4153 static void genMod (iCode *ic)
4155 /* Task deferred to genDiv */
4158 operand *left = IC_LEFT(ic);
4159 operand *right = IC_RIGHT(ic);
4160 operand *result= IC_RESULT(ic);
4164 /* assign the amsops */
4165 pic16_aopOp (left,ic,FALSE);
4166 pic16_aopOp (right,ic,FALSE);
4167 pic16_aopOp (result,ic,TRUE);
4169 /* special cases first */
4171 if (AOP_TYPE(left) == AOP_CRY &&
4172 AOP_TYPE(right)== AOP_CRY) {
4173 genModbits(left,right,result);
4177 /* if both are of size == 1 */
4178 if (AOP_SIZE(left) == 1 &&
4179 AOP_SIZE(right) == 1 ) {
4180 genModOneByte(left,right,result);
4184 /* should have been converted to function call */
4188 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4189 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4190 pic16_freeAsmop(result,NULL,ic,TRUE);
4194 /*-----------------------------------------------------------------*/
4195 /* genIfxJump :- will create a jump depending on the ifx */
4196 /*-----------------------------------------------------------------*/
4198 note: May need to add parameter to indicate when a variable is in bit space.
4200 static void genIfxJump (iCode *ic, char *jval)
4204 /* if true label then we jump if condition
4206 if ( IC_TRUE(ic) ) {
4208 if(strcmp(jval,"a") == 0)
4210 else if (strcmp(jval,"c") == 0)
4213 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4214 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4217 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4218 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4222 /* false label is present */
4223 if(strcmp(jval,"a") == 0)
4225 else if (strcmp(jval,"c") == 0)
4228 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4229 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4232 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4233 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4238 /* mark the icode as generated */
4242 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4246 /* if true label then we jump if condition
4248 if ( IC_TRUE(ic) ) {
4249 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4250 pic16_emitpcode(POC_BTFSC, jop);
4252 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4253 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4256 /* false label is present */
4257 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4258 pic16_emitpcode(POC_BTFSS, jop);
4260 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4261 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4265 /* mark the icode as generated */
4272 /*-----------------------------------------------------------------*/
4274 /*-----------------------------------------------------------------*/
4275 static void genSkip(iCode *ifx,int status_bit)
4277 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4281 if ( IC_TRUE(ifx) ) {
4282 switch(status_bit) {
4297 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4298 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4302 switch(status_bit) {
4316 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4317 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4324 /*-----------------------------------------------------------------*/
4326 /*-----------------------------------------------------------------*/
4327 static void genSkipc(resolvedIfx *rifx)
4329 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4340 rifx->generated = 1;
4343 /*-----------------------------------------------------------------*/
4344 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4345 /* aop (if it's NOT a literal) or from lit (if */
4346 /* aop is a literal) */
4347 /*-----------------------------------------------------------------*/
4348 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4349 if (aop->type == AOP_LIT) {
4350 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4352 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4356 /*-----------------------------------------------------------------*/
4357 /* genCmp :- greater or less than comparison */
4358 /*-----------------------------------------------------------------*/
4360 /* genCmp performs a left < right comparison, stores
4361 * the outcome in result (if != NULL) and generates
4362 * control flow code for the ifx (if != NULL).
4364 * This version leaves in sequences like
4365 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4366 * which should be optmized by the peephole
4367 * optimizer - RN 2005-01-01 */
4368 static void genCmp (operand *left,operand *right,
4369 operand *result, iCode *ifx, int sign)
4382 assert (left && right);
4383 assert (AOP_SIZE(left) == AOP_SIZE(right));
4385 size = AOP_SIZE(right) - 1;
4386 mask = (0x100UL << (size*8)) - 1;
4387 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4392 resolveIfx (&rIfx, ifx);
4394 /* handle for special cases */
4395 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4398 /**********************************************************************
4399 * handle bits - bit compares are promoted to int compares seemingly! *
4400 **********************************************************************/
4402 // THIS IS COMPLETELY UNTESTED!
4403 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4404 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4405 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4406 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4409 // 1 < {0,1} is false --> clear C by skipping the next instruction
4410 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4411 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4412 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4413 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4414 emitCLRC; // only skipped for left=0 && right=1
4416 goto correct_result_in_carry;
4420 /*************************************************
4421 * make sure that left is register (or the like) *
4422 *************************************************/
4423 if (!isAOP_REGlike(left)) {
4424 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4425 assert (isAOP_LIT(left));
4426 assert (isAOP_REGlike(right));
4427 // swap left and right
4428 // left < right <==> right > left <==> (right >= left + 1)
4429 lit = ulFromVal (AOP(left)->aopu.aop_lit);
4431 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4432 // MAXVALUE < right? always false
4433 if (performedLt) emitCLRC; else emitSETC;
4434 goto correct_result_in_carry;
4437 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4438 // that's why we handled it above.
4445 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4446 } else if (isAOP_LIT(right)) {
4447 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4450 assert (isAOP_REGlike(left)); // left must be register or the like
4451 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4453 /*************************************************
4454 * special cases go here *
4455 *************************************************/
4457 if (isAOP_LIT(right)) {
4459 // unsigned comparison to a literal
4460 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4462 // unsigned left < 0? always false
4463 if (performedLt) emitCLRC; else emitSETC;
4464 goto correct_result_in_carry;
4467 // signed comparison to a literal
4468 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4469 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4470 // signed left < 0x80000000? always false
4471 if (performedLt) emitCLRC; else emitSETC;
4472 goto correct_result_in_carry;
4473 } else if (lit == 0) {
4474 // compare left < 0; set CARRY if SIGNBIT(left) is set
4475 if (performedLt) emitSETC; else emitCLRC;
4476 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4477 if (performedLt) emitCLRC; else emitSETC;
4478 goto correct_result_in_carry;
4481 } // right is literal
4483 /*************************************************
4484 * perform a general case comparison *
4485 * make sure we get CARRY==1 <==> left >= right *
4486 *************************************************/
4487 // compare most significant bytes
4488 //DEBUGpc ("comparing bytes at offset %d", size);
4490 // unsigned comparison
4491 mov2w_regOrLit (AOP(right), lit, size);
4492 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4494 // signed comparison
4495 // (add 2^n to both operands then perform an unsigned comparison)
4496 if (isAOP_LIT(right)) {
4497 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4498 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4500 if (litbyte == 0x80) {
4501 // left >= 0x80 -- always true, but more bytes to come
4502 pic16_mov2w (AOP(left), size);
4503 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4506 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4507 pic16_mov2w (AOP(left), size);
4508 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4509 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4512 /* using PRODL as a temporary register here */
4513 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4514 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4515 pic16_mov2w (AOP(left), size);
4516 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4517 pic16_emitpcode (POC_MOVWF, pctemp);
4518 pic16_mov2w (AOP(right), size);
4519 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4520 pic16_emitpcode (POC_SUBFW, pctemp);
4521 //pic16_popReleaseTempReg(pctemp, 1);
4525 // compare remaining bytes (treat as unsigned case from above)
4526 templbl = newiTempLabel ( NULL );
4529 //DEBUGpc ("comparing bytes at offset %d", offs);
4530 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4531 mov2w_regOrLit (AOP(right), lit, offs);
4532 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4534 pic16_emitpLabel (templbl->key);
4535 goto result_in_carry;
4539 /****************************************************
4540 * now CARRY contains the result of the comparison: *
4541 * SUBWF sets CARRY iff *
4542 * F-W >= 0 <==> F >= W <==> !(F < W) *
4543 * (F=left, W=right) *
4544 ****************************************************/
4547 if (result && AOP_TYPE(result) != AOP_CRY) {
4548 // value will be stored
4551 // value wil only be used in the following genSkipc()
4552 rIfx.condition ^= 1;
4556 correct_result_in_carry:
4558 // assign result to variable (if neccessary)
4559 if (result && AOP_TYPE(result) != AOP_CRY) {
4560 //DEBUGpc ("assign result");
4561 size = AOP_SIZE(result);
4563 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4565 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4568 // perform conditional jump
4570 //DEBUGpc ("generate control flow");
4576 /*-----------------------------------------------------------------*/
4577 /* genCmpGt :- greater than comparison */
4578 /*-----------------------------------------------------------------*/
4579 static void genCmpGt (iCode *ic, iCode *ifx)
4581 operand *left, *right, *result;
4582 sym_link *letype , *retype;
4588 right= IC_RIGHT(ic);
4589 result = IC_RESULT(ic);
4591 letype = getSpec(operandType(left));
4592 retype =getSpec(operandType(right));
4593 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4594 /* assign the amsops */
4595 pic16_aopOp (left,ic,FALSE);
4596 pic16_aopOp (right,ic,FALSE);
4597 pic16_aopOp (result,ic,TRUE);
4599 genCmp(right, left, result, ifx, sign);
4601 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4602 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4603 pic16_freeAsmop(result,NULL,ic,TRUE);
4606 /*-----------------------------------------------------------------*/
4607 /* genCmpLt - less than comparisons */
4608 /*-----------------------------------------------------------------*/
4609 static void genCmpLt (iCode *ic, iCode *ifx)
4611 operand *left, *right, *result;
4612 sym_link *letype , *retype;
4618 right= IC_RIGHT(ic);
4619 result = IC_RESULT(ic);
4621 letype = getSpec(operandType(left));
4622 retype =getSpec(operandType(right));
4623 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4625 /* assign the amsops */
4626 pic16_aopOp (left,ic,FALSE);
4627 pic16_aopOp (right,ic,FALSE);
4628 pic16_aopOp (result,ic,TRUE);
4630 genCmp(left, right, result, ifx, sign);
4632 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4633 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4634 pic16_freeAsmop(result,NULL,ic,TRUE);
4637 /*-----------------------------------------------------------------*/
4638 /* pic16_isLitOp - check if operand has to be treated as literal */
4639 /*-----------------------------------------------------------------*/
4640 bool pic16_isLitOp(operand *op)
4642 return ((AOP_TYPE(op) == AOP_LIT)
4643 || ( (AOP_TYPE(op) == AOP_PCODE)
4644 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4645 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4648 /*-----------------------------------------------------------------*/
4649 /* pic16_isLitAop - check if operand has to be treated as literal */
4650 /*-----------------------------------------------------------------*/
4651 bool pic16_isLitAop(asmop *aop)
4653 return ((aop->type == AOP_LIT)
4654 || ( (aop->type == AOP_PCODE)
4655 && ( (aop->aopu.pcop->type == PO_LITERAL)
4656 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4661 /*-----------------------------------------------------------------*/
4662 /* genCmpEq - generates code for equal to */
4663 /*-----------------------------------------------------------------*/
4664 static void genCmpEq (iCode *ic, iCode *ifx)
4666 operand *left, *right, *result;
4667 symbol *falselbl = newiTempLabel(NULL);
4668 symbol *donelbl = newiTempLabel(NULL);
4670 int preserve_result = 0;
4671 int generate_result = 0;
4673 unsigned long lit = -1;
4677 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4678 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4679 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4681 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4683 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4685 werror(W_POSSBUG2, __FILE__, __LINE__);
4686 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4687 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4691 if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4693 operand *tmp = right ;
4698 if (AOP_TYPE(right) == AOP_LIT) {
4699 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4702 if ( regsInCommon(left, result) || regsInCommon(right, result) )
4703 preserve_result = 1;
4705 if(result && AOP_SIZE(result))
4706 generate_result = 1;
4708 if(generate_result && !preserve_result)
4710 for(i = 0; i < AOP_SIZE(result); i++)
4711 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4714 assert( AOP_SIZE(left) == AOP_SIZE(right) );
4715 for(i=0; i < AOP_SIZE(left); i++)
4717 if(AOP_TYPE(left) != AOP_ACC)
4719 if(pic16_isLitOp(left))
4720 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4722 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4724 if(pic16_isLitOp(right)) {
4725 if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4726 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4729 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4731 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4736 if(generate_result && preserve_result)
4738 for(i = 0; i < AOP_SIZE(result); i++)
4739 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4743 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4745 if(generate_result && preserve_result)
4746 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4748 if(ifx && IC_TRUE(ifx))
4749 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4751 if(ifx && IC_FALSE(ifx))
4752 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4754 pic16_emitpLabel(falselbl->key);
4758 if(ifx && IC_FALSE(ifx))
4759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4761 if(generate_result && preserve_result)
4763 for(i = 0; i < AOP_SIZE(result); i++)
4764 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4767 pic16_emitpLabel(donelbl->key);
4773 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4774 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4775 pic16_freeAsmop(result,NULL,ic,TRUE);
4781 // old version kept for reference
4783 /*-----------------------------------------------------------------*/
4784 /* genCmpEq - generates code for equal to */
4785 /*-----------------------------------------------------------------*/
4786 static void genCmpEq (iCode *ic, iCode *ifx)
4788 operand *left, *right, *result;
4789 unsigned long lit = 0L;
4791 symbol *falselbl = newiTempLabel(NULL);
4794 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4797 DEBUGpic16_emitcode ("; ifx is non-null","");
4799 DEBUGpic16_emitcode ("; ifx is null","");
4801 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4802 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4803 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4805 size = max(AOP_SIZE(left),AOP_SIZE(right));
4807 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4809 /* if literal, literal on the right or
4810 if the right is in a pointer register and left
4812 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4813 operand *tmp = right ;
4819 if(ifx && !AOP_SIZE(result)){
4821 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
4822 /* if they are both bit variables */
4823 if (AOP_TYPE(left) == AOP_CRY &&
4824 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4825 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
4826 if(AOP_TYPE(right) == AOP_LIT){
4827 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4829 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4830 pic16_emitcode("cpl","c");
4831 } else if(lit == 1L) {
4832 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4834 pic16_emitcode("clr","c");
4836 /* AOP_TYPE(right) == AOP_CRY */
4838 symbol *lbl = newiTempLabel(NULL);
4839 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4840 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4841 pic16_emitcode("cpl","c");
4842 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4844 /* if true label then we jump if condition
4846 tlbl = newiTempLabel(NULL);
4847 if ( IC_TRUE(ifx) ) {
4848 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4849 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4851 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4852 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4854 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4857 /* left and right are both bit variables, result is carry */
4860 resolveIfx(&rIfx,ifx);
4862 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4863 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4864 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4865 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4870 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
4872 /* They're not both bit variables. Is the right a literal? */
4873 if(AOP_TYPE(right) == AOP_LIT) {
4874 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4879 switch(lit & 0xff) {
4881 if ( IC_TRUE(ifx) ) {
4882 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4884 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4886 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4887 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4891 if ( IC_TRUE(ifx) ) {
4892 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4896 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4897 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4901 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4903 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4908 /* end of size == 1 */
4912 genc16bit2lit(left,lit,offset);
4915 /* end of size == 2 */
4920 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4921 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4922 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4923 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4926 /* search for patterns that can be optimized */
4928 genc16bit2lit(left,lit,0);
4932 emitSKPZ; // if hi word unequal
4934 emitSKPNZ; // if hi word equal
4936 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4937 genc16bit2lit(left,lit,2);
4940 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4941 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4945 pic16_emitpLabel(falselbl->key);
4954 } else if(AOP_TYPE(right) == AOP_CRY ) {
4955 /* we know the left is not a bit, but that the right is */
4956 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4957 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4958 pic16_popGet(AOP(right),offset));
4959 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4961 /* if the two are equal, then W will be 0 and the Z bit is set
4962 * we could test Z now, or go ahead and check the high order bytes if
4963 * the variable we're comparing is larger than a byte. */
4966 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4968 if ( IC_TRUE(ifx) ) {
4970 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4971 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4974 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4975 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4979 /* They're both variables that are larger than bits */
4982 tlbl = newiTempLabel(NULL);
4985 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4986 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4988 if ( IC_TRUE(ifx) ) {
4992 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4994 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4995 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4999 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5002 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5003 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5008 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5011 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5015 if(s>1 && IC_TRUE(ifx)) {
5016 pic16_emitpLabel(tlbl->key);
5017 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5021 /* mark the icode as generated */
5026 /* if they are both bit variables */
5027 if (AOP_TYPE(left) == AOP_CRY &&
5028 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5029 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5030 if(AOP_TYPE(right) == AOP_LIT){
5031 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5033 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5034 pic16_emitcode("cpl","c");
5035 } else if(lit == 1L) {
5036 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5038 pic16_emitcode("clr","c");
5040 /* AOP_TYPE(right) == AOP_CRY */
5042 symbol *lbl = newiTempLabel(NULL);
5043 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5044 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5045 pic16_emitcode("cpl","c");
5046 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5049 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5050 pic16_outBitC(result);
5054 genIfxJump (ifx,"c");
5057 /* if the result is used in an arithmetic operation
5058 then put the result in place */
5059 pic16_outBitC(result);
5062 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5063 gencjne(left,right,result,ifx);
5066 gencjne(left,right,newiTempLabel(NULL));
5068 if(IC_TRUE(ifx)->key)
5069 gencjne(left,right,IC_TRUE(ifx)->key);
5071 gencjne(left,right,IC_FALSE(ifx)->key);
5075 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5076 pic16_aopPut(AOP(result),"a",0);
5081 genIfxJump (ifx,"a");
5085 /* if the result is used in an arithmetic operation
5086 then put the result in place */
5088 if (AOP_TYPE(result) != AOP_CRY)
5089 pic16_outAcc(result);
5091 /* leave the result in acc */
5095 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5096 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5097 pic16_freeAsmop(result,NULL,ic,TRUE);
5101 /*-----------------------------------------------------------------*/
5102 /* ifxForOp - returns the icode containing the ifx for operand */
5103 /*-----------------------------------------------------------------*/
5104 static iCode *ifxForOp ( operand *op, iCode *ic )
5108 /* if true symbol then needs to be assigned */
5109 if (IS_TRUE_SYMOP(op))
5112 /* if this has register type condition and
5113 the next instruction is ifx with the same operand
5114 and live to of the operand is upto the ifx only then */
5116 && ic->next->op == IFX
5117 && IC_COND(ic->next)->key == op->key
5118 && OP_SYMBOL(op)->liveTo <= ic->next->seq
5120 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5126 ic->next->op == IFX &&
5127 IC_COND(ic->next)->key == op->key) {
5128 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5133 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5135 ic->next->op == IFX)
5136 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5139 ic->next->op == IFX &&
5140 IC_COND(ic->next)->key == op->key) {
5141 DEBUGpic16_emitcode ("; "," key is okay");
5142 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5143 OP_SYMBOL(op)->liveTo,
5148 /* the code below is completely untested
5149 * it just allows ulong2fs.c compile -- VR */
5152 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5153 __FILE__, __FUNCTION__, __LINE__);
5155 /* if this has register type condition and
5156 the next instruction is ifx with the same operand
5157 and live to of the operand is upto the ifx only then */
5159 ic->next->op == IFX &&
5160 IC_COND(ic->next)->key == op->key &&
5161 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5165 ic->next->op == IFX &&
5166 IC_COND(ic->next)->key == op->key) {
5167 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5171 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5172 __FILE__, __FUNCTION__, __LINE__);
5174 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
5179 /*-----------------------------------------------------------------*/
5180 /* genAndOp - for && operation */
5181 /*-----------------------------------------------------------------*/
5182 static void genAndOp (iCode *ic)
5184 operand *left,*right, *result;
5189 /* note here that && operations that are in an
5190 if statement are taken away by backPatchLabels
5191 only those used in arthmetic operations remain */
5192 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5193 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5194 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5196 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5198 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5199 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5200 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5202 /* if both are bit variables */
5203 /* if (AOP_TYPE(left) == AOP_CRY && */
5204 /* AOP_TYPE(right) == AOP_CRY ) { */
5205 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5206 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5207 /* pic16_outBitC(result); */
5209 /* tlbl = newiTempLabel(NULL); */
5210 /* pic16_toBoolean(left); */
5211 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5212 /* pic16_toBoolean(right); */
5213 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5214 /* pic16_outBitAcc(result); */
5217 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5218 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5219 pic16_freeAsmop(result,NULL,ic,TRUE);
5223 /*-----------------------------------------------------------------*/
5224 /* genOrOp - for || operation */
5225 /*-----------------------------------------------------------------*/
5228 modified this code, but it doesn't appear to ever get called
5231 static void genOrOp (iCode *ic)
5233 operand *left,*right, *result;
5238 /* note here that || operations that are in an
5239 if statement are taken away by backPatchLabels
5240 only those used in arthmetic operations remain */
5241 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5242 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5243 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5245 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5247 /* if both are bit variables */
5248 if (AOP_TYPE(left) == AOP_CRY &&
5249 AOP_TYPE(right) == AOP_CRY ) {
5250 pic16_emitcode("clrc","");
5251 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5252 AOP(left)->aopu.aop_dir,
5253 AOP(left)->aopu.aop_dir);
5254 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5255 AOP(right)->aopu.aop_dir,
5256 AOP(right)->aopu.aop_dir);
5257 pic16_emitcode("setc","");
5260 tlbl = newiTempLabel(NULL);
5261 pic16_toBoolean(left);
5263 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5264 pic16_toBoolean(right);
5265 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5267 pic16_outBitAcc(result);
5270 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5271 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5272 pic16_freeAsmop(result,NULL,ic,TRUE);
5275 /*-----------------------------------------------------------------*/
5276 /* isLiteralBit - test if lit == 2^n */
5277 /*-----------------------------------------------------------------*/
5278 static int isLiteralBit(unsigned long lit)
5280 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5281 0x100L,0x200L,0x400L,0x800L,
5282 0x1000L,0x2000L,0x4000L,0x8000L,
5283 0x10000L,0x20000L,0x40000L,0x80000L,
5284 0x100000L,0x200000L,0x400000L,0x800000L,
5285 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5286 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5290 for(idx = 0; idx < 32; idx++)
5296 /*-----------------------------------------------------------------*/
5297 /* continueIfTrue - */
5298 /*-----------------------------------------------------------------*/
5299 static void continueIfTrue (iCode *ic)
5303 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5307 /*-----------------------------------------------------------------*/
5309 /*-----------------------------------------------------------------*/
5310 static void jumpIfTrue (iCode *ic)
5314 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5318 /*-----------------------------------------------------------------*/
5319 /* jmpTrueOrFalse - */
5320 /*-----------------------------------------------------------------*/
5321 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5323 // ugly but optimized by peephole
5326 symbol *nlbl = newiTempLabel(NULL);
5327 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5328 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5329 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5330 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5332 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5333 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5338 /*-----------------------------------------------------------------*/
5339 /* genAnd - code for and */
5340 /*-----------------------------------------------------------------*/
5341 static void genAnd (iCode *ic, iCode *ifx)
5343 operand *left, *right, *result;
5344 int size, offset = 0;
5345 unsigned long lit = 0L;
5350 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5351 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5352 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5354 resolveIfx (&rIfx, ifx);
5356 /* if left is a literal & right is not then exchange them */
5357 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5358 AOP_NEEDSACC (left))
5360 operand *tmp = right;
5365 /* if result = right then exchange them */
5366 if (pic16_sameRegs (AOP (result), AOP (right)))
5368 operand *tmp = right;
5373 /* if right is bit then exchange them */
5374 if (AOP_TYPE (right) == AOP_CRY &&
5375 AOP_TYPE (left) != AOP_CRY)
5377 operand *tmp = right;
5382 if (AOP_TYPE (right) == AOP_LIT)
5383 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5385 size = AOP_SIZE (result);
5387 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5390 // result = bit & yy;
5391 if (AOP_TYPE(left) == AOP_CRY){
5392 // c = bit & literal;
5393 if(AOP_TYPE(right) == AOP_LIT){
5395 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5398 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5401 if(size && (AOP_TYPE(result) == AOP_CRY)){
5402 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5405 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5409 pic16_emitcode("clr","c");
5412 if (AOP_TYPE(right) == AOP_CRY){
5414 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5415 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5418 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5420 pic16_emitcode("rrc","a");
5421 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5427 pic16_outBitC(result);
5429 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5430 genIfxJump(ifx, "c");
5434 // if (val & 0xZZ) - size = 0, ifx != FALSE -
5435 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5436 if ((AOP_TYPE (right) == AOP_LIT) &&
5437 (AOP_TYPE (result) == AOP_CRY) &&
5438 (AOP_TYPE (left) != AOP_CRY))
5440 symbol *tlbl = newiTempLabel (NULL);
5441 int sizel = AOP_SIZE (left);
5448 /* get number of non null bytes in literal */
5451 if (lit & (0xff << (sizel * 8)))
5455 emitBra = nonnull || rIfx.condition;
5457 for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5459 unsigned char bytelit = lit;
5467 /* patch provided by Aaron Colwell */
5468 if ((posbit = isLiteralBit (bytelit)) != 0)
5472 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5473 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5477 pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5482 if (bytelit == 0xff)
5484 /* Aaron had a MOVF instruction here, changed to MOVFW cause
5485 * a peephole could optimize it out -- VR */
5486 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5490 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5491 pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5498 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5502 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5507 /* last non null byte */
5517 // bit = left & literal
5521 pic16_emitpLabel (tlbl->key);
5524 // if(left & literal)
5530 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
5533 pic16_emitpLabel (tlbl->key);
5536 pic16_outBitC (result);
5540 /* if left is same as result */
5541 if(pic16_sameRegs(AOP(result),AOP(left))){
5543 for(;size--; offset++,lit>>=8) {
5544 if(AOP_TYPE(right) == AOP_LIT){
5545 switch(lit & 0xff) {
5547 /* and'ing with 0 has clears the result */
5548 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5549 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5552 /* and'ing with 0xff is a nop when the result and left are the same */
5557 int p = pic16_my_powof2( (~lit) & 0xff );
5559 /* only one bit is set in the literal, so use a bcf instruction */
5560 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5561 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5564 pic16_emitcode("movlw","0x%x", (lit & 0xff));
5565 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5566 if(know_W != (lit&0xff))
5567 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5569 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5574 if (AOP_TYPE(left) == AOP_ACC) {
5575 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5577 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5578 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5585 // left & result in different registers
5586 if(AOP_TYPE(result) == AOP_CRY){
5588 // if(size), result in bit
5589 // if(!size && ifx), conditional oper: if(left & right)
5590 symbol *tlbl = newiTempLabel(NULL);
5591 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5593 pic16_emitcode("setb","c");
5595 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5596 pic16_emitcode("anl","a,%s",
5597 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5598 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5603 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5604 pic16_outBitC(result);
5606 jmpTrueOrFalse(ifx, tlbl);
5608 for(;(size--);offset++) {
5610 // result = left & right
5611 if(AOP_TYPE(right) == AOP_LIT){
5612 int t = (lit >> (offset*8)) & 0x0FFL;
5615 pic16_emitcode("clrf","%s",
5616 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5617 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5620 pic16_emitcode("movf","%s,w",
5621 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5622 pic16_emitcode("movwf","%s",
5623 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5624 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5625 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5628 pic16_emitcode("movlw","0x%x",t);
5629 pic16_emitcode("andwf","%s,w",
5630 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5631 pic16_emitcode("movwf","%s",
5632 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5634 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5635 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5636 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5641 if (AOP_TYPE(left) == AOP_ACC) {
5642 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5643 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5645 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5646 pic16_emitcode("andwf","%s,w",
5647 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5648 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5649 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5651 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5652 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5658 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5659 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5660 pic16_freeAsmop(result,NULL,ic,TRUE);
5663 /*-----------------------------------------------------------------*/
5664 /* genOr - code for or */
5665 /*-----------------------------------------------------------------*/
5666 static void genOr (iCode *ic, iCode *ifx)
5668 operand *left, *right, *result;
5669 int size, offset = 0;
5670 unsigned long lit = 0L;
5675 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5676 pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5677 pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5679 resolveIfx (&rIfx, ifx);
5681 /* if left is a literal & right is not then exchange them */
5682 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5683 AOP_NEEDSACC (left))
5685 operand *tmp = right;
5690 /* if result = right then exchange them */
5691 if (pic16_sameRegs (AOP (result), AOP (right)))
5693 operand *tmp = right;
5698 /* if right is bit then exchange them */
5699 if (AOP_TYPE (right) == AOP_CRY &&
5700 AOP_TYPE (left) != AOP_CRY)
5702 operand *tmp = right;
5707 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5709 if (AOP_TYPE (right) == AOP_LIT)
5710 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5712 size = AOP_SIZE (result);
5716 if (AOP_TYPE(left) == AOP_CRY){
5717 if(AOP_TYPE(right) == AOP_LIT){
5718 // c = bit & literal;
5720 // lit != 0 => result = 1
5721 if(AOP_TYPE(result) == AOP_CRY){
5723 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5724 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5725 // AOP(result)->aopu.aop_dir,
5726 // AOP(result)->aopu.aop_dir);
5728 continueIfTrue(ifx);
5732 // lit == 0 => result = left
5733 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5735 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5738 if (AOP_TYPE(right) == AOP_CRY){
5739 if(pic16_sameRegs(AOP(result),AOP(left))){
5741 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5742 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5743 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5746 if( AOP_TYPE(result) == AOP_ACC) {
5747 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5748 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5749 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5750 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5754 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5755 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5756 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5757 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5763 symbol *tlbl = newiTempLabel(NULL);
5764 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5767 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
5768 if( AOP_TYPE(right) == AOP_ACC) {
5769 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5771 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5772 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5777 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5778 pic16_emitcode(";XXX setb","c");
5779 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5780 AOP(left)->aopu.aop_dir,tlbl->key+100);
5781 pic16_toBoolean(right);
5782 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5783 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5784 jmpTrueOrFalse(ifx, tlbl);
5788 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5795 pic16_outBitC(result);
5797 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5798 genIfxJump(ifx, "c");
5802 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5803 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5804 if ((AOP_TYPE (right) == AOP_LIT) &&
5805 (AOP_TYPE (result) == AOP_CRY) &&
5806 (AOP_TYPE (left) != AOP_CRY))
5808 if (IS_OP_VOLATILE(left)) {
5809 pic16_mov2w_volatile(AOP(left));
5814 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5823 /* if left is same as result */
5824 if(pic16_sameRegs(AOP(result),AOP(left))){
5826 for(;size--; offset++,lit>>=8) {
5827 if(AOP_TYPE(right) == AOP_LIT){
5828 if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5829 /* or'ing with 0 has no effect */
5832 int p = pic16_my_powof2(lit & 0xff);
5834 /* only one bit is set in the literal, so use a bsf instruction */
5835 pic16_emitpcode(POC_BSF,
5836 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5838 if(know_W != (lit & 0xff))
5839 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5840 know_W = lit & 0xff;
5841 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5846 if (AOP_TYPE(left) == AOP_ACC) {
5847 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
5849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5850 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5855 // left & result in different registers
5856 if(AOP_TYPE(result) == AOP_CRY){
5858 // if(size), result in bit
5859 // if(!size && ifx), conditional oper: if(left | right)
5860 symbol *tlbl = newiTempLabel(NULL);
5861 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5862 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5866 pic16_emitcode(";XXX setb","c");
5868 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5869 pic16_emitcode(";XXX orl","a,%s",
5870 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5871 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5876 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5877 pic16_outBitC(result);
5879 jmpTrueOrFalse(ifx, tlbl);
5880 } else for(;(size--);offset++){
5882 // result = left & right
5883 if(AOP_TYPE(right) == AOP_LIT){
5884 int t = (lit >> (offset*8)) & 0x0FFL;
5887 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
5888 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5892 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5893 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5898 // faster than result <- left, anl result,right
5899 // and better if result is SFR
5900 if (AOP_TYPE(left) == AOP_ACC) {
5901 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
5903 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
5904 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
5906 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
5911 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5912 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5913 pic16_freeAsmop(result,NULL,ic,TRUE);
5916 /*-----------------------------------------------------------------*/
5917 /* genXor - code for xclusive or */
5918 /*-----------------------------------------------------------------*/
5919 static void genXor (iCode *ic, iCode *ifx)
5921 operand *left, *right, *result;
5922 int size, offset = 0;
5923 unsigned long lit = 0L;
5928 pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5929 pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5930 pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5932 resolveIfx (&rIfx,ifx);
5934 /* if left is a literal & right is not ||
5935 if left needs acc & right does not */
5936 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5937 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5939 operand *tmp = right;
5944 /* if result = right then exchange them */
5945 if (pic16_sameRegs (AOP (result), AOP (right)))
5947 operand *tmp = right ;
5952 /* if right is bit then exchange them */
5953 if (AOP_TYPE (right) == AOP_CRY &&
5954 AOP_TYPE (left) != AOP_CRY)
5956 operand *tmp = right ;
5961 if (AOP_TYPE (right) == AOP_LIT)
5962 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5964 size = AOP_SIZE (result);
5968 if (AOP_TYPE(left) == AOP_CRY)
5970 if (AOP_TYPE(right) == AOP_LIT)
5972 // c = bit & literal;
5975 // lit>>1 != 0 => result = 1
5976 if (AOP_TYPE(result) == AOP_CRY)
5980 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
5983 continueIfTrue(ifx);
5986 pic16_emitcode("setb", "c");
5993 // lit == 0, result = left
5994 if (size && pic16_sameRegs(AOP(result), AOP(left)))
5996 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6000 // lit == 1, result = not(left)
6001 if (size && pic16_sameRegs(AOP(result), AOP(left)))
6003 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6004 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6005 pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6010 pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6011 pic16_emitcode("cpl", "c");
6019 symbol *tlbl = newiTempLabel(NULL);
6020 if (AOP_TYPE(right) == AOP_CRY)
6023 pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6027 int sizer = AOP_SIZE(right);
6029 // if val>>1 != 0, result = 1
6030 pic16_emitcode("setb", "c");
6033 MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6035 // test the msb of the lsb
6036 pic16_emitcode("anl", "a,#0xfe");
6037 pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6041 pic16_emitcode("rrc", "a");
6043 pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6044 pic16_emitcode("cpl", "c");
6045 pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6050 pic16_outBitC(result);
6052 else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6053 genIfxJump(ifx, "c");
6057 // if(val ^ 0xZZ) - size = 0, ifx != FALSE -
6058 // bit = val ^ 0xZZ - size = 1, ifx = FALSE -
6059 if ((AOP_TYPE (right) == AOP_LIT) &&
6060 (AOP_TYPE (result) == AOP_CRY) &&
6061 (AOP_TYPE (left) != AOP_CRY))
6063 symbol *tlbl = newiTempLabel (NULL);
6069 for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6071 unsigned char bytelit = lit;
6076 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6080 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6084 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6085 pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6092 /* rIfx.lbl might be far away... */
6094 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6098 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6103 /* last non null byte */
6111 // bit = left ^ literal
6115 pic16_emitpLabel (tlbl->key);
6117 // if (left ^ literal)
6122 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
6125 pic16_emitpLabel (tlbl->key);
6129 pic16_outBitC (result);
6133 if (pic16_sameRegs(AOP(result), AOP(left)))
6135 /* if left is same as result */
6136 for (; size--; offset++)
6138 if (AOP_TYPE(right) == AOP_LIT)
6140 int t = (lit >> (offset * 8)) & 0x0FFL;
6145 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6146 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6151 if (AOP_TYPE(left) == AOP_ACC)
6152 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6155 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6156 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6163 // left ^ result in different registers
6164 if (AOP_TYPE(result) == AOP_CRY)
6167 // if(size), result in bit
6168 // if(!size && ifx), conditional oper: if(left ^ right)
6169 symbol *tlbl = newiTempLabel(NULL);
6170 int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6172 pic16_emitcode("setb", "c");
6175 if ((AOP_TYPE(right) == AOP_LIT) &&
6176 (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6178 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6182 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6183 pic16_emitcode("xrl", "a,%s",
6184 pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6186 pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6192 pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6193 pic16_outBitC(result);
6196 jmpTrueOrFalse(ifx, tlbl);
6200 for (; (size--); offset++)
6203 // result = left ^ right
6204 if (AOP_TYPE(right) == AOP_LIT)
6206 int t = (lit >> (offset * 8)) & 0x0FFL;
6210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6211 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6215 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6216 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6220 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6221 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6227 // faster than result <- left, anl result,right
6228 // and better if result is SFR
6229 if (AOP_TYPE(left) == AOP_ACC)
6231 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6235 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6236 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6238 if ( AOP_TYPE(result) != AOP_ACC)
6240 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6247 pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6248 pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6249 pic16_freeAsmop(result, NULL, ic, TRUE);
6252 /*-----------------------------------------------------------------*/
6253 /* genInline - write the inline code out */
6254 /*-----------------------------------------------------------------*/
6255 static void genInline (iCode *ic)
6257 char *buffer, *bp, *bp1;
6258 bool inComment = FALSE;
6260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6262 _G.inLine += (!options.asmpeep);
6264 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6266 while((bp1=strstr(bp, "\\n"))) {
6274 /* This is an experimental code for #pragma inline
6275 and is temporarily disabled for 2.5.0 release */
6283 cbuf = Safe_strdup(buffer);
6284 cblen = strlen(buffer)+1;
6285 memset(cbuf, 0, cblen);
6290 if(*bp != '%')*bp1++ = *bp++;
6296 if(i>elementsInSet(asmInlineMap))break;
6299 s = indexSet(asmInlineMap, i);
6300 DEBUGpc("searching symbol s = `%s'", s);
6301 sym = findSym(SymbolTab, NULL, s);
6304 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6306 strcat(bp1, sym->rname);
6312 if(strlen(bp1) > cblen - 16) {
6313 int i = strlen(cbuf);
6315 cbuf = realloc(cbuf, cblen);
6316 memset(cbuf+i, 0, 50);
6322 buffer = Safe_strdup( cbuf );
6329 /* emit each line as a code */
6343 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6348 /* Add \n for labels, not dirs such as c:\mydir */
6349 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6354 /* print label, use this special format with NULL directive
6355 * to denote that the argument should not be indented with tab */
6356 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6365 if ((bp1 != bp) && *bp1)
6366 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6370 _G.inLine -= (!options.asmpeep);
6373 /*-----------------------------------------------------------------*/
6374 /* genRRC - rotate right with carry */
6375 /*-----------------------------------------------------------------*/
6376 static void genRRC (iCode *ic)
6378 operand *left , *result ;
6379 int size, offset = 0, same;
6381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6383 /* rotate right with carry */
6385 result=IC_RESULT(ic);
6386 pic16_aopOp (left,ic,FALSE);
6387 pic16_aopOp (result,ic,TRUE);
6389 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6391 same = pic16_sameRegs(AOP(result),AOP(left));
6393 size = AOP_SIZE(result);
6395 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6397 /* get the lsb and put it into the carry */
6398 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6405 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6407 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6408 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6414 pic16_freeAsmop(left,NULL,ic,TRUE);
6415 pic16_freeAsmop(result,NULL,ic,TRUE);
6418 /*-----------------------------------------------------------------*/
6419 /* genRLC - generate code for rotate left with carry */
6420 /*-----------------------------------------------------------------*/
6421 static void genRLC (iCode *ic)
6423 operand *left , *result ;
6424 int size, offset = 0;
6427 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6428 /* rotate right with carry */
6430 result=IC_RESULT(ic);
6431 pic16_aopOp (left,ic,FALSE);
6432 pic16_aopOp (result,ic,TRUE);
6434 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6436 same = pic16_sameRegs(AOP(result),AOP(left));
6438 /* move it to the result */
6439 size = AOP_SIZE(result);
6441 /* get the msb and put it into the carry */
6442 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6449 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6451 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6452 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6459 pic16_freeAsmop(left,NULL,ic,TRUE);
6460 pic16_freeAsmop(result,NULL,ic,TRUE);
6464 /* gpasm can get the highest order bit with HIGH/UPPER
6465 * so the following probably is not needed -- VR */
6467 /*-----------------------------------------------------------------*/
6468 /* genGetHbit - generates code get highest order bit */
6469 /*-----------------------------------------------------------------*/
6470 static void genGetHbit (iCode *ic)
6472 operand *left, *result;
6474 result=IC_RESULT(ic);
6475 pic16_aopOp (left,ic,FALSE);
6476 pic16_aopOp (result,ic,FALSE);
6478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6479 /* get the highest order byte into a */
6480 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6481 if(AOP_TYPE(result) == AOP_CRY){
6482 pic16_emitcode("rlc","a");
6483 pic16_outBitC(result);
6486 pic16_emitcode("rl","a");
6487 pic16_emitcode("anl","a,#0x01");
6488 pic16_outAcc(result);
6492 pic16_freeAsmop(left,NULL,ic,TRUE);
6493 pic16_freeAsmop(result,NULL,ic,TRUE);
6497 /*-----------------------------------------------------------------*/
6498 /* AccRol - rotate left accumulator by known count */
6499 /*-----------------------------------------------------------------*/
6500 static void AccRol (int shCount)
6502 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6503 shCount &= 0x0007; // shCount : 0..7
6508 pic16_emitcode("rl","a");
6511 pic16_emitcode("rl","a");
6512 pic16_emitcode("rl","a");
6515 pic16_emitcode("swap","a");
6516 pic16_emitcode("rr","a");
6519 pic16_emitcode("swap","a");
6522 pic16_emitcode("swap","a");
6523 pic16_emitcode("rl","a");
6526 pic16_emitcode("rr","a");
6527 pic16_emitcode("rr","a");
6530 pic16_emitcode("rr","a");
6536 /*-----------------------------------------------------------------*/
6537 /* AccLsh - left shift accumulator by known count */
6538 /*-----------------------------------------------------------------*/
6539 static void AccLsh (int shCount, int doMask)
6541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6547 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6550 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6551 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6554 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6555 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6558 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6561 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6562 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6565 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6566 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6569 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6573 /* no masking is required in genPackBits */
6574 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6578 /*-----------------------------------------------------------------*/
6579 /* AccRsh - right shift accumulator by known count */
6580 /*-----------------------------------------------------------------*/
6581 static void AccRsh (int shCount, int andmask)
6583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6584 assert ((shCount >= 0) && (shCount <= 8));
6589 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6592 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6593 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6596 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597 pic16_emitpcode(POC_RLNCFW,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_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6607 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6611 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6614 // Rotating by 8 is a NOP.
6619 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6621 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6624 /*-----------------------------------------------------------------*/
6625 /* shiftR1Left2Result - shift right one byte from left to result */
6626 /*-----------------------------------------------------------------*/
6627 static void shiftR1Left2ResultSigned (operand *left, int offl,
6628 operand *result, int offr,
6633 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6634 assert ((shCount >= 0) && (shCount <= 8));
6636 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6638 /* Do NOT use result for intermediate results, it might be an SFR!. */
6642 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6648 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6650 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6652 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6653 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6658 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6659 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6661 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6662 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6667 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6668 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6669 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6670 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6671 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6676 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6677 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6678 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6679 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6684 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6685 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6686 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6687 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6688 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6689 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6693 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6694 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6695 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6696 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6697 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6698 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6703 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6709 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6714 /*-----------------------------------------------------------------*/
6715 /* shiftR1Left2Result - shift right one byte from left to result */
6716 /*-----------------------------------------------------------------*/
6717 static void shiftR1Left2Result (operand *left, int offl,
6718 operand *result, int offr,
6719 int shCount, int sign)
6723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6724 assert ((shCount >= 0) && (shCount <= 8));
6726 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6728 /* Copy the msb into the carry if signed. */
6730 shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6734 /* Do NOT use result for intermediate results, it might be an SFR!. */
6738 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6739 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6746 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6748 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6749 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6750 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6755 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6756 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6757 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6758 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6762 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6763 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6764 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6765 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6769 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6770 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6775 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6776 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6777 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6778 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6782 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6783 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6784 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6785 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6789 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6790 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6791 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6795 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6800 /*-----------------------------------------------------------------*/
6801 /* shiftL1Left2Result - shift left one byte from left to result */
6802 /*-----------------------------------------------------------------*/
6803 static void shiftL1Left2Result (operand *left, int offl,
6804 operand *result, int offr, int shCount)
6808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6809 assert ((shCount >= 0) && (shCount <= 8));
6811 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6813 /* Do NOT use result for intermediate results, it might be an SFR!. */
6817 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6818 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6825 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6827 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6828 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6829 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6834 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6835 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6836 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6841 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6842 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6843 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6848 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6849 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6850 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6854 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6855 pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6856 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6861 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6862 pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6863 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6864 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6868 pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6869 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6870 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6874 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6879 /*-----------------------------------------------------------------*/
6880 /* movLeft2Result - move byte from left to result */
6881 /*-----------------------------------------------------------------*/
6882 static void movLeft2Result (operand *left, int offl,
6883 operand *result, int offr)
6885 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6886 if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6887 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6888 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6892 /*-----------------------------------------------------------------*/
6893 /* shiftL2Left2Result - shift left two bytes from left to result */
6894 /*-----------------------------------------------------------------*/
6895 static void shiftL2Left2Result (operand *left, int offl,
6896 operand *result, int offr, int shCount)
6898 int same = pic16_sameRegs(AOP(result), AOP(left));
6901 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6903 if (same && (offl != offr)) { // shift bytes
6906 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6907 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6909 } else { // just treat as different later on
6922 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6923 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6924 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6928 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6929 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6935 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6936 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6937 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6938 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6939 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6940 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6941 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6943 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6944 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6948 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6949 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6950 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6951 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6952 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6953 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6954 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6955 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6956 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6957 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6960 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6961 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6962 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6963 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6974 /* note, use a mov/add for the shift since the mov has a
6975 chance of getting optimized out */
6976 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6978 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6979 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6980 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6984 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6985 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6991 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6992 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6994 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6996 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
6997 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6998 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7003 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7007 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7008 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7009 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7010 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7012 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7013 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7014 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7015 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7016 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7017 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7018 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7019 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7022 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7024 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7025 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7026 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7031 /*-----------------------------------------------------------------*/
7032 /* shiftR2Left2Result - shift right two bytes from left to result */
7033 /*-----------------------------------------------------------------*/
7034 static void shiftR2Left2Result (operand *left, int offl,
7035 operand *result, int offr,
7036 int shCount, int sign)
7038 int same = pic16_sameRegs(AOP(result), AOP(left));
7040 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7042 if (same && (offl != offr)) { // shift right bytes
7045 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7046 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7048 } else { // just treat as different later on
7059 /* obtain sign from left operand */
7061 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7066 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7067 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7069 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7070 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7071 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7072 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7077 /* now get sign from already assigned result (avoid BANKSEL) */
7078 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7081 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7082 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7089 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7090 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7091 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7093 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7094 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7095 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7096 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7098 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7099 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7100 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7102 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7103 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7104 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7105 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7106 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7110 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7111 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7115 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7116 pic16_emitpcode(POC_BTFSC,
7117 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7118 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7126 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7127 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7129 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7130 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7131 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7132 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7134 pic16_emitpcode(POC_BTFSC,
7135 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7136 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7138 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7139 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7140 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7141 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7143 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7144 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7145 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7146 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7147 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7148 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7149 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7150 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7152 pic16_emitpcode(POC_BTFSC,
7153 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7154 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7156 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7157 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7164 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7165 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7167 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7170 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7172 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7177 /*-----------------------------------------------------------------*/
7178 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7179 /*-----------------------------------------------------------------*/
7180 static void shiftLLeftOrResult (operand *left, int offl,
7181 operand *result, int offr, int shCount)
7183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7185 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7186 /* shift left accumulator */
7188 /* or with result */
7189 /* back to result */
7190 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7193 /*-----------------------------------------------------------------*/
7194 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7195 /*-----------------------------------------------------------------*/
7196 static void shiftRLeftOrResult (operand *left, int offl,
7197 operand *result, int offr, int shCount)
7199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7201 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7202 /* shift right accumulator */
7204 /* or with result */
7205 /* back to result */
7206 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7209 /*-----------------------------------------------------------------*/
7210 /* genlshOne - left shift a one byte quantity by known count */
7211 /*-----------------------------------------------------------------*/
7212 static void genlshOne (operand *result, operand *left, int shCount)
7214 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7215 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7218 /*-----------------------------------------------------------------*/
7219 /* genlshTwo - left shift two bytes by known amount != 0 */
7220 /*-----------------------------------------------------------------*/
7221 static void genlshTwo (operand *result,operand *left, int shCount)
7225 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7226 size = pic16_getDataSize(result);
7228 /* if shCount >= 8 */
7234 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7236 movLeft2Result(left, LSB, result, MSB16);
7238 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7241 /* 1 <= shCount <= 7 */
7244 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7246 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7250 /*-----------------------------------------------------------------*/
7251 /* shiftLLong - shift left one long from left to result */
7252 /* offr = LSB or MSB16 */
7253 /*-----------------------------------------------------------------*/
7254 static void shiftLLong (operand *left, operand *result, int offr )
7256 int size = AOP_SIZE(result);
7257 int same = pic16_sameRegs(AOP(left),AOP(result));
7260 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7262 if (same && (offr == MSB16)) { //shift one byte
7263 for(i=size-1;i>=MSB16;i--) {
7264 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7265 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7268 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7271 if (size > LSB+offr ){
7273 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7275 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7276 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7280 if(size > MSB16+offr){
7282 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7284 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7285 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7289 if(size > MSB24+offr){
7291 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7293 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7294 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7298 if(size > MSB32+offr){
7300 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7302 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7303 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7307 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7311 /*-----------------------------------------------------------------*/
7312 /* genlshFour - shift four byte by a known amount != 0 */
7313 /*-----------------------------------------------------------------*/
7314 static void genlshFour (operand *result, operand *left, int shCount)
7318 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7319 size = AOP_SIZE(result);
7321 /* if shifting more that 3 bytes */
7322 if (shCount >= 24 ) {
7325 /* lowest order of left goes to the highest
7326 order of the destination */
7327 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7329 movLeft2Result(left, LSB, result, MSB32);
7331 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7332 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7333 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7338 /* more than two bytes */
7339 else if ( shCount >= 16 ) {
7340 /* lower order two bytes goes to higher order two bytes */
7342 /* if some more remaining */
7344 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7346 movLeft2Result(left, MSB16, result, MSB32);
7347 movLeft2Result(left, LSB, result, MSB24);
7349 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7350 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7354 /* if more than 1 byte */
7355 else if ( shCount >= 8 ) {
7356 /* lower order three bytes goes to higher order three bytes */
7360 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7362 movLeft2Result(left, LSB, result, MSB16);
7364 else{ /* size = 4 */
7366 movLeft2Result(left, MSB24, result, MSB32);
7367 movLeft2Result(left, MSB16, result, MSB24);
7368 movLeft2Result(left, LSB, result, MSB16);
7369 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7371 else if(shCount == 1)
7372 shiftLLong(left, result, MSB16);
7374 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7375 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7376 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7377 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7382 /* 1 <= shCount <= 7 */
7383 else if(shCount <= 3)
7385 shiftLLong(left, result, LSB);
7386 while(--shCount >= 1)
7387 shiftLLong(result, result, LSB);
7389 /* 3 <= shCount <= 7, optimize */
7391 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7392 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7393 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7397 /*-----------------------------------------------------------------*/
7398 /* genLeftShiftLiteral - left shifting by known count */
7399 /*-----------------------------------------------------------------*/
7400 void pic16_genLeftShiftLiteral (operand *left,
7405 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7409 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7410 pic16_freeAsmop(right,NULL,ic,TRUE);
7412 pic16_aopOp(left,ic,FALSE);
7413 pic16_aopOp(result,ic,TRUE);
7415 size = getSize(operandType(result));
7418 pic16_emitcode("; shift left ","result %d, left %d",size,
7422 /* I suppose that the left size >= result size */
7425 movLeft2Result(left, size, result, size);
7429 else if(shCount >= (size * 8))
7431 pic16_aopPut(AOP(result),zero,size);
7435 genlshOne (result,left,shCount);
7440 genlshTwo (result,left,shCount);
7444 genlshFour (result,left,shCount);
7448 pic16_freeAsmop(left,NULL,ic,TRUE);
7449 pic16_freeAsmop(result,NULL,ic,TRUE);
7452 /*-----------------------------------------------------------------*
7453 * genMultiAsm - repeat assembly instruction for size of register.
7454 * if endian == 1, then the high byte (i.e base address + size of
7455 * register) is used first else the low byte is used first;
7456 *-----------------------------------------------------------------*/
7457 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7475 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7481 /*-----------------------------------------------------------------*/
7482 /* genrshOne - right shift a one byte quantity by known count */
7483 /*-----------------------------------------------------------------*/
7484 static void genrshOne (operand *result, operand *left,
7485 int shCount, int sign)
7487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7488 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7491 /*-----------------------------------------------------------------*/
7492 /* genrshTwo - right shift two bytes by known amount != 0 */
7493 /*-----------------------------------------------------------------*/
7494 static void genrshTwo (operand *result,operand *left,
7495 int shCount, int sign)
7497 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7498 /* if shCount >= 8 */
7502 shiftR1Left2Result(left, MSB16, result, LSB,
7505 movLeft2Result(left, MSB16, result, LSB);
7507 pic16_addSign (result, 1, sign);
7510 /* 1 <= shCount <= 7 */
7512 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7515 /*-----------------------------------------------------------------*/
7516 /* shiftRLong - shift right one long from left to result */
7517 /* offl = LSB or MSB16 */
7518 /*-----------------------------------------------------------------*/
7519 static void shiftRLong (operand *left, int offl,
7520 operand *result, int sign)
7522 int size = AOP_SIZE(result);
7523 int same = pic16_sameRegs(AOP(left),AOP(result));
7525 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7527 if (same && (offl == MSB16)) { //shift one byte right
7528 for(i=MSB16;i<size;i++) {
7529 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7530 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7535 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7541 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7543 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7544 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7548 /* add sign of "a" */
7549 pic16_addSign(result, MSB32, sign);
7553 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7555 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7556 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7560 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7562 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7563 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7567 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7570 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7571 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7576 /*-----------------------------------------------------------------*/
7577 /* genrshFour - shift four byte by a known amount != 0 */
7578 /*-----------------------------------------------------------------*/
7579 static void genrshFour (operand *result, operand *left,
7580 int shCount, int sign)
7582 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7583 /* if shifting more that 3 bytes */
7584 if(shCount >= 24 ) {
7587 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7589 movLeft2Result(left, MSB32, result, LSB);
7591 pic16_addSign(result, MSB16, sign);
7593 else if(shCount >= 16){
7596 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7598 movLeft2Result(left, MSB24, result, LSB);
7599 movLeft2Result(left, MSB32, result, MSB16);
7601 pic16_addSign(result, MSB24, sign);
7603 else if(shCount >= 8){
7606 shiftRLong(left, MSB16, result, sign);
7607 else if(shCount == 0){
7608 movLeft2Result(left, MSB16, result, LSB);
7609 movLeft2Result(left, MSB24, result, MSB16);
7610 movLeft2Result(left, MSB32, result, MSB24);
7611 pic16_addSign(result, MSB32, sign);
7613 else{ //shcount >= 2
7614 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7615 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7616 /* the last shift is signed */
7617 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7618 pic16_addSign(result, MSB32, sign);
7621 else{ /* 1 <= shCount <= 7 */
7623 shiftRLong(left, LSB, result, sign);
7625 shiftRLong(result, LSB, result, sign);
7628 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7629 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7630 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7635 /*-----------------------------------------------------------------*/
7636 /* genRightShiftLiteral - right shifting by known count */
7637 /*-----------------------------------------------------------------*/
7638 static void genRightShiftLiteral (operand *left,
7644 int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7647 pic16_freeAsmop(right,NULL,ic,TRUE);
7649 pic16_aopOp(left,ic,FALSE);
7650 pic16_aopOp(result,ic,TRUE);
7652 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7655 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7659 lsize = pic16_getDataSize(left);
7660 res_size = pic16_getDataSize(result);
7661 /* test the LEFT size !!! */
7663 /* I suppose that the left size >= result size */
7665 assert (res_size <= lsize);
7666 while (res_size--) {
7667 pic16_mov2f (AOP(result), AOP(left), res_size);
7669 } else if (shCount >= (lsize * 8)) {
7676 * even for 8-bit operands; result might be an SFR.
7678 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7679 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7680 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7681 while (res_size--) {
7682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7684 } else { // unsigned
7685 while (res_size--) {
7686 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7689 } else { // 0 < shCount < 8*lsize
7692 genrshOne (result,left,shCount,sign);
7696 genrshTwo (result,left,shCount,sign);
7700 genrshFour (result,left,shCount,sign);
7707 pic16_freeAsmop(left,NULL,ic,TRUE);
7708 pic16_freeAsmop(result,NULL,ic,TRUE);
7711 /*-----------------------------------------------------------------*/
7712 /* genGenericShift - generates code for left or right shifting */
7713 /*-----------------------------------------------------------------*/
7714 static void genGenericShift (iCode *ic, int isShiftLeft)
7716 operand *left,*right, *result;
7718 int sign, signedCount;
7719 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7720 PIC_OPCODE pos_shift, neg_shift;
7724 right = IC_RIGHT(ic);
7726 result = IC_RESULT(ic);
7728 pic16_aopOp(right,ic,FALSE);
7729 pic16_aopOp(left,ic,FALSE);
7730 pic16_aopOp(result,ic,TRUE);
7732 sign = !SPEC_USIGN(operandType (left));
7733 signedCount = !SPEC_USIGN(operandType (right));
7735 /* if the shift count is known then do it
7736 as efficiently as possible */
7737 if (AOP_TYPE(right) == AOP_LIT) {
7738 long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7739 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7740 // we should modify right->aopu.aop_lit here!
7741 // Instead we use abs(shCount) in genXXXShiftLiteral()...
7742 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7744 pic16_genLeftShiftLiteral (left,right,result,ic);
7746 genRightShiftLiteral (left,right,result,ic, sign);
7749 } // if (right is literal)
7751 /* shift count is unknown then we have to form a loop.
7752 * Note: we take only the lower order byte since shifting
7753 * more than 32 bits make no sense anyway, ( the
7754 * largest size of an object can be only 32 bits )
7755 * Note: we perform arithmetic shifts if the left operand is
7756 * signed and we do an (effective) right shift, i. e. we
7757 * shift in the sign bit from the left. */
7759 label_complete = newiTempLabel ( NULL );
7760 label_loop_pos = newiTempLabel ( NULL );
7761 label_loop_neg = NULL;
7762 label_negative = NULL;
7763 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7764 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7767 // additional labels needed
7768 label_loop_neg = newiTempLabel ( NULL );
7769 label_negative = newiTempLabel ( NULL );
7772 // copy source to result -- this will effectively truncate the left operand to the size of result!
7773 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7774 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7775 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7776 pic16_mov2f (AOP(result),AOP(left), offset);
7779 // if result is longer than left, fill with zeros (or sign)
7780 if (AOP_SIZE(left) < AOP_SIZE(result)) {
7781 if (sign && AOP_SIZE(left) > 0) {
7782 // shift signed operand -- fill with sign
7783 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7784 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7785 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7786 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7787 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7790 // shift unsigned operand -- fill result with zeros
7791 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7792 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7795 } // if (size mismatch)
7797 pic16_mov2w (AOP(right), 0);
7798 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7799 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7802 // perform a shift by one (shift count is positive)
7803 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7804 // 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])
7805 pic16_emitpLabel (label_loop_pos->key);
7807 if (sign && (pos_shift == POC_RRCF)) {
7808 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7811 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7812 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7813 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7815 // perform a shift by one (shift count is positive)
7816 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7817 // 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])
7818 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7819 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7821 pic16_emitpLabel (label_loop_pos->key);
7822 if (sign && (pos_shift == POC_RRCF)) {
7823 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7826 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7827 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7828 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7829 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7833 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7835 pic16_emitpLabel (label_negative->key);
7836 // perform a shift by -1 (shift count is negative)
7837 // 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)
7839 pic16_emitpLabel (label_loop_neg->key);
7840 if (sign && (neg_shift == POC_RRCF)) {
7841 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7844 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7845 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7846 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7847 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7848 } // if (signedCount)
7850 pic16_emitpLabel (label_complete->key);
7853 pic16_freeAsmop (right,NULL,ic,TRUE);
7854 pic16_freeAsmop(left,NULL,ic,TRUE);
7855 pic16_freeAsmop(result,NULL,ic,TRUE);
7858 static void genLeftShift (iCode *ic) {
7859 genGenericShift (ic, 1);
7862 static void genRightShift (iCode *ic) {
7863 genGenericShift (ic, 0);
7867 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7868 void pic16_loadFSR0(operand *op, int lit)
7870 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7871 if (AOP_TYPE(op) == AOP_LIT) {
7872 /* handle 12 bit integers correctly */
7873 unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7874 if ((val & 0x0fff) != val) {
7875 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7876 val, (val & 0x0fff) );
7879 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7881 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7884 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7885 // set up FSR0 with address of result
7886 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7887 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7891 /*----------------------------------------------------------------*/
7892 /* pic16_derefPtr - move one byte from the location ptr points to */
7893 /* to WREG (doWrite == 0) or one byte from WREG */
7894 /* to the location ptr points to (doWrite != 0) */
7895 /*----------------------------------------------------------------*/
7896 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7898 if (!IS_PTR(operandType(ptr)))
7900 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7901 else pic16_mov2w (AOP(ptr), 0);
7905 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7906 /* We might determine pointer type right here: */
7907 p_type = DCL_TYPE(operandType(ptr));
7912 if (!fsr0_setup || !*fsr0_setup)
7914 pic16_loadFSR0( ptr, 0 );
7915 if (fsr0_setup) *fsr0_setup = 1;
7918 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7920 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7924 if (AOP(ptr)->aopu.aop_reg[2]) {
7925 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7926 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7927 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7928 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7929 pic16_mov2w(AOP(ptr), 2);
7930 pic16_callGenericPointerRW(doWrite, 1);
7932 // data pointer (just 2 byte given)
7933 if (!fsr0_setup || !*fsr0_setup)
7935 pic16_loadFSR0( ptr, 0 );
7936 if (fsr0_setup) *fsr0_setup = 1;
7939 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7941 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7946 assert (0 && "invalid pointer type specified");
7951 /*-----------------------------------------------------------------*/
7952 /* genUnpackBits - generates code for unpacking bits */
7953 /*-----------------------------------------------------------------*/
7954 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7957 sym_link *etype, *letype;
7963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7964 etype = getSpec(operandType(result));
7965 letype = getSpec(operandType(left));
7967 // if(IS_BITFIELD(etype)) {
7968 blen = SPEC_BLEN(etype);
7969 bstr = SPEC_BSTR(etype);
7972 lbstr = SPEC_BSTR( letype );
7974 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7975 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7978 if((blen == 1) && (bstr < 8)
7979 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
7980 /* it is a single bit, so use the appropriate bit instructions */
7981 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
7983 same = pic16_sameRegs(AOP(left),AOP(result));
7984 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
7985 pic16_emitpcode(POC_CLRF, op);
7987 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
7988 /* workaround to reduce the extra lfsr instruction */
7989 pic16_emitpcode(POC_BTFSC,
7990 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
7992 assert (PIC_IS_DATA_PTR (operandType(left)));
7993 pic16_loadFSR0 (left, 0);
7994 pic16_emitpcode(POC_BTFSC,
7995 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
7998 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7999 /* unsigned bitfields result in either 0 or 1 */
8000 pic16_emitpcode(POC_INCF, op);
8002 /* signed bitfields result in either 0 or -1 */
8003 pic16_emitpcode(POC_DECF, op);
8006 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8009 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8015 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8016 // access symbol directly
8017 pic16_mov2w (AOP(left), 0);
8019 pic16_derefPtr (left, ptype, 0, NULL);
8022 /* if we have bitdisplacement then it fits */
8023 /* into this byte completely or if length is */
8024 /* less than a byte */
8025 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
8027 /* shift right acc */
8030 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8031 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8033 /* VR -- normally I would use the following, but since we use the hack,
8034 * to avoid the masking from AccRsh, why not mask it right now? */
8037 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8040 /* extend signed bitfields to 8 bits */
8041 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8043 assert (blen + bstr > 0);
8044 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8045 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8048 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8050 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8054 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8055 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8062 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8064 int size, offset = 0, leoffset=0 ;
8066 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8067 pic16_aopOp(result, ic, TRUE);
8071 size = AOP_SIZE(result);
8072 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8076 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8077 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8078 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8083 if(AOP(left)->aopu.pcop->type == PO_DIR)
8084 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8086 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8089 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8091 // pic16_DumpOp("(result)",result);
8092 if(pic16_isLitAop(AOP(result))) {
8093 pic16_mov2w(AOP(left), offset); // patch 8
8094 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8096 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8097 pic16_popGet(AOP(left), offset), //patch 8
8098 pic16_popGet(AOP(result), offset)));
8106 pic16_freeAsmop(result,NULL,ic,TRUE);
8111 /*-----------------------------------------------------------------*/
8112 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8113 /*-----------------------------------------------------------------*/
8114 static void genNearPointerGet (operand *left,
8118 // asmop *aop = NULL;
8119 //regs *preg = NULL ;
8120 sym_link *rtype, *retype;
8121 sym_link *ltype, *letype;
8125 rtype = operandType(result);
8126 retype= getSpec(rtype);
8127 ltype = operandType(left);
8128 letype= getSpec(ltype);
8130 pic16_aopOp(left,ic,FALSE);
8132 // pic16_DumpOp("(left)",left);
8133 // pic16_DumpOp("(result)",result);
8135 /* if left is rematerialisable and
8136 * result is not bit variable type and
8137 * the left is pointer to data space i.e
8138 * lower 128 bytes of space */
8140 if (AOP_TYPE(left) == AOP_PCODE
8141 && !IS_BITFIELD(retype)
8142 && DCL_TYPE(ltype) == POINTER) {
8144 genDataPointerGet (left,result,ic);
8145 pic16_freeAsmop(left, NULL, ic, TRUE);
8149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8150 pic16_aopOp (result,ic,TRUE);
8152 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8155 if(IS_BITFIELD( retype )
8156 && (SPEC_BLEN(operandType(result))==1)
8160 int bitstrt, bytestrt;
8162 /* if this is bitfield of size 1, see if we are checking the value
8163 * of a single bit in an if-statement,
8164 * if yes, then don't generate usual code, but execute the
8165 * genIfx directly -- VR */
8169 /* CHECK: if next iCode is IFX
8170 * and current result operand is nextic's conditional operand
8171 * and current result operand live ranges ends at nextic's key number
8173 if((nextic->op == IFX)
8174 && (result == IC_COND(nextic))
8175 && (OP_LIVETO(result) == nextic->seq)
8176 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
8178 /* everything is ok then */
8179 /* find a way to optimize the genIfx iCode */
8181 bytestrt = SPEC_BSTR(operandType(result))/8;
8182 bitstrt = SPEC_BSTR(operandType(result))%8;
8184 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8186 genIfxpCOpJump(nextic, jop);
8188 pic16_freeAsmop(left, NULL, ic, TRUE);
8189 pic16_freeAsmop(result, NULL, ic, TRUE);
8195 /* if bitfield then unpack the bits */
8196 if (IS_BITFIELD(letype))
8197 genUnpackBits (result, left, NULL, POINTER);
8199 /* we have can just get the values */
8200 int size = AOP_SIZE(result);
8203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8205 pic16_loadFSR0( left, 0 );
8209 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8210 pic16_popGet(AOP(result), offset++)));
8212 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8213 pic16_popGet(AOP(result), offset++)));
8219 /* now some housekeeping stuff */
8221 /* we had to allocate for this iCode */
8222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8223 pic16_freeAsmop(NULL,aop,ic,TRUE);
8225 /* we did not allocate which means left
8226 * already in a pointer register, then
8227 * if size > 0 && this could be used again
8228 * we have to point it back to where it
8230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8231 if (AOP_SIZE(result) > 1
8232 && !OP_SYMBOL(left)->remat
8233 && ( OP_SYMBOL(left)->liveTo > ic->seq
8235 // int size = AOP_SIZE(result) - 1;
8237 // pic16_emitcode("dec","%s",rname);
8243 pic16_freeAsmop(left,NULL,ic,TRUE);
8244 pic16_freeAsmop(result,NULL,ic,TRUE);
8247 /*-----------------------------------------------------------------*/
8248 /* genGenPointerGet - gget value from generic pointer space */
8249 /*-----------------------------------------------------------------*/
8250 static void genGenPointerGet (operand *left,
8251 operand *result, iCode *ic)
8254 sym_link *letype = getSpec(operandType(left));
8256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8257 pic16_aopOp(left,ic,FALSE);
8258 pic16_aopOp(result,ic,TRUE);
8259 size = AOP_SIZE(result);
8261 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8263 /* if bit then unpack */
8264 if (IS_BITFIELD(letype)) {
8265 genUnpackBits(result,left,"BAD",GPOINTER);
8269 /* set up WREG:PRODL:FSR0L with address from left */
8270 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8271 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8272 pic16_mov2w(AOP(left), 2);
8273 pic16_callGenericPointerRW(0, size);
8275 assignResultValue(result, size, 1);
8278 pic16_freeAsmop(left,NULL,ic,TRUE);
8279 pic16_freeAsmop(result,NULL,ic,TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* genConstPointerGet - get value from const generic pointer space */
8284 /*-----------------------------------------------------------------*/
8285 static void genConstPointerGet (operand *left,
8286 operand *result, iCode *ic)
8288 //sym_link *retype = getSpec(operandType(result));
8289 // symbol *albl = newiTempLabel(NULL); // patch 15
8290 // symbol *blbl = newiTempLabel(NULL); //
8291 // PIC_OPCODE poc; // patch 15
8295 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8296 pic16_aopOp(left,ic,FALSE);
8297 pic16_aopOp(result,ic,TRUE);
8298 size = AOP_SIZE(result);
8300 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8302 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8304 // set up table pointer
8305 if( (AOP_TYPE(left) == AOP_PCODE)
8306 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8307 || (AOP(left)->aopu.pcop->type == PO_DIR)))
8309 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8310 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8311 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8312 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8313 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8314 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8316 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8317 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8318 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8322 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8323 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8327 pic16_freeAsmop(left,NULL,ic,TRUE);
8328 pic16_freeAsmop(result,NULL,ic,TRUE);
8332 /*-----------------------------------------------------------------*/
8333 /* genPointerGet - generate code for pointer get */
8334 /*-----------------------------------------------------------------*/
8335 static void genPointerGet (iCode *ic)
8337 operand *left, *result ;
8338 sym_link *type, *etype;
8344 result = IC_RESULT(ic) ;
8346 /* depending on the type of pointer we need to
8347 move it to the correct pointer register */
8348 type = operandType(left);
8349 etype = getSpec(type);
8352 if (IS_PTR_CONST(type))
8354 if (IS_CODEPTR(type))
8356 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8358 /* if left is of type of pointer then it is simple */
8359 if (IS_PTR(type) && !IS_FUNC(type->next))
8360 p_type = DCL_TYPE(type);
8362 /* we have to go by the storage class */
8363 p_type = PTR_TYPE(SPEC_OCLS(etype));
8365 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8367 if (SPEC_OCLS(etype)->codesp ) {
8368 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8369 //p_type = CPOINTER ;
8371 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8372 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8373 /*p_type = FPOINTER ;*/
8375 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8376 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8377 /* p_type = PPOINTER; */
8379 if (SPEC_OCLS(etype) == idata ) {
8380 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8381 /* p_type = IPOINTER; */
8383 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8384 /* p_type = POINTER ; */
8388 /* now that we have the pointer type we assign
8389 the pointer values */
8394 genNearPointerGet (left,result,ic);
8398 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8400 genPagedPointerGet(left,result,ic);
8404 genFarPointerGet (left,result,ic);
8409 genConstPointerGet (left,result,ic);
8410 //pic16_emitcodePointerGet (left,result,ic);
8415 if (IS_PTR_CONST(type))
8416 genConstPointerGet (left,result,ic);
8419 genGenPointerGet (left,result,ic);
8423 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8424 "genPointerGet: illegal pointer type");
8429 /*-----------------------------------------------------------------*/
8430 /* genPackBits - generates code for packed bit storage */
8431 /*-----------------------------------------------------------------*/
8432 static void genPackBits (sym_link *etype , operand *result,
8434 char *rname, int p_type)
8440 int shifted_and_masked = 0;
8441 unsigned long lit = (unsigned long)-1;
8444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8445 blen = SPEC_BLEN(etype);
8446 bstr = SPEC_BSTR(etype);
8448 retype = getSpec(operandType(right));
8450 if(AOP_TYPE(right) == AOP_LIT) {
8451 lit = ulFromVal (AOP(right)->aopu.aop_lit);
8453 if((blen == 1) && (bstr < 8)) {
8454 /* it is a single bit, so use the appropriate bit instructions */
8456 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8458 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8459 /* workaround to reduce the extra lfsr instruction */
8461 pic16_emitpcode(POC_BSF,
8462 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8464 pic16_emitpcode(POC_BCF,
8465 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8468 if (PIC_IS_DATA_PTR(operandType(result))) {
8469 pic16_loadFSR0(result, 0);
8470 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8471 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8474 pic16_derefPtr (result, p_type, 0, NULL);
8475 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8476 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8477 /* write back new value */
8478 pic16_derefPtr (result, p_type, 1, NULL);
8484 /* IORLW below is more efficient */
8485 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8486 lit = (lit & ((1UL << blen) - 1)) << bstr;
8487 shifted_and_masked = 1;
8490 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8491 && IS_BITFIELD(retype)
8492 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8496 rblen = SPEC_BLEN( retype );
8497 rbstr = SPEC_BSTR( retype );
8499 if(IS_BITFIELD(etype)) {
8500 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8501 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8503 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8506 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8508 if(IS_BITFIELD(etype)) {
8509 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8511 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8514 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8518 /* move right to W */
8519 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8522 /* if the bit length is less than or */
8523 /* it exactly fits a byte then */
8524 if((shCnt=SPEC_BSTR(etype))
8525 || SPEC_BLEN(etype) <= 8 ) {
8528 if (blen != 8 || (bstr % 8) != 0) {
8529 // we need to combine the value with the old value
8530 if(!shifted_and_masked)
8532 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8534 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8535 SPEC_BSTR(etype), SPEC_BLEN(etype));
8537 /* shift left acc, do NOT mask the result again */
8540 /* using PRODH as a temporary register here */
8541 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8544 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8545 || IS_DIRECT(result)) {
8546 /* access symbol directly */
8547 pic16_mov2w (AOP(result), 0);
8550 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8553 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8554 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8555 (unsigned char)(0xff >> (8-bstr))) ));
8556 if (!shifted_and_masked) {
8557 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8559 /* We have the shifted and masked (literal) right value in `lit' */
8561 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8563 } else { // if (blen == 8 && (bstr % 8) == 0)
8564 if (shifted_and_masked) {
8565 // move right (literal) to WREG (only case where right is not yet in WREG)
8566 pic16_mov2w(AOP(right), (bstr / 8));
8570 /* write new value back */
8571 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8572 || IS_DIRECT(result)) {
8573 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8575 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8584 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8585 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8590 pic16_loadFSR0(result, 0); // load FSR0 with address of result
8591 rLen = SPEC_BLEN(etype)-8;
8593 /* now generate for lengths greater than one byte */
8597 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8603 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8609 pic16_emitcode("movx","@dptr,a");
8614 DEBUGpic16_emitcode(";lcall","__gptrput");
8622 pic16_mov2w(AOP(right), offset++);
8625 /* last last was not complete */
8627 /* save the byte & read byte */
8630 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8631 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8636 pic16_emitcode ("mov","b,a");
8637 pic16_emitcode("movx","a,@dptr");
8641 pic16_emitcode ("push","b");
8642 pic16_emitcode ("push","acc");
8643 pic16_emitcode ("lcall","__gptrget");
8644 pic16_emitcode ("pop","b");
8650 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8651 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8652 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8653 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8654 // pic16_emitcode ("orl","a,b");
8657 // if (p_type == GPOINTER)
8658 // pic16_emitcode("pop","b");
8663 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8664 // pic16_emitcode("mov","@%s,a",rname);
8668 pic16_emitcode("movx","@dptr,a");
8672 DEBUGpic16_emitcode(";lcall","__gptrput");
8679 // pic16_freeAsmop(right, NULL, ic, TRUE);
8682 /*-----------------------------------------------------------------*/
8683 /* genDataPointerSet - remat pointer to data space */
8684 /*-----------------------------------------------------------------*/
8685 static void genDataPointerSet(operand *right,
8689 int size, offset = 0, resoffset=0 ;
8691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8692 pic16_aopOp(right,ic,FALSE);
8694 size = AOP_SIZE(right);
8696 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8699 if ( AOP_TYPE(result) == AOP_PCODE) {
8700 fprintf(stderr,"genDataPointerSet %s, %d\n",
8701 AOP(result)->aopu.pcop->name,
8702 (AOP(result)->aopu.pcop->type == PO_DIR)?
8703 PCOR(AOP(result)->aopu.pcop)->instance:
8704 PCOI(AOP(result)->aopu.pcop)->offset);
8708 if(AOP(result)->aopu.pcop->type == PO_DIR)
8709 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8712 if (AOP_TYPE(right) == AOP_LIT) {
8713 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8714 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8716 pic16_mov2w(AOP(right), offset);
8717 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8723 pic16_freeAsmop(right,NULL,ic,TRUE);
8728 /*-----------------------------------------------------------------*/
8729 /* genNearPointerSet - pic16_emitcode for near pointer put */
8730 /*-----------------------------------------------------------------*/
8731 static void genNearPointerSet (operand *right,
8737 sym_link *ptype = operandType(result);
8740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8741 retype= getSpec(operandType(right));
8742 resetype = getSpec(operandType(result));
8744 pic16_aopOp(result,ic,FALSE);
8746 /* if the result is rematerializable &
8747 * in data space & not a bit variable */
8749 /* and result is not a bit variable */
8750 if (AOP_TYPE(result) == AOP_PCODE
8751 && DCL_TYPE(ptype) == POINTER
8752 && !IS_BITFIELD(retype)
8753 && !IS_BITFIELD(resetype)) {
8755 genDataPointerSet (right,result,ic);
8756 pic16_freeAsmop(result,NULL,ic,TRUE);
8760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8761 pic16_aopOp(right,ic,FALSE);
8762 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8764 /* if bitfield then unpack the bits */
8765 if (IS_BITFIELD(resetype)) {
8766 genPackBits (resetype, result, right, NULL, POINTER);
8768 /* we have can just get the values */
8769 int size = AOP_SIZE(right);
8772 pic16_loadFSR0(result, 0);
8774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8776 if (pic16_isLitOp(right)) {
8777 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8779 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8781 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8783 } else { // no literal
8785 pic16_emitpcode(POC_MOVFF,
8786 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8787 pic16_popCopyReg(&pic16_pc_postinc0)));
8789 pic16_emitpcode(POC_MOVFF,
8790 pic16_popGet2p(pic16_popGet(AOP(right),offset),
8791 pic16_popCopyReg(&pic16_pc_indf0)));
8799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8800 /* now some housekeeping stuff */
8802 /* we had to allocate for this iCode */
8803 pic16_freeAsmop(NULL,aop,ic,TRUE);
8805 /* we did not allocate which means left
8806 * already in a pointer register, then
8807 * if size > 0 && this could be used again
8808 * we have to point it back to where it
8810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8811 if (AOP_SIZE(right) > 1
8812 && !OP_SYMBOL(result)->remat
8813 && ( OP_SYMBOL(result)->liveTo > ic->seq
8816 int size = AOP_SIZE(right) - 1;
8819 pic16_emitcode("decf","fsr0,f");
8820 //pic16_emitcode("dec","%s",rname);
8824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8827 pic16_freeAsmop(right,NULL,ic,TRUE);
8828 pic16_freeAsmop(result,NULL,ic,TRUE);
8831 /*-----------------------------------------------------------------*/
8832 /* genGenPointerSet - set value from generic pointer space */
8833 /*-----------------------------------------------------------------*/
8834 static void genGenPointerSet (operand *right,
8835 operand *result, iCode *ic)
8838 sym_link *retype = getSpec(operandType(result));
8840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8842 pic16_aopOp(result,ic,FALSE);
8843 pic16_aopOp(right,ic,FALSE);
8844 size = AOP_SIZE(right);
8846 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8849 /* if bit then unpack */
8850 if (IS_BITFIELD(retype)) {
8851 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8852 genPackBits(retype,result,right,"dptr",GPOINTER);
8856 size = AOP_SIZE(right);
8858 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
8861 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8863 /* value of right+0 is placed on stack, which will be retrieved
8864 * by the support function thus restoring the stack. The important
8865 * thing is that there is no need to manually restore stack pointer
8867 pushaop(AOP(right), 0);
8868 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8869 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8870 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8871 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8873 /* load address to write to in WREG:FSR0H:FSR0L */
8874 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8875 pic16_popCopyReg(&pic16_pc_fsr0l)));
8876 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8877 pic16_popCopyReg(&pic16_pc_prodl)));
8878 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8880 pic16_callGenericPointerRW(1, size);
8883 pic16_freeAsmop(right,NULL,ic,TRUE);
8884 pic16_freeAsmop(result,NULL,ic,TRUE);
8887 /*-----------------------------------------------------------------*/
8888 /* genPointerSet - stores the value into a pointer location */
8889 /*-----------------------------------------------------------------*/
8890 static void genPointerSet (iCode *ic)
8892 operand *right, *result ;
8893 sym_link *type, *etype;
8898 right = IC_RIGHT(ic);
8899 result = IC_RESULT(ic) ;
8901 /* depending on the type of pointer we need to
8902 move it to the correct pointer register */
8903 type = operandType(result);
8904 etype = getSpec(type);
8906 /* if left is of type of pointer then it is simple */
8907 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8908 p_type = DCL_TYPE(type);
8911 /* we have to go by the storage class */
8912 p_type = PTR_TYPE(SPEC_OCLS(etype));
8914 /* if (SPEC_OCLS(etype)->codesp ) { */
8915 /* p_type = CPOINTER ; */
8918 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8919 /* p_type = FPOINTER ; */
8921 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8922 /* p_type = PPOINTER ; */
8924 /* if (SPEC_OCLS(etype) == idata ) */
8925 /* p_type = IPOINTER ; */
8927 /* p_type = POINTER ; */
8930 /* now that we have the pointer type we assign
8931 the pointer values */
8936 genNearPointerSet (right,result,ic);
8940 /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8942 genPagedPointerSet (right,result,ic);
8946 genFarPointerSet (right,result,ic);
8951 genGenPointerSet (right,result,ic);
8955 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8956 "genPointerSet: illegal pointer type");
8960 /*-----------------------------------------------------------------*/
8961 /* genIfx - generate code for Ifx statement */
8962 /*-----------------------------------------------------------------*/
8963 static void genIfx (iCode *ic, iCode *popIc)
8965 operand *cond = IC_COND(ic);
8970 pic16_aopOp(cond,ic,FALSE);
8972 /* get the value into acc */
8973 if (AOP_TYPE(cond) != AOP_CRY)
8974 pic16_toBoolean(cond);
8977 /* the result is now in the accumulator */
8978 pic16_freeAsmop(cond,NULL,ic,TRUE);
8980 /* if there was something to be popped then do it */
8984 /* if the condition is a bit variable */
8985 if (isbit && IS_ITEMP(cond) &&
8988 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8990 if (isbit && !IS_ITEMP(cond))
8991 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8998 /*-----------------------------------------------------------------*/
8999 /* genAddrOf - generates code for address of */
9000 /*-----------------------------------------------------------------*/
9001 static void genAddrOf (iCode *ic)
9003 operand *result, *left;
9005 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
9006 pCodeOp *pcop0, *pcop1, *pcop2;
9010 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9012 sym = OP_SYMBOL( IC_LEFT(ic) );
9015 /* get address of symbol on stack */
9016 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9018 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9019 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9022 // operands on stack are accessible via "FSR2 + index" with index
9023 // starting at 2 for arguments and growing from 0 downwards for
9024 // local variables (index == 0 is not assigned so we add one here)
9026 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9033 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9034 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9035 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9036 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9037 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9038 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9039 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9045 // if(pic16_debug_verbose) {
9046 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9047 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9050 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9051 size = AOP_SIZE(IC_RESULT(ic));
9053 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9054 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9055 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9058 pic16_emitpcode(POC_MOVLW, pcop0);
9059 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9060 pic16_emitpcode(POC_MOVLW, pcop1);
9061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9062 pic16_emitpcode(POC_MOVLW, pcop2);
9063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9066 pic16_emitpcode(POC_MOVLW, pcop0);
9067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9068 pic16_emitpcode(POC_MOVLW, pcop1);
9069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9071 pic16_emitpcode(POC_MOVLW, pcop0);
9072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9075 pic16_freeAsmop(left, NULL, ic, FALSE);
9077 pic16_freeAsmop(result,NULL,ic,TRUE);
9081 /*-----------------------------------------------------------------*/
9082 /* genAssign - generate code for assignment */
9083 /*-----------------------------------------------------------------*/
9084 static void genAssign (iCode *ic)
9086 operand *result, *right;
9087 sym_link *restype, *rtype;
9088 int size, offset,know_W;
9089 unsigned long lit = 0L;
9091 result = IC_RESULT(ic);
9092 right = IC_RIGHT(ic) ;
9096 /* if they are the same */
9097 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9100 /* reversed order operands are aopOp'ed so that result operand
9101 * is effective in case right is a stack symbol. This maneauver
9102 * allows to use the _G.resDirect flag later */
9103 pic16_aopOp(result,ic,TRUE);
9104 pic16_aopOp(right,ic,FALSE);
9106 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9108 /* if they are the same registers */
9109 if (pic16_sameRegs(AOP(right),AOP(result)))
9112 /* if the result is a bit */
9113 if (AOP_TYPE(result) == AOP_CRY) {
9114 /* if the right size is a literal then
9115 we know what the value is */
9116 if (AOP_TYPE(right) == AOP_LIT) {
9118 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9119 pic16_popGet(AOP(result),0));
9121 if (((int) operandLitValue(right)))
9122 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9123 AOP(result)->aopu.aop_dir,
9124 AOP(result)->aopu.aop_dir);
9126 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9127 AOP(result)->aopu.aop_dir,
9128 AOP(result)->aopu.aop_dir);
9133 /* the right is also a bit variable */
9134 if (AOP_TYPE(right) == AOP_CRY) {
9135 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9136 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9137 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9143 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9144 pic16_toBoolean(right);
9146 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9147 //pic16_aopPut(AOP(result),"a",0);
9151 /* bit variables done */
9153 size = AOP_SIZE(result);
9156 /* bit variables done */
9158 size = AOP_SIZE(result);
9159 restype = operandType(result);
9160 rtype = operandType(right);
9163 if(AOP_TYPE(right) == AOP_LIT) {
9164 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9166 lit = ulFromVal (AOP(right)->aopu.aop_lit);
9168 /* patch tag for literals that are cast to pointers */
9169 if (IS_CODEPTR(restype)) {
9170 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9171 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9173 if (IS_GENPTR(restype))
9175 if (IS_CODEPTR(rtype)) {
9176 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9177 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9178 } else if (PIC_IS_DATA_PTR(rtype)) {
9179 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9180 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9181 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9182 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9183 } else if (IS_PTR(rtype)) {
9184 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9185 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9191 unsigned long lit_int;
9196 if(IS_FIXED16X16(operandType(right))) {
9197 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9199 /* take care if literal is a float */
9200 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9206 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9207 // sizeof(unsigned long int), sizeof(float));
9210 if (AOP_TYPE(right) == AOP_REG) {
9211 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9213 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9218 /* when do we have to read the program memory?
9219 * - if right itself is a symbol in code space
9220 * (we don't care what it points to if it's a pointer)
9221 * - AND right is not a function (we would want its address)
9223 if(AOP_TYPE(right) != AOP_LIT
9224 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9225 && !IS_FUNC(OP_SYM_TYPE(right))
9226 && !IS_ITEMP(right)) {
9228 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9229 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9231 // set up table pointer
9232 if(pic16_isLitOp(right)) {
9233 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9234 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9235 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9236 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9237 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9238 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9239 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9241 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9242 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9243 pic16_popCopyReg(&pic16_pc_tblptrl)));
9244 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9245 pic16_popCopyReg(&pic16_pc_tblptrh)));
9246 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9247 pic16_popCopyReg(&pic16_pc_tblptru)));
9250 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9251 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9253 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9255 pic16_popGet(AOP(result),offset)));
9259 /* FIXME: for pointers we need to extend differently (according
9260 * to pointer type DATA/CODE/EEPROM/... :*/
9261 size = getSize(OP_SYM_TYPE(right));
9262 if(AOP_SIZE(result) > size) {
9263 size = AOP_SIZE(result) - size;
9265 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9273 /* VR - What is this?! */
9274 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9277 if(aopIdx(AOP(result),0) == 4) {
9278 /* this is a workaround to save value of right into wreg too,
9279 * value of wreg is going to be used later */
9280 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9281 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9282 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9286 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9290 size = AOP_SIZE(right);
9291 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9294 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
9295 if(AOP_TYPE(right) == AOP_LIT) {
9297 if(know_W != (lit&0xff))
9298 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9300 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9302 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9306 } else if (AOP_TYPE(right) == AOP_CRY) {
9307 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9309 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9310 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9311 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9313 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9314 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9315 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9319 if(!_G.resDirect) { /* use this aopForSym feature */
9320 if(AOP_TYPE(result) == AOP_ACC) {
9321 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9323 if(AOP_TYPE(right) == AOP_ACC) {
9324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9326 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9333 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9336 pic16_freeAsmop (right,NULL,ic,FALSE);
9337 pic16_freeAsmop (result,NULL,ic,TRUE);
9340 /*-----------------------------------------------------------------*/
9341 /* genJumpTab - generates code for jump table */
9342 /*-----------------------------------------------------------------*/
9343 static void genJumpTab (iCode *ic)
9348 pCodeOp *jt_offs_hi;
9353 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9354 /* get the condition into accumulator */
9355 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9357 /* multiply by three */
9358 pic16_emitcode("add","a,acc");
9359 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9361 jtab = newiTempLabel(NULL);
9362 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9363 pic16_emitcode("jmp","@a+dptr");
9364 pic16_emitcode("","%05d_DS_:",jtab->key+100);
9367 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9368 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9370 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9371 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9372 pic16_emitpLabel(jtab->key);
9376 jt_offs = pic16_popGetTempReg(0);
9377 jt_offs_hi = pic16_popGetTempReg(1);
9378 jt_label = pic16_popGetLabel (jtab->key);
9379 //fprintf (stderr, "Creating jump table...\n");
9381 // calculate offset into jump table (idx * sizeof (GOTO))
9382 pic16_emitpcode(POC_CLRF , jt_offs_hi);
9383 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9384 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9385 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9386 pic16_emitpcode(POC_RLCF , jt_offs_hi);
9387 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9388 pic16_emitpcode(POC_MOVWF , jt_offs);
9390 // prepare PCLATx (set to first entry in jump table)
9391 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9392 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9393 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9394 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9395 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9397 // set PCLATx to selected entry (new PCL is stored in jt_offs)
9398 pic16_emitpcode(POC_ADDWF , jt_offs);
9399 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9400 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9402 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
9404 // release temporaries and prepare jump into table (new PCL --> WREG)
9405 pic16_emitpcode(POC_MOVFW , jt_offs);
9406 pic16_popReleaseTempReg (jt_offs_hi, 1);
9407 pic16_popReleaseTempReg (jt_offs, 0);
9409 // jump into the table
9410 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9412 pic16_emitpLabelFORCE(jtab->key);
9415 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9416 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9418 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9419 /* now generate the jump labels */
9420 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9421 jtab = setNextItem(IC_JTLABELS(ic))) {
9422 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9423 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9426 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9430 /*-----------------------------------------------------------------*/
9431 /* genMixedOperation - gen code for operators between mixed types */
9432 /*-----------------------------------------------------------------*/
9434 TSD - Written for the PIC port - but this unfortunately is buggy.
9435 This routine is good in that it is able to efficiently promote
9436 types to different (larger) sizes. Unfortunately, the temporary
9437 variables that are optimized out by this routine are sometimes
9438 used in other places. So until I know how to really parse the
9439 iCode tree, I'm going to not be using this routine :(.
9441 static int genMixedOperation (iCode *ic)
9444 operand *result = IC_RESULT(ic);
9445 sym_link *ctype = operandType(IC_LEFT(ic));
9446 operand *right = IC_RIGHT(ic);
9452 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9454 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9460 nextright = IC_RIGHT(nextic);
9461 nextleft = IC_LEFT(nextic);
9462 nextresult = IC_RESULT(nextic);
9464 pic16_aopOp(right,ic,FALSE);
9465 pic16_aopOp(result,ic,FALSE);
9466 pic16_aopOp(nextright, nextic, FALSE);
9467 pic16_aopOp(nextleft, nextic, FALSE);
9468 pic16_aopOp(nextresult, nextic, FALSE);
9470 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9476 pic16_emitcode(";remove right +","");
9478 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9484 pic16_emitcode(";remove left +","");
9488 big = AOP_SIZE(nextleft);
9489 small = AOP_SIZE(nextright);
9491 switch(nextic->op) {
9494 pic16_emitcode(";optimize a +","");
9495 /* if unsigned or not an integral type */
9496 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9497 pic16_emitcode(";add a bit to something","");
9500 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9502 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9503 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9504 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9506 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9514 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9515 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9516 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9519 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9521 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9522 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9523 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9524 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9525 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9528 pic16_emitcode("rlf","known_zero,w");
9535 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9536 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9537 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9539 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9549 pic16_freeAsmop(right,NULL,ic,TRUE);
9550 pic16_freeAsmop(result,NULL,ic,TRUE);
9551 pic16_freeAsmop(nextright,NULL,ic,TRUE);
9552 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9554 nextic->generated = 1;
9561 /*-----------------------------------------------------------------*/
9562 /* genCast - gen code for casting */
9563 /*-----------------------------------------------------------------*/
9564 static void genCast (iCode *ic)
9566 operand *result = IC_RESULT(ic);
9567 sym_link *ctype = operandType(IC_LEFT(ic));
9568 sym_link *rtype = operandType(IC_RIGHT(ic));
9569 sym_link *restype = operandType(IC_RESULT(ic));
9570 operand *right = IC_RIGHT(ic);
9576 /* if they are equivalent then do nothing */
9577 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9580 pic16_aopOp(result,ic,FALSE);
9581 pic16_aopOp(right,ic,FALSE) ;
9583 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9586 /* if the result is a bit */
9587 if (AOP_TYPE(result) == AOP_CRY) {
9589 /* if the right size is a literal then
9590 * we know what the value is */
9591 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9593 if (AOP_TYPE(right) == AOP_LIT) {
9594 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9595 pic16_popGet(AOP(result),0));
9597 if (((int) operandLitValue(right)))
9598 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9599 AOP(result)->aopu.aop_dir,
9600 AOP(result)->aopu.aop_dir);
9602 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9603 AOP(result)->aopu.aop_dir,
9604 AOP(result)->aopu.aop_dir);
9608 /* the right is also a bit variable */
9609 if (AOP_TYPE(right) == AOP_CRY) {
9611 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9613 pic16_emitcode("clrc","");
9614 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9615 AOP(right)->aopu.aop_dir,
9616 AOP(right)->aopu.aop_dir);
9617 pic16_aopPut(AOP(result),"c",0);
9622 if (AOP_TYPE(right) == AOP_REG) {
9623 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
9624 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9625 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
9627 pic16_toBoolean(right);
9628 pic16_aopPut(AOP(result),"a",0);
9632 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9635 size = AOP_SIZE(result);
9637 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9639 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9640 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9641 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9644 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9649 if(IS_BITFIELD(getSpec(restype))
9650 && IS_BITFIELD(getSpec(rtype))) {
9651 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9654 /* port from pic14 to cope with generic pointers */
9655 if (PIC_IS_TAGGED(restype))
9657 operand *result = IC_RESULT(ic);
9658 //operand *left = IC_LEFT(ic);
9659 operand *right = IC_RIGHT(ic);
9662 /* copy common part */
9663 int max, size = AOP_SIZE(result);
9664 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9665 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9670 pic16_mov2w (AOP(right), size);
9671 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9674 /* upcast into generic pointer type? */
9675 if (IS_GENPTR(restype)
9676 && !PIC_IS_TAGGED(rtype)
9677 && (AOP_SIZE(result) > max))
9679 /* determine appropriate tag for right */
9680 if (PIC_IS_DATA_PTR(rtype))
9681 tag = GPTR_TAG_DATA;
9682 else if (IS_CODEPTR(rtype))
9683 tag = GPTR_TAG_CODE;
9684 else if (PIC_IS_DATA_PTR(ctype)) {
9685 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9686 tag = GPTR_TAG_DATA;
9687 } else if (IS_CODEPTR(ctype)) {
9688 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9689 tag = GPTR_TAG_CODE;
9690 } else if (IS_PTR(rtype)) {
9691 PERFORM_ONCE(weirdcast,
9692 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9694 tag = GPTR_TAG_DATA;
9696 PERFORM_ONCE(weirdcast,
9697 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9699 tag = GPTR_TAG_DATA;
9702 assert (AOP_SIZE(result) == 3);
9703 /* zero-extend address... */
9704 for (size = max; size < AOP_SIZE(result)-1; size++)
9705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9706 /* ...and add tag */
9707 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9708 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9709 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9710 for (size = max; size < AOP_SIZE(result)-1; size++)
9711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9712 /* add __code tag */
9713 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9714 } else if (AOP_SIZE(result) > max) {
9715 /* extend non-pointers */
9716 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9717 pic16_addSign(result, max, 0);
9722 /* if they are the same size : or less */
9723 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9725 /* if they are in the same place */
9726 if (pic16_sameRegs(AOP(right),AOP(result)))
9729 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9731 if (IS_PTR_CONST(rtype))
9733 if (IS_CODEPTR(rtype))
9735 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9738 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9740 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9742 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9744 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9745 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9746 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9748 if(AOP_SIZE(result) < 2) {
9749 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9751 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9755 /* if they in different places then copy */
9756 size = AOP_SIZE(result);
9759 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9767 /* if the result is of type pointer */
9768 if (IS_PTR(ctype)) {
9770 sym_link *type = operandType(right);
9771 sym_link *etype = getSpec(type);
9773 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
9775 /* pointer to generic pointer */
9776 if (IS_GENPTR(ctype)) {
9780 p_type = DCL_TYPE(type);
9782 /* we have to go by the storage class */
9783 p_type = PTR_TYPE(SPEC_OCLS(etype));
9785 /* if (SPEC_OCLS(etype)->codesp ) */
9786 /* p_type = CPOINTER ; */
9788 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9789 /* p_type = FPOINTER ; */
9791 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9792 /* p_type = PPOINTER; */
9794 /* if (SPEC_OCLS(etype) == idata ) */
9795 /* p_type = IPOINTER ; */
9797 /* p_type = POINTER ; */
9800 /* the first two bytes are known */
9801 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
9802 size = GPTRSIZE - 1;
9805 if(offset < AOP_SIZE(right)) {
9806 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9807 pic16_mov2f(AOP(result), AOP(right), offset);
9809 if ((AOP_TYPE(right) == AOP_PCODE) &&
9810 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9811 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9812 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9815 pic16_aopPut(AOP(result),
9816 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9821 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9824 /* the last byte depending on type */
9829 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9833 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9837 pic16_emitcode(";BUG!? ","%d",__LINE__);
9842 if (GPTRSIZE > AOP_SIZE(right)) {
9843 // assume __data pointer... THIS MIGHT BE WRONG!
9844 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9846 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9851 /* this should never happen */
9852 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9853 "got unknown pointer type");
9856 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9862 /* just copy the pointers */
9863 size = AOP_SIZE(result);
9866 pic16_aopPut(AOP(result),
9867 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9876 /* so we now know that the size of destination is greater
9877 than the size of the source.
9878 Now, if the next iCode is an operator then we might be
9879 able to optimize the operation without performing a cast.
9881 if(genMixedOperation(ic))
9884 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9886 /* we move to result for the size of source */
9887 size = AOP_SIZE(right);
9892 pic16_mov2f(AOP(result), AOP(right), offset);
9896 /* now depending on the sign of the destination */
9897 size = AOP_SIZE(result) - AOP_SIZE(right);
9898 /* if unsigned or not an integral type */
9899 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9901 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
9903 /* we need to extend the sign :( */
9906 /* Save one instruction of casting char to int */
9907 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9908 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9909 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
9911 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9914 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9916 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9918 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9921 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
9926 pic16_freeAsmop(right,NULL,ic,TRUE);
9927 pic16_freeAsmop(result,NULL,ic,TRUE);
9931 /*-----------------------------------------------------------------*/
9932 /* genDjnz - generate decrement & jump if not zero instrucion */
9933 /*-----------------------------------------------------------------*/
9934 static int genDjnz (iCode *ic, iCode *ifx)
9937 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9942 /* if the if condition has a false label
9943 then we cannot save */
9947 /* if the minus is not of the form
9949 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9950 !IS_OP_LITERAL(IC_RIGHT(ic)))
9953 if (operandLitValue(IC_RIGHT(ic)) != 1)
9956 /* if the size of this greater than one then no
9958 if (getSize(operandType(IC_RESULT(ic))) > 1)
9961 /* otherwise we can save BIG */
9962 lbl = newiTempLabel(NULL);
9963 lbl1= newiTempLabel(NULL);
9965 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9967 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9968 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9970 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9975 /*-----------------------------------------------------------------*/
9976 /* genReceive - generate code for a receive iCode */
9977 /*-----------------------------------------------------------------*/
9978 static void genReceive (iCode *ic)
9984 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
9985 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
9987 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
9989 if (isOperandInFarSpace(IC_RESULT(ic))
9990 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
9991 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9993 int size = getSize(operandType(IC_RESULT(ic)));
9994 int offset = pic16_fReturnSizePic - size;
9998 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9999 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10003 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10005 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10006 size = AOP_SIZE(IC_RESULT(ic));
10009 pic16_emitcode ("pop","acc");
10010 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10013 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10015 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10018 /* set pseudo stack pointer to where it should be - dw*/
10019 GpsuedoStkPtr = ic->parmBytes;
10021 /* setting GpsuedoStkPtr has side effects here: */
10022 /* FIXME: What's the correct size of the return(ed) value?
10023 * For now, assuming '4' as before... */
10024 assignResultValue(IC_RESULT(ic), 4, 0);
10027 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10030 /*-----------------------------------------------------------------*/
10031 /* genDummyRead - generate code for dummy read of volatiles */
10032 /*-----------------------------------------------------------------*/
10034 genDummyRead (iCode * ic)
10039 if (op && IS_SYMOP(op)) {
10040 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10041 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10044 pic16_aopOp (op, ic, FALSE);
10045 pic16_mov2w_volatile(AOP(op));
10046 pic16_freeAsmop (op, NULL, ic, TRUE);
10048 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10052 /*-----------------------------------------------------------------*/
10053 /* genpic16Code - generate code for pic16 based controllers */
10054 /*-----------------------------------------------------------------*/
10056 * At this point, ralloc.c has gone through the iCode and attempted
10057 * to optimize in a way suitable for a PIC. Now we've got to generate
10058 * PIC instructions that correspond to the iCode.
10060 * Once the instructions are generated, we'll pass through both the
10061 * peep hole optimizer and the pCode optimizer.
10062 *-----------------------------------------------------------------*/
10064 void genpic16Code (iCode *lic)
10069 lineHead = lineCurr = NULL;
10071 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10072 pic16_addpBlock(pb);
10075 /* if debug information required */
10076 if (options.debug && currFunc) {
10078 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10083 for (ic = lic ; ic ; ic = ic->next ) {
10085 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10086 if ( cln != ic->lineno ) {
10087 if ( options.debug ) {
10088 debugFile->writeCLine (ic);
10091 if(!options.noCcodeInAsm) {
10092 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10093 printCLine(ic->filename, ic->lineno)));
10099 if(options.iCodeInAsm) {
10102 /* insert here code to print iCode as comment */
10103 iLine = printILine(ic);
10104 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10108 /* if the result is marked as
10109 * spilt and rematerializable or code for
10110 * this has already been generated then
10112 if (resultRemat(ic) || ic->generated )
10115 /* depending on the operation */
10134 /* IPOP happens only when trying to restore a
10135 * spilt live range, if there is an ifx statement
10136 * following this pop then the if statement might
10137 * be using some of the registers being popped which
10138 * would destroy the contents of the register so
10139 * we need to check for this condition and handle it */
10141 && ic->next->op == IFX
10142 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10143 genIfx (ic->next,ic);
10161 genEndFunction (ic);
10177 pic16_genPlus (ic) ;
10181 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10182 pic16_genMinus (ic);
10198 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10202 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10208 /* note these two are xlated by algebraic equivalence
10209 * during parsing SDCC.y */
10210 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10211 "got '>=' or '<=' shouldn't have come here");
10215 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10227 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10231 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10235 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10259 genRightShift (ic);
10262 case GET_VALUE_AT_ADDRESS:
10267 if (POINTER_SET(ic))
10294 addSet(&_G.sendSet,ic);
10297 case DUMMY_READ_VOLATILE:
10307 /* now we are ready to call the
10308 peep hole optimizer */
10309 if (!options.nopeep)
10310 peepHole (&lineHead);
10312 /* now do the actual printing */
10313 printLine (lineHead, codeOutBuf);
10316 DFPRINTF((stderr,"printing pBlock\n\n"));
10317 pic16_printpBlock(stdout,pb);