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)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
52 /* Set the following to 1 to enable the slower/bigger
53 * but more robust generic shifting routine (which also
54 * operates correctly with negative shift values). */
55 #define USE_GENERIC_SIGNED_SHIFT 1
57 /* Set the following to 1 to enable the new
58 * stripped down genCmp version.
59 * This version should be easier to understand,
60 * more reliable and (sigh) slighly slower. */
61 #define USE_SIMPLE_GENCMP 1
63 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
64 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
67 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
69 /* If you change these, you also have to update the library files
70 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
71 #define GPTR_TAG_DATA 0x80
72 #define GPTR_TAG_EEPROM 0x40
73 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
75 /* Wrapper to execute `code' at most once. */
76 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
78 void pic16_genMult8X8_n (operand *, operand *,operand *);
80 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
81 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 void pic16_genMult16X16_16(operand *, operand *, operand *);
83 void pic16_genMult32X32_32(operand *, operand *, operand *);
85 pCode *pic16_AssembleLine(char *line, int peeps);
86 extern void pic16_printpBlock(FILE *of, pBlock *pb);
87 static asmop *newAsmop (short type);
88 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
89 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
90 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
91 static pCodeOp *pic16_popRegFromIdx(int rIdx);
93 //static int aopIdx (asmop *aop, int offset);
95 int pic16_labelOffset=0;
96 extern int pic16_debug_verbose;
97 #if !(USE_GENERIC_SIGNED_SHIFT)
98 static int optimized_for_speed = 0;
107 /* max_key keeps track of the largest label number used in
108 a function. This is then used to adjust the label offset
109 for the next function.
111 static int max_key=0;
112 static int GpsuedoStkPtr=0;
114 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
116 const char *pic16_AopType(short type);
117 static iCode *ifxForOp ( operand *op, iCode *ic );
119 void pic16_pushpCodeOp(pCodeOp *pcop);
120 void pic16_poppCodeOp(pCodeOp *pcop);
122 static bool is_LitOp(operand *op);
123 static bool is_LitAOp(asmop *aop);
126 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
128 /* set the following macro to 1 to enable passing the
129 * first byte of functions parameters via WREG */
130 #define USE_WREG_IN_FUNC_PARAMS 0
133 /* this is the down and dirty file with all kinds of
134 kludgy & hacky stuff. This is what it is all about
135 CODE GENERATION for a specific MCU . some of the
136 routines may be reusable, will have to see */
138 static char *zero = "#0x00";
139 static char *one = "#0x01";
140 //static char *spname = "sp";
144 * Function return value policy (MSB-->LSB):
146 * 16 bits -> PRODL:WREG
147 * 24 bits -> PRODH:PRODL:WREG
148 * 32 bits -> FSR0L:PRODH:PRODL:WREG
149 * >32 bits -> on stack, and FSR0 points to the beginning
154 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
155 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
156 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
157 static char **fReturn = fReturnpic16;
159 static char *accUse[] = {"WREG"};
161 //static short rbank = -1;
175 bitVect *fregsUsed; /* registers used in function */
177 set *sregsAllocSet; /* registers used to store stack variables */
178 int stack_lat; /* stack offset latency */
180 int useWreg; /* flag when WREG is used to pass function parameter */
183 extern int pic16_ptrRegReq ;
184 extern int pic16_nRegs;
185 extern FILE *codeOutFile;
186 //static void saverbank (int, iCode *,bool);
188 static lineNode *lineHead = NULL;
189 static lineNode *lineCurr = NULL;
191 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
192 0xE0, 0xC0, 0x80, 0x00};
193 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
194 0x07, 0x03, 0x01, 0x00};
198 /*-----------------------------------------------------------------*/
199 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
200 /* exponent of 2 is returned, otherwise -1 is */
202 /* note that this is similar to the function `powof2' in SDCCsymt */
206 /*-----------------------------------------------------------------*/
207 int pic16_my_powof2 (unsigned long num)
210 if( (num & (num-1)) == 0) {
223 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
225 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
227 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
228 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
229 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
230 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
231 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
232 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
233 ((result) ? AOP_SIZE(result) : 0));
236 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
239 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
241 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
242 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
243 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
244 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
245 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
246 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
250 void pic16_emitpcomment (char *fmt, ...)
253 char lb[INITIAL_INLINEASM];
254 unsigned char *lbp = (unsigned char *)lb;
259 vsprintf(lb+1,fmt,ap);
261 while (isspace(*lbp)) lbp++;
264 lineCurr = (lineCurr ?
265 connectLine(lineCurr,newLineNode(lb)) :
266 (lineHead = newLineNode(lb)));
267 lineCurr->isInline = _G.inLine;
268 lineCurr->isDebug = _G.debugLine;
270 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
273 // fprintf(stderr, "%s\n", lb);
276 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
279 char lb[INITIAL_INLINEASM];
280 unsigned char *lbp = (unsigned char *)lb;
282 if(!pic16_debug_verbose)
289 sprintf(lb,"%s\t",inst);
291 sprintf(lb,"%s",inst);
292 vsprintf(lb+(strlen(lb)),fmt,ap);
296 while (isspace(*lbp)) lbp++;
299 lineCurr = (lineCurr ?
300 connectLine(lineCurr,newLineNode(lb)) :
301 (lineHead = newLineNode(lb)));
302 lineCurr->isInline = _G.inLine;
303 lineCurr->isDebug = _G.debugLine;
305 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
308 // fprintf(stderr, "%s\n", lb);
313 void pic16_emitpLabel(int key)
315 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
318 void pic16_emitpLabelFORCE(int key)
320 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
323 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
324 * NEVER call pic16_emitpcode_real directly, please... */
325 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
329 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
331 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
334 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
337 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
339 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
342 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
345 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
351 #define pic16_emitcode DEBUGpic16_emitcode
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitcode - writes the code into a file : for now it is simple */
355 /*-----------------------------------------------------------------*/
356 void pic16_emitcode (char *inst,char *fmt, ...)
359 char lb[INITIAL_INLINEASM];
360 unsigned char *lbp = lb;
366 sprintf(lb,"%s\t",inst);
368 sprintf(lb,"%s",inst);
369 vsprintf(lb+(strlen(lb)),fmt,ap);
373 while (isspace(*lbp)) lbp++;
376 lineCurr = (lineCurr ?
377 connectLine(lineCurr,newLineNode(lb)) :
378 (lineHead = newLineNode(lb)));
379 lineCurr->isInline = _G.inLine;
380 lineCurr->isDebug = _G.debugLine;
382 // VR fprintf(stderr, "lb = <%s>\n", lbp);
384 // if(pic16_debug_verbose)
385 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
392 /*-----------------------------------------------------------------*/
393 /* pic16_emitDebuggerSymbol - associate the current code location */
394 /* with a debugger symbol */
395 /*-----------------------------------------------------------------*/
397 pic16_emitDebuggerSymbol (char * debugSym)
400 pic16_emitcode (";", "%s ==.", debugSym);
405 /*-----------------------------------------------------------------*/
406 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
407 /*-----------------------------------------------------------------*/
408 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
410 // bool r0iu = FALSE , r1iu = FALSE;
411 // bool r0ou = FALSE , r1ou = FALSE;
412 bool fsr0iu = FALSE, fsr0ou;
413 bool fsr2iu = FALSE, fsr2ou;
415 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
418 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
419 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
421 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
422 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
424 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
425 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
426 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
429 if(!fsr0iu && !fsr0ou) {
430 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
431 (*aopp)->type = AOP_FSR0;
433 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
435 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
439 /* no usage of FSR2 */
440 if(!fsr2iu && !fsr2ou) {
441 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
442 (*aopp)->type = AOP_FSR2;
444 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
448 /* now we know they both have usage */
449 /* if fsr0 not used in this instruction */
451 if (!_G.fsr0Pushed) {
452 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
453 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
457 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
458 (*aopp)->type = AOP_FSR0;
460 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
462 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
466 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
471 /* the logic: if r0 & r1 used in the instruction
472 then we are in trouble otherwise */
474 /* first check if r0 & r1 are used by this
475 instruction, in which case we are in trouble */
476 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
477 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
482 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
483 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
485 /* if no usage of r0 then return it */
486 if (!r0iu && !r0ou) {
487 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
488 (*aopp)->type = AOP_R0;
490 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
493 /* if no usage of r1 then return it */
494 if (!r1iu && !r1ou) {
495 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
496 (*aopp)->type = AOP_R1;
498 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
501 /* now we know they both have usage */
502 /* if r0 not used in this instruction */
504 /* push it if not already pushed */
506 //pic16_emitcode ("push","%s",
507 // pic16_regWithIdx(R0_IDX)->dname);
511 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
512 (*aopp)->type = AOP_R0;
514 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
517 /* if r1 not used then */
520 /* push it if not already pushed */
522 //pic16_emitcode ("push","%s",
523 // pic16_regWithIdx(R1_IDX)->dname);
527 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
528 (*aopp)->type = AOP_R1;
529 return pic16_regWithIdx(R1_IDX);
533 /* I said end of world but not quite end of world yet */
534 /* if this is a result then we can push it on the stack*/
536 (*aopp)->type = AOP_STK;
540 /* other wise this is true end of the world */
541 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
542 "getFreePtr should never reach here");
547 /*-----------------------------------------------------------------*/
548 /* newAsmop - creates a new asmOp */
549 /*-----------------------------------------------------------------*/
550 static asmop *newAsmop (short type)
554 aop = Safe_calloc(1,sizeof(asmop));
559 static void genSetDPTR(int n)
563 pic16_emitcode(";", "Select standard DPTR");
564 pic16_emitcode("mov", "dps, #0x00");
568 pic16_emitcode(";", "Select alternate DPTR");
569 pic16_emitcode("mov", "dps, #0x01");
573 /*-----------------------------------------------------------------*/
574 /* resolveIfx - converts an iCode ifx into a form more useful for */
575 /* generating code */
576 /*-----------------------------------------------------------------*/
577 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
581 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
587 resIfx->condition = 1; /* assume that the ifx is true */
588 resIfx->generated = 0; /* indicate that the ifx has not been used */
591 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
594 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
595 __FUNCTION__,__LINE__,resIfx->lbl->key);
600 resIfx->lbl = IC_TRUE(ifx);
602 resIfx->lbl = IC_FALSE(ifx);
603 resIfx->condition = 0;
608 DEBUGpic16_emitcode("; +++","ifx true is non-null");
610 DEBUGpic16_emitcode("; +++","ifx true is null");
612 DEBUGpic16_emitcode("; +++","ifx false is non-null");
614 DEBUGpic16_emitcode("; +++","ifx false is null");
618 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
622 /*-----------------------------------------------------------------*/
623 /* pointerCode - returns the code for a pointer type */
624 /*-----------------------------------------------------------------*/
625 static int pointerCode (sym_link *etype)
628 return PTR_TYPE(SPEC_OCLS(etype));
633 /*-----------------------------------------------------------------*/
634 /* aopForSym - for a true symbol */
635 /*-----------------------------------------------------------------*/
636 static asmop *aopForSym (iCode *ic, operand *op, bool result)
638 symbol *sym=OP_SYMBOL(op);
640 memmap *space= SPEC_OCLS(sym->etype);
644 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
646 // sym = OP_SYMBOL(op);
648 /* if already has one */
650 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
655 /* if symbol was initially placed onStack then we must re-place it
656 * to direct memory, since pic16 does not have a specific stack */
658 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
666 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
668 sym->aop = aop = newAsmop (AOP_PAGED);
669 aop->aopu.aop_dir = sym->rname ;
670 aop->size = getSize(sym->type);
671 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
672 pic16_allocDirReg( IC_LEFT(ic) );
680 /* assign depending on the storage class */
681 /* if it is on the stack or indirectly addressable */
682 /* space we need to assign either r0 or r1 to it */
683 if (sym->onStack) // || sym->iaccess)
688 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
689 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
691 /* acquire a temporary register -- it is saved in function */
693 sym->aop = aop = newAsmop(AOP_STA);
694 aop->aopu.stk.stk = sym->stack;
695 aop->size = getSize(sym->type);
698 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
699 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
700 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
701 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
703 for(i=0;i<aop->size;i++)
704 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
705 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
707 if(1 && ic->op == SEND) {
709 /* if SEND do the send here */
712 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
713 for(i=0;i<aop->size;i++) {
714 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
715 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
720 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
723 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
725 // we do not need to load the value if it is to be defined...
726 if (result) return aop;
729 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
732 for(i=0;i<aop->size;i++) {
734 /* initialise for stack access via frame pointer */
735 // operands on stack are accessible via "{FRAME POINTER} + index" with index
736 // starting at 2 for arguments and growing from 0 downwards for
737 // local variables (index == 0 is not assigned so we add one here)
739 int soffs = sym->stack;
745 if(1 && ic->op == SEND) {
746 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
747 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
748 pic16_popCopyReg( pic16_frame_plusw ),
749 pic16_popCopyReg(pic16_stack_postdec )));
751 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
752 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
753 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
759 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
766 /* now assign the address of the variable to
767 the pointer register */
768 if (aop->type != AOP_STK) {
772 pic16_emitcode("push","acc");
774 pic16_emitcode("mov","a,_bp");
775 pic16_emitcode("add","a,#0x%02x",
777 ((char)(sym->stack - _G.nRegsSaved )) :
778 ((char)sym->stack)) & 0xff);
779 pic16_emitcode("mov","%s,a",
780 aop->aopu.aop_ptr->name);
783 pic16_emitcode("pop","acc");
785 pic16_emitcode("mov","%s,#%s",
786 aop->aopu.aop_ptr->name,
788 aop->paged = space->paged;
790 aop->aopu.aop_stk = sym->stack;
798 if (sym->onStack && options.stack10bit)
800 /* It's on the 10 bit stack, which is located in
804 //DEBUGpic16_emitcode(";","%d",__LINE__);
807 pic16_emitcode("push","acc");
809 pic16_emitcode("mov","a,_bp");
810 pic16_emitcode("add","a,#0x%02x",
812 ((char)(sym->stack - _G.nRegsSaved )) :
813 ((char)sym->stack)) & 0xff);
816 pic16_emitcode ("mov","dpx1,#0x40");
817 pic16_emitcode ("mov","dph1,#0x00");
818 pic16_emitcode ("mov","dpl1, a");
822 pic16_emitcode("pop","acc");
824 sym->aop = aop = newAsmop(AOP_DPTR2);
825 aop->size = getSize(sym->type);
831 /* special case for a function */
832 if (IS_FUNC(sym->type)) {
833 sym->aop = aop = newAsmop(AOP_PCODE);
834 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
835 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
836 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
837 PCOI(aop->aopu.pcop)->index = 0;
838 aop->size = FPTRSIZE;
839 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
846 //DEBUGpic16_emitcode(";","%d",__LINE__);
847 /* if in bit space */
848 if (IN_BITSPACE(space)) {
849 sym->aop = aop = newAsmop (AOP_CRY);
850 aop->aopu.aop_dir = sym->rname ;
851 aop->size = getSize(sym->type);
852 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
855 /* if it is in direct space */
856 if (IN_DIRSPACE(space)) {
857 if(!strcmp(sym->rname, "_WREG")) {
858 sym->aop = aop = newAsmop (AOP_ACC);
859 aop->size = getSize(sym->type); /* should always be 1 */
860 assert(aop->size == 1);
861 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
864 sym->aop = aop = newAsmop (AOP_DIR);
865 aop->aopu.aop_dir = sym->rname ;
866 aop->size = getSize(sym->type);
867 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
868 pic16_allocDirReg( IC_LEFT(ic) );
873 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
874 sym->aop = aop = newAsmop (AOP_DIR);
875 aop->aopu.aop_dir = sym->rname ;
876 aop->size = getSize(sym->type);
877 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
878 pic16_allocDirReg( IC_LEFT(ic) );
883 /* only remaining is far space */
884 sym->aop = aop = newAsmop(AOP_PCODE);
886 /* change the next if to 1 to revert to good old immediate code */
887 if(IN_CODESPACE(space)) {
888 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
889 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
890 PCOI(aop->aopu.pcop)->index = 0;
892 /* try to allocate via direct register */
893 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
894 // aop->size = getSize( sym->type );
897 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
898 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
901 if(!pic16_allocDirReg (IC_LEFT(ic)))
905 if(IN_DIRSPACE( space ))
907 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
908 aop->size = FPTRSIZE;
909 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
910 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
911 else if(sym->onStack) {
914 if(SPEC_SCLS(sym->etype) == S_PDATA) {
915 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
916 aop->size = FPTRSIZE;
921 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
923 /* if it is in code space */
924 if (IN_CODESPACE(space))
930 /*-----------------------------------------------------------------*/
931 /* aopForRemat - rematerialzes an object */
932 /*-----------------------------------------------------------------*/
933 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
935 symbol *sym = OP_SYMBOL(op);
937 iCode *ic = NULL, *oldic;
938 asmop *aop = newAsmop(AOP_PCODE);
945 ic = sym->rematiCode;
947 if(IS_OP_POINTER(op)) {
948 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
951 // if(!result) /* fixme-vr */
955 // pic16_emitpcomment("ic: %s\n", printILine(ic));
958 val += (int) operandLitValue(IC_RIGHT(ic));
959 } else if (ic->op == '-') {
960 val -= (int) operandLitValue(IC_RIGHT(ic));
964 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
967 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
970 if(!op->isaddr)viaimmd++; else viaimmd=0;
972 /* set the following if to 1 to revert to good old immediate code */
973 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
976 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
978 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
981 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
983 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
986 PCOI(aop->aopu.pcop)->index = val;
988 aop->size = getSize( sym->type );
990 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
992 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
993 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
995 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
999 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1000 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1002 val, IS_PTR_CONST(operandType(op)));
1004 val, IS_CODEPTR(operandType(op)));
1007 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1009 pic16_allocDirReg (IC_LEFT(ic));
1011 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1018 static int aopIdx (asmop *aop, int offset)
1023 if(aop->type != AOP_REG)
1026 return aop->aopu.aop_reg[offset]->rIdx;
1031 /*-----------------------------------------------------------------*/
1032 /* regsInCommon - two operands have some registers in common */
1033 /*-----------------------------------------------------------------*/
1034 static bool regsInCommon (operand *op1, operand *op2)
1036 symbol *sym1, *sym2;
1039 /* if they have registers in common */
1040 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1043 sym1 = OP_SYMBOL(op1);
1044 sym2 = OP_SYMBOL(op2);
1046 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1049 for (i = 0 ; i < sym1->nRegs ; i++) {
1054 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1058 if (sym2->regs[j] == sym1->regs[i])
1066 /*-----------------------------------------------------------------*/
1067 /* operandsEqu - equivalent */
1068 /*-----------------------------------------------------------------*/
1069 static bool operandsEqu ( operand *op1, operand *op2)
1071 symbol *sym1, *sym2;
1073 /* if they not symbols */
1074 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1077 sym1 = OP_SYMBOL(op1);
1078 sym2 = OP_SYMBOL(op2);
1080 /* if both are itemps & one is spilt
1081 and the other is not then false */
1082 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1083 sym1->isspilt != sym2->isspilt )
1086 /* if they are the same */
1090 if (sym1->rname[0] && sym2->rname[0]
1091 && strcmp (sym1->rname, sym2->rname) == 0)
1095 /* if left is a tmp & right is not */
1096 if (IS_ITEMP(op1) &&
1099 (sym1->usl.spillLoc == sym2))
1102 if (IS_ITEMP(op2) &&
1106 (sym2->usl.spillLoc == sym1))
1112 /*-----------------------------------------------------------------*/
1113 /* pic16_sameRegs - two asmops have the same registers */
1114 /*-----------------------------------------------------------------*/
1115 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1122 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1123 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1125 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1127 if (aop1->type != AOP_REG ||
1128 aop2->type != AOP_REG )
1131 /* This is a bit too restrictive if one is a subset of the other...
1132 if (aop1->size != aop2->size )
1136 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1137 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1139 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1140 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1147 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1149 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1150 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1152 if(aop1 == aop2)return TRUE;
1153 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1155 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1161 /*-----------------------------------------------------------------*/
1162 /* pic16_aopOp - allocates an asmop for an operand : */
1163 /*-----------------------------------------------------------------*/
1164 void pic16_aopOp (operand *op, iCode *ic, bool result)
1173 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1175 /* if this a literal */
1176 if (IS_OP_LITERAL(op)) {
1177 op->aop = aop = newAsmop(AOP_LIT);
1178 aop->aopu.aop_lit = op->operand.valOperand;
1179 aop->size = getSize(operandType(op));
1184 sym_link *type = operandType(op);
1186 if(IS_PTR_CONST(type))
1188 if(IS_CODEPTR(type))
1190 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1193 /* if already has a asmop then continue */
1197 /* if the underlying symbol has a aop */
1198 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1199 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1200 op->aop = OP_SYMBOL(op)->aop;
1204 /* if this is a true symbol */
1205 if (IS_TRUE_SYMOP(op)) {
1206 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1207 op->aop = aopForSym(ic, op, result);
1211 /* this is a temporary : this has
1217 e) can be a return use only */
1219 sym = OP_SYMBOL(op);
1221 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1222 /* if the type is a conditional */
1223 if (sym->regType == REG_CND) {
1224 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1229 /* if it is spilt then two situations
1231 b) has a spill location */
1232 if (sym->isspilt || sym->nRegs == 0) {
1234 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1235 DEBUGpic16_emitcode(";","%d",__LINE__);
1236 /* rematerialize it NOW */
1239 sym->aop = op->aop = aop = aopForRemat (op, result);
1240 // aop->size = getSize(sym->type);
1241 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1248 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1249 aop->size = getSize(sym->type);
1250 for ( i = 0 ; i < 1 ; i++ ) {
1251 aop->aopu.aop_str[i] = accUse[i];
1252 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1254 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1255 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1263 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1264 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1265 //pic16_allocDirReg (IC_LEFT(ic));
1266 aop->size = getSize(sym->type);
1271 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1272 aop->size = getSize(sym->type);
1273 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1274 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1276 DEBUGpic16_emitcode(";","%d",__LINE__);
1280 /* else spill location */
1281 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1282 /* force a new aop if sizes differ */
1283 sym->usl.spillLoc->aop = NULL;
1287 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1288 __FUNCTION__,__LINE__,
1289 sym->usl.spillLoc->rname,
1290 sym->rname, sym->usl.spillLoc->offset);
1293 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1294 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1295 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1296 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1298 sym->usl.spillLoc->offset, op);
1299 } else if (getSize(sym->type) <= 1) {
1300 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1301 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1302 assert (getSize(sym->type) <= 1);
1303 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1304 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1306 /* We need some kind of dummy area for getSize(sym->type) byte,
1307 * use WREG for all storage locations.
1308 * XXX: This only works if we are implementing a `dummy read',
1309 * the stored value will not be retrievable...
1310 * See #1503234 for a case requiring this. */
1311 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1312 aop->size = getSize(sym->type);
1313 for ( i = 0 ; i < aop->size ;i++)
1314 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1316 aop->size = getSize(sym->type);
1322 sym_link *type = operandType(op);
1324 if(IS_PTR_CONST(type))
1326 if(IS_CODEPTR(type))
1328 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1331 /* must be in a register */
1332 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1333 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1334 aop->size = sym->nRegs;
1335 for ( i = 0 ; i < sym->nRegs ;i++)
1336 aop->aopu.aop_reg[i] = sym->regs[i];
1339 /*-----------------------------------------------------------------*/
1340 /* pic16_freeAsmop - free up the asmop given to an operand */
1341 /*----------------------------------------------------------------*/
1342 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1359 /* depending on the asmop type only three cases need work AOP_RO
1360 , AOP_R1 && AOP_STK */
1362 switch (aop->type) {
1364 if (_G.fsr0Pushed ) {
1366 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1367 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1368 // pic16_emitcode ("pop","ar0");
1372 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1376 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1382 pic16_emitcode ("pop","ar0");
1386 bitVectUnSetBit(ic->rUsed,R0_IDX);
1392 pic16_emitcode ("pop","ar1");
1396 bitVectUnSetBit(ic->rUsed,R1_IDX);
1403 /* we must store the result on stack */
1404 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1405 // operands on stack are accessible via "FSR2 + index" with index
1406 // starting at 2 for arguments and growing from 0 downwards for
1407 // local variables (index == 0 is not assigned so we add one here)
1408 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1413 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1414 for(i=0;i<aop->size;i++) {
1415 /* initialise for stack access via frame pointer */
1416 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1417 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1418 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1421 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1425 for(i=0;i<aop->size;i++) {
1426 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1428 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1429 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1430 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1437 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1438 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1439 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1440 deleteSetItem( &_G.sregsAllocSet, sr );
1451 int stk = aop->aopu.aop_stk + aop->size;
1452 bitVectUnSetBit(ic->rUsed,R0_IDX);
1453 bitVectUnSetBit(ic->rUsed,R1_IDX);
1455 getFreePtr(ic,&aop,FALSE);
1457 if (options.stack10bit)
1459 /* I'm not sure what to do here yet... */
1462 "*** Warning: probably generating bad code for "
1463 "10 bit stack mode.\n");
1467 pic16_emitcode ("mov","a,_bp");
1468 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1469 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1471 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1475 pic16_emitcode("pop","acc");
1476 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1478 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1481 pic16_freeAsmop(op,NULL,ic,TRUE);
1483 pic16_emitcode("pop","ar0");
1488 pic16_emitcode("pop","ar1");
1498 /* all other cases just dealloc */
1502 OP_SYMBOL(op)->aop = NULL;
1503 /* if the symbol has a spill */
1505 SPIL_LOC(op)->aop = NULL;
1510 /*-----------------------------------------------------------------*/
1511 /* pic16_aopGet - for fetching value of the aop */
1512 /*-----------------------------------------------------------------*/
1513 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1518 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1520 /* offset is greater than size then zero */
1521 if (offset > (aop->size - 1) &&
1522 aop->type != AOP_LIT)
1525 /* depending on type */
1526 switch (aop->type) {
1530 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1531 rs = Safe_calloc(1, strlen(s)+1);
1536 /* if we need to increment it */
1537 while (offset > aop->coff)
1539 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1543 while (offset < aop->coff)
1545 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1551 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1552 return (dname ? "acc" : "a");
1554 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1555 rs = Safe_calloc (1, strlen (s) + 1);
1563 sprintf (s,"%s",aop->aopu.aop_immd);
1566 sprintf(s,"(%s >> %d)",
1571 aop->aopu.aop_immd);
1572 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1573 rs = Safe_calloc(1,strlen(s)+1);
1579 sprintf(s,"(%s + %d)",
1582 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1584 sprintf(s,"%s",aop->aopu.aop_dir);
1585 rs = Safe_calloc(1,strlen(s)+1);
1590 return aop->aopu.aop_reg[offset]->name;
1593 return aop->aopu.aop_dir;
1596 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1597 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1599 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1600 rs = Safe_strdup("WREG");
1604 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1605 rs = Safe_calloc(1,strlen(s)+1);
1610 aop->coff = offset ;
1612 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1615 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1616 aop->type = AOP_ACC;
1617 return Safe_strdup("_WREG");
1619 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1621 return aop->aopu.aop_str[offset];
1625 pCodeOp *pcop = aop->aopu.pcop;
1626 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1628 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1629 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1631 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1633 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1636 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1639 rs = Safe_calloc(1,strlen(s)+1);
1645 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1647 sprintf(s,"(%s + %d)",
1651 sprintf(s,"%s",aop->aopu.aop_dir);
1652 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1653 rs = Safe_calloc(1,strlen(s)+1);
1659 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1663 // pCodeOp *pcop = aop->aop
1668 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1669 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1670 "aopget got unsupported aop->type");
1676 /* lock has the following meaning: When allocating temporary registers
1677 * for stack variables storage, the value of the temporary register is
1678 * saved on stack. Its value is restored at the end. This procedure is
1679 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1680 * a possibility that before a call to pic16_aopOp, a temporary register
1681 * is allocated for a while and it is freed after some time, this will
1682 * mess the stack and values will not be restored properly. So use lock=1
1683 * to allocate temporary registers used internally by the programmer, and
1684 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1685 * to inform the compiler developer about a possible bug. This is an internal
1686 * feature for developing the compiler -- VR */
1688 int _TempReg_lock = 0;
1689 /*-----------------------------------------------------------------*/
1690 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1691 /*-----------------------------------------------------------------*/
1692 pCodeOp *pic16_popGetTempReg(int lock)
1697 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1699 // werror(W_POSSBUG2, __FILE__, __LINE__);
1702 _TempReg_lock += lock;
1712 /* this code might seem better but it does the *same* job with
1713 * the old code, it all depends on ralloc.c to get a free/unused
1717 while(i < pic16_nRegs) {
1718 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1719 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1720 if((!rr || (rr && rr->isFree))
1721 && !bitVectBitValue(cfunc->regsUsed, i)) {
1722 pcop = pic16_newpCodeOpReg( i );
1723 PCOR(pcop)->r->wasUsed = 1;
1724 PCOR(pcop)->r->isFree = 0;
1731 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1735 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1736 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1737 PCOR(pcop)->r->wasUsed=1;
1738 PCOR(pcop)->r->isFree=0;
1740 /* push value on stack */
1741 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1750 /*-----------------------------------------------------------------*/
1751 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1752 /* is not part of f, but don't save if */
1754 /*-----------------------------------------------------------------*/
1755 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1761 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1764 // werror(W_POSSBUG2, __FILE__, __LINE__);
1767 _TempReg_lock += lock;
1772 i = bitVectFirstBit(f);
1775 /* bypass registers that are used by function */
1776 if(!bitVectBitValue(f, i)) {
1778 /* bypass registers that are already allocated for stack access */
1779 if(!bitVectBitValue(v, i)) {
1781 // debugf("getting register rIdx = %d\n", i);
1782 /* ok, get the operand */
1783 pcop = pic16_newpCodeOpReg( i );
1785 /* should never by NULL */
1786 assert( pcop != NULL );
1790 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1793 PCOR(pcop)->r->wasUsed=1;
1794 PCOR(pcop)->r->isFree=0;
1800 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1802 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1803 /* already used in previous steps, break */
1810 /* caller takes care of the following */
1811 // bitVectSetBit(v, i);
1814 /* push value on stack */
1815 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1816 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1832 /*-----------------------------------------------------------------*/
1833 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1834 /*-----------------------------------------------------------------*/
1835 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1839 _TempReg_lock -= lock;
1841 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1842 PCOR(pcop)->r->isFree = 1;
1844 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1847 /*-----------------------------------------------------------------*/
1848 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1849 /*-----------------------------------------------------------------*/
1850 pCodeOp *pic16_popGetLabel(int key)
1853 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1858 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1861 /*-----------------------------------------------------------------*/
1862 /* pic16_popCopyReg - copy a pcode operator */
1863 /*-----------------------------------------------------------------*/
1864 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1868 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1869 memcpy (pcor, pc, sizeof (pCodeOpReg));
1870 pcor->r->wasUsed = 1;
1872 //pcor->pcop.type = pc->pcop.type;
1874 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1875 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1877 pcor->pcop.name = NULL;
1880 //pcor->rIdx = pc->rIdx;
1881 //pcor->r->wasUsed=1;
1882 //pcor->instance = pc->instance;
1884 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1889 /*-----------------------------------------------------------------*/
1890 /* pic16_popGetLit - asm operator to pcode operator conversion */
1891 /*-----------------------------------------------------------------*/
1892 pCodeOp *pic16_popGetLit(int lit)
1894 return pic16_newpCodeOpLit(lit);
1897 /* Allow for 12 bit literals (LFSR x, <here!>). */
1898 pCodeOp *pic16_popGetLit12(int lit)
1900 return pic16_newpCodeOpLit12(lit);
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1908 return pic16_newpCodeOpLit2(lit, arg2);
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1917 return pic16_newpCodeOpImmd(name, offset,index, 0);
1921 /*-----------------------------------------------------------------*/
1922 /* pic16_popGet - asm operator to pcode operator conversion */
1923 /*-----------------------------------------------------------------*/
1924 pCodeOp *pic16_popGetWithString(char *str)
1930 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1934 pcop = pic16_newpCodeOp(str,PO_STR);
1939 /*-----------------------------------------------------------------*/
1940 /* pic16_popRegFromString - */
1941 /*-----------------------------------------------------------------*/
1942 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1945 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1946 pcop->type = PO_DIR;
1948 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1949 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1954 pcop->name = Safe_calloc(1,strlen(str)+1);
1955 strcpy(pcop->name,str);
1957 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1959 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1960 // PCOR(pcop)->r->wasUsed = 1;
1962 /* make sure that register doesn't exist,
1963 * and operand isn't NULL
1964 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1965 if((PCOR(pcop)->r == NULL)
1967 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1968 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1969 // __FUNCTION__, __LINE__, str, size, offset);
1971 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1972 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1975 PCOR(pcop)->instance = offset;
1980 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1984 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1985 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1987 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1988 PCOR(pcop)->rIdx = rIdx;
1989 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1991 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1993 PCOR(pcop)->r->isFree = 0;
1994 PCOR(pcop)->r->wasUsed = 1;
1996 pcop->type = PCOR(pcop)->r->pc_type;
2001 /*---------------------------------------------------------------------------------*/
2002 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2004 /*---------------------------------------------------------------------------------*/
2005 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2007 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2008 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2014 /*--------------------------------------------------------------------------------.-*/
2015 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2016 /* VR 030601 , adapted by Hans Dorn */
2017 /*--------------------------------------------------------------------------------.-*/
2018 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2021 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2025 /*---------------------------------------------------------------------------------*/
2026 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2027 /* movff instruction */
2028 /*---------------------------------------------------------------------------------*/
2029 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2031 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2032 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2038 /*-----------------------------------------------------------------*/
2039 /* pic16_popGet - asm operator to pcode operator conversion */
2040 /*-----------------------------------------------------------------*/
2041 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2043 // char *s = buffer ;
2049 /* offset is greater than size then zero */
2051 // if (offset > (aop->size - 1) &&
2052 // aop->type != AOP_LIT)
2053 // return NULL; //zero;
2055 /* depending on type */
2056 switch (aop->type) {
2061 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2062 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2068 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2069 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2070 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2071 PCOR(pcop)->r->wasUsed = 1;
2072 PCOR(pcop)->r->isFree = 0;
2074 PCOR(pcop)->instance = offset;
2075 pcop->type = PCOR(pcop)->r->pc_type;
2079 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2080 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2083 /* pCodeOp is already allocated from aopForSym */
2084 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2085 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2090 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2092 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2094 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2096 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2097 PCOR(pcop)->rIdx = rIdx;
2098 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2099 PCOR(pcop)->r->wasUsed=1;
2100 PCOR(pcop)->r->isFree=0;
2102 PCOR(pcop)->instance = offset;
2103 pcop->type = PCOR(pcop)->r->pc_type;
2104 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2108 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2109 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2115 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2116 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2120 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2121 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2128 // debugf2("aop = %p\toffset = %d\n", aop, offset);
2129 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
2130 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2132 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2134 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2135 // pcop->type = PO_GPR_REGISTER;
2136 PCOR(pcop)->rIdx = rIdx;
2137 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2138 PCOR(pcop)->r->wasUsed=1;
2139 PCOR(pcop)->r->isFree=0;
2141 PCOR(pcop)->instance = offset;
2142 pcop->type = PCOR(pcop)->r->pc_type;
2144 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2145 // rs = aop->aopu.aop_reg[offset]->name;
2146 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2151 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2153 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2154 PCOR(pcop)->instance = offset;
2155 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2156 //if(PCOR(pcop)->r == NULL)
2157 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2161 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2162 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2165 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2166 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2169 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2170 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2171 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2172 pcop->type = PCOR(pcop)->r->pc_type;
2173 pcop->name = PCOR(pcop)->r->name;
2179 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2181 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2182 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2183 switch( aop->aopu.pcop->type ) {
2184 case PO_DIR: PCOR(pcop)->instance += offset; break;
2185 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2190 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2191 assert( 0 ); /* should never reach here */;
2196 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2197 "pic16_popGet got unsupported aop->type");
2200 /*-----------------------------------------------------------------*/
2201 /* pic16_aopPut - puts a string for a aop */
2202 /*-----------------------------------------------------------------*/
2203 void pic16_aopPut (asmop *aop, char *s, int offset)
2210 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2212 if (aop->size && offset > ( aop->size - 1)) {
2213 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2214 "pic16_aopPut got offset > aop->size");
2218 /* will assign value to value */
2219 /* depending on where it is ofcourse */
2220 switch (aop->type) {
2223 sprintf(d,"(%s + %d)",
2224 aop->aopu.aop_dir,offset);
2225 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2228 sprintf(d,"%s",aop->aopu.aop_dir);
2231 DEBUGpic16_emitcode(";","%d",__LINE__);
2233 pic16_emitcode("movf","%s,w",s);
2234 pic16_emitcode("movwf","%s",d);
2237 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2238 if(offset >= aop->size) {
2239 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2242 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2245 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2252 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2253 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2256 strcmp(s,"r0") == 0 ||
2257 strcmp(s,"r1") == 0 ||
2258 strcmp(s,"r2") == 0 ||
2259 strcmp(s,"r3") == 0 ||
2260 strcmp(s,"r4") == 0 ||
2261 strcmp(s,"r5") == 0 ||
2262 strcmp(s,"r6") == 0 ||
2263 strcmp(s,"r7") == 0 )
2264 pic16_emitcode("mov","%s,%s ; %d",
2265 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2269 if(strcmp(s,"W")==0 )
2270 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2272 pic16_emitcode("movwf","%s",
2273 aop->aopu.aop_reg[offset]->name);
2275 if(strcmp(s,zero)==0) {
2276 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2278 } else if(strcmp(s,"W")==0) {
2279 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2280 pcop->type = PO_GPR_REGISTER;
2282 PCOR(pcop)->rIdx = -1;
2283 PCOR(pcop)->r = NULL;
2285 DEBUGpic16_emitcode(";","%d",__LINE__);
2286 pcop->name = Safe_strdup(s);
2287 pic16_emitpcode(POC_MOVFW,pcop);
2288 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2289 } else if(strcmp(s,one)==0) {
2290 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2291 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2293 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2301 if (aop->type == AOP_DPTR2)
2307 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2308 "pic16_aopPut writting to code space");
2312 while (offset > aop->coff) {
2314 pic16_emitcode ("inc","dptr");
2317 while (offset < aop->coff) {
2319 pic16_emitcode("lcall","__decdptr");
2324 /* if not in accumulater */
2327 pic16_emitcode ("movx","@dptr,a");
2329 if (aop->type == AOP_DPTR2)
2337 while (offset > aop->coff) {
2339 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2341 while (offset < aop->coff) {
2343 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2349 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2354 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2356 if (strcmp(s,"r0") == 0 ||
2357 strcmp(s,"r1") == 0 ||
2358 strcmp(s,"r2") == 0 ||
2359 strcmp(s,"r3") == 0 ||
2360 strcmp(s,"r4") == 0 ||
2361 strcmp(s,"r5") == 0 ||
2362 strcmp(s,"r6") == 0 ||
2363 strcmp(s,"r7") == 0 ) {
2365 sprintf(buffer,"a%s",s);
2366 pic16_emitcode("mov","@%s,%s",
2367 aop->aopu.aop_ptr->name,buffer);
2369 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2374 if (strcmp(s,"a") == 0)
2375 pic16_emitcode("push","acc");
2377 pic16_emitcode("push","%s",s);
2382 /* if bit variable */
2383 if (!aop->aopu.aop_dir) {
2384 pic16_emitcode("clr","a");
2385 pic16_emitcode("rlc","a");
2388 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2391 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2394 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2396 lbl = newiTempLabel(NULL);
2398 if (strcmp(s,"a")) {
2401 pic16_emitcode("clr","c");
2402 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2403 pic16_emitcode("cpl","c");
2404 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2405 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2412 if (strcmp(aop->aopu.aop_str[offset],s))
2413 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2418 if (!offset && (strcmp(s,"acc") == 0))
2421 if (strcmp(aop->aopu.aop_str[offset],s))
2422 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2426 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2427 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2428 // "pic16_aopPut got unsupported aop->type");
2434 /*-----------------------------------------------------------------*/
2435 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2436 /*-----------------------------------------------------------------*/
2437 void pic16_mov2w (asmop *aop, int offset)
2439 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2442 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2444 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2447 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2449 if(is_LitAOp(src)) {
2450 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2451 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2453 if(pic16_sameRegsOfs(src, dst, offset))return;
2454 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2455 pic16_popGet(dst, offset)));
2459 static void pic16_movLit2f(pCodeOp *pc, int lit)
2461 if (0 == (lit & 0x00ff))
2463 pic16_emitpcode (POC_CLRF, pc);
2464 } else if (0xff == (lit & 0x00ff))
2466 pic16_emitpcode (POC_SETF, pc);
2468 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2469 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2473 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2475 if(is_LitAOp(src)) {
2476 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2477 pic16_emitpcode(POC_MOVWF, dst);
2479 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2483 void pic16_testStackOverflow(void)
2485 #define GSTACK_TEST_NAME "_gstack_test"
2487 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2492 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2493 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2494 // strcpy(sym->rname, GSTACK_TEST_NAME);
2495 checkAddSym(&externs, sym);
2500 /* push pcop into stack */
2501 void pic16_pushpCodeOp(pCodeOp *pcop)
2503 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2504 if (pcop->type == PO_LITERAL) {
2505 pic16_emitpcode(POC_MOVLW, pcop);
2506 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2508 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2510 if(pic16_options.gstack)
2511 pic16_testStackOverflow();
2515 /* pop pcop from stack */
2516 void pic16_poppCodeOp(pCodeOp *pcop)
2518 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2519 if(pic16_options.gstack)
2520 pic16_testStackOverflow();
2524 /*-----------------------------------------------------------------*/
2525 /* pushw - pushes wreg to stack */
2526 /*-----------------------------------------------------------------*/
2529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2531 if(pic16_options.gstack)
2532 pic16_testStackOverflow();
2536 /*-----------------------------------------------------------------*/
2537 /* pushaop - pushes aop to stack */
2538 /*-----------------------------------------------------------------*/
2539 void pushaop(asmop *aop, int offset)
2541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2543 if(_G.resDirect)return;
2545 if(is_LitAOp(aop)) {
2546 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2547 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2549 pic16_emitpcode(POC_MOVFF,
2550 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2553 if(pic16_options.gstack)
2554 pic16_testStackOverflow();
2557 /*-----------------------------------------------------------------*/
2558 /* popaop - pops aop from stack */
2559 /*-----------------------------------------------------------------*/
2560 void popaop(asmop *aop, int offset)
2562 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2563 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2564 if(pic16_options.gstack)
2565 pic16_testStackOverflow();
2568 void popaopidx(asmop *aop, int offset, int index)
2572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2574 if(STACK_MODEL_LARGE)ofs++;
2576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2577 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2578 if(pic16_options.gstack)
2579 pic16_testStackOverflow();
2582 #if !(USE_GENERIC_SIGNED_SHIFT)
2583 /*-----------------------------------------------------------------*/
2584 /* reAdjustPreg - points a register back to where it should */
2585 /*-----------------------------------------------------------------*/
2586 static void reAdjustPreg (asmop *aop)
2590 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2592 if ((size = aop->size) <= 1)
2595 switch (aop->type) {
2599 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2603 if (aop->type == AOP_DPTR2)
2609 pic16_emitcode("lcall","__decdptr");
2612 if (aop->type == AOP_DPTR2)
2624 /*-----------------------------------------------------------------*/
2625 /* opIsGptr: returns non-zero if the passed operand is */
2626 /* a generic pointer type. */
2627 /*-----------------------------------------------------------------*/
2628 static int opIsGptr(operand *op)
2630 sym_link *type = operandType(op);
2632 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2633 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2641 /*-----------------------------------------------------------------*/
2642 /* pic16_getDataSize - get the operand data size */
2643 /*-----------------------------------------------------------------*/
2644 int pic16_getDataSize(operand *op)
2646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2649 return AOP_SIZE(op);
2651 // tsd- in the pic port, the genptr size is 1, so this code here
2652 // fails. ( in the 8051 port, the size was 4).
2655 size = AOP_SIZE(op);
2656 if (size == GPTRSIZE)
2658 sym_link *type = operandType(op);
2659 if (IS_GENPTR(type))
2661 /* generic pointer; arithmetic operations
2662 * should ignore the high byte (pointer type).
2665 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2672 /*-----------------------------------------------------------------*/
2673 /* pic16_outAcc - output Acc */
2674 /*-----------------------------------------------------------------*/
2675 void pic16_outAcc(operand *result)
2678 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2679 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2682 size = pic16_getDataSize(result);
2684 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2687 /* unsigned or positive */
2689 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2694 /*-----------------------------------------------------------------*/
2695 /* pic16_outBitC - output a bit C */
2696 /* Move to result the value of Carry flag -- VR */
2697 /*-----------------------------------------------------------------*/
2698 void pic16_outBitC(operand *result)
2702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2704 /* if the result is bit */
2705 if (AOP_TYPE(result) == AOP_CRY) {
2706 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2707 pic16_aopPut(AOP(result),"c",0);
2710 i = AOP_SIZE(result);
2712 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2714 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2718 /*-----------------------------------------------------------------*/
2719 /* pic16_outBitOp - output a bit from Op */
2720 /* Move to result the value of set/clr op -- VR */
2721 /*-----------------------------------------------------------------*/
2722 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2726 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2728 /* if the result is bit */
2729 if (AOP_TYPE(result) == AOP_CRY) {
2730 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2731 pic16_aopPut(AOP(result),"c",0);
2734 i = AOP_SIZE(result);
2736 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2738 pic16_emitpcode(POC_RRCF, pcop);
2739 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2743 /*-----------------------------------------------------------------*/
2744 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2745 /*-----------------------------------------------------------------*/
2746 void pic16_toBoolean(operand *oper)
2748 int size = AOP_SIZE(oper) - 1;
2751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2753 if ( AOP_TYPE(oper) != AOP_ACC) {
2754 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2757 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2761 /*-----------------------------------------------------------------*/
2762 /* genUminusFloat - unary minus for floating points */
2763 /*-----------------------------------------------------------------*/
2764 static void genUminusFloat(operand *op,operand *result)
2766 int size ,offset =0 ;
2769 /* for this we just need to flip the
2770 first it then copy the rest in place */
2771 size = AOP_SIZE(op);
2772 assert( size == AOP_SIZE(result) );
2775 pic16_mov2f(AOP(result), AOP(op), offset);
2779 /* toggle the MSB's highest bit */
2780 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2783 /*-----------------------------------------------------------------*/
2784 /* genUminus - unary minus code generation */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminus (iCode *ic)
2789 sym_link *optype, *rtype;
2796 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2797 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2799 /* if both in bit space then special case */
2800 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2801 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2803 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2804 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2805 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2809 optype = operandType(IC_LEFT(ic));
2810 rtype = operandType(IC_RESULT(ic));
2813 /* if float then do float stuff */
2814 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2815 if(IS_FIXED(optype))
2816 debugf("implement fixed16x16 type\n", 0);
2818 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2822 /* otherwise subtract from zero by taking the 2's complement */
2823 size = AOP_SIZE(IC_LEFT(ic));
2824 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2825 label = newiTempLabel ( NULL );
2827 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2828 for (i=size-1; i > 0; i--) {
2829 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2831 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2832 for (i=1; i < size; i++) {
2833 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2834 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2837 for (i=size-1; i >= 0; i--) {
2838 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2839 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2842 for (i=0; i < size-2; i++) {
2843 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2844 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2846 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2848 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2851 pic16_emitpLabel (label->key);
2854 /* release the aops */
2855 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2856 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2860 /*-----------------------------------------------------------------*/
2861 /* saveRegisters - will look for a call and save the registers */
2862 /*-----------------------------------------------------------------*/
2863 static void saveRegisters(iCode *lic)
2870 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2872 for (ic = lic ; ic ; ic = ic->next)
2873 if (ic->op == CALL || ic->op == PCALL)
2877 fprintf(stderr,"found parameter push with no function call\n");
2881 /* if the registers have been saved already then
2883 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2886 /* find the registers in use at this time
2887 and push them away to safety */
2888 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2892 if (options.useXstack) {
2893 if (bitVectBitValue(rsave,R0_IDX))
2894 pic16_emitcode("mov","b,r0");
2895 pic16_emitcode("mov","r0,%s",spname);
2896 for (i = 0 ; i < pic16_nRegs ; i++) {
2897 if (bitVectBitValue(rsave,i)) {
2899 pic16_emitcode("mov","a,b");
2901 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2902 pic16_emitcode("movx","@r0,a");
2903 pic16_emitcode("inc","r0");
2906 pic16_emitcode("mov","%s,r0",spname);
2907 if (bitVectBitValue(rsave,R0_IDX))
2908 pic16_emitcode("mov","r0,b");
2910 //for (i = 0 ; i < pic16_nRegs ; i++) {
2911 // if (bitVectBitValue(rsave,i))
2912 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2915 dtype = operandType(IC_LEFT(ic));
2916 if (currFunc && dtype &&
2917 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2918 IFFUNC_ISISR(currFunc->type) &&
2921 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2924 /*-----------------------------------------------------------------*/
2925 /* unsaveRegisters - pop the pushed registers */
2926 /*-----------------------------------------------------------------*/
2927 static void unsaveRegisters (iCode *ic)
2932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2933 /* find the registers in use at this time
2934 and push them away to safety */
2935 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2938 if (options.useXstack) {
2939 pic16_emitcode("mov","r0,%s",spname);
2940 for (i = pic16_nRegs ; i >= 0 ; i--) {
2941 if (bitVectBitValue(rsave,i)) {
2942 pic16_emitcode("dec","r0");
2943 pic16_emitcode("movx","a,@r0");
2945 pic16_emitcode("mov","b,a");
2947 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2951 pic16_emitcode("mov","%s,r0",spname);
2952 if (bitVectBitValue(rsave,R0_IDX))
2953 pic16_emitcode("mov","r0,b");
2955 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2956 // if (bitVectBitValue(rsave,i))
2957 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2964 /*-----------------------------------------------------------------*/
2966 /*-----------------------------------------------------------------*/
2967 static void pushSide(operand * oper, int size)
2970 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2972 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2973 if (AOP_TYPE(oper) != AOP_REG &&
2974 AOP_TYPE(oper) != AOP_DIR &&
2976 pic16_emitcode("mov","a,%s",l);
2977 pic16_emitcode("push","acc");
2979 pic16_emitcode("push","%s",l);
2984 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2986 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2987 pic16_emitpcode(POC_MOVFW, src);
2988 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2990 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2991 src, pic16_popGet(AOP(op), offset)));
2996 /*-----------------------------------------------------------------*/
2997 /* assignResultValue - assign results to oper, rescall==1 is */
2998 /* called from genCall() or genPcall() */
2999 /*-----------------------------------------------------------------*/
3000 static void assignResultValue(operand * oper, int res_size, int rescall)
3002 int size = AOP_SIZE(oper);
3006 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3007 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3010 /* assign result from a call/pcall function() */
3012 /* function results are stored in a special order,
3013 * see top of file with Function return policy, or manual */
3016 /* 8-bits, result in WREG */
3017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3019 if(size > 1 && res_size > 1) {
3020 /* 16-bits, result in PRODL:WREG */
3021 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3024 if(size > 2 && res_size > 2) {
3025 /* 24-bits, result in PRODH:PRODL:WREG */
3026 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3029 if(size > 3 && res_size > 3) {
3030 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3031 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3034 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3037 /* >32-bits, result on stack, and FSR0 points to beginning.
3038 * Fix stack when done */
3040 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3042 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3043 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3045 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3050 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3051 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3052 if(STACK_MODEL_LARGE) {
3054 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3058 int areg = 0; /* matching argument register */
3060 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3061 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3064 /* its called from genReceive (probably) -- VR */
3065 /* I hope this code will not be called from somewhere else in the future!
3066 * We manually set the pseudo stack pointer in genReceive. - dw
3068 if(!GpsuedoStkPtr && _G.useWreg) {
3069 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3071 /* The last byte in the assignment is in W */
3072 if(areg <= GpsuedoStkPtr) {
3074 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3076 // debugf("receive from WREG\n", 0);
3078 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3081 _G.stack_lat = AOP_SIZE(oper)-1;
3086 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3087 // debugf("receive from STACK\n", 0);
3094 /*-----------------------------------------------------------------*/
3095 /* genIpush - generate code for pushing this gets a little complex */
3096 /*-----------------------------------------------------------------*/
3097 static void genIpush (iCode *ic)
3099 // int size, offset=0;
3102 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3105 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3107 /* send to stack as normal */
3108 addSet(&_G.sendSet,ic);
3109 // addSetHead(&_G.sendSet,ic);
3110 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3115 int size, offset = 0 ;
3119 /* if this is not a parm push : ie. it is spill push
3120 and spill push is always done on the local stack */
3121 if (!ic->parmPush) {
3123 /* and the item is spilt then do nothing */
3124 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3127 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3128 size = AOP_SIZE(IC_LEFT(ic));
3129 /* push it on the stack */
3131 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3136 pic16_emitcode("push","%s",l);
3141 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3145 /*-----------------------------------------------------------------*/
3146 /* genIpop - recover the registers: can happen only for spilling */
3147 /*-----------------------------------------------------------------*/
3148 static void genIpop (iCode *ic)
3151 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3156 /* if the temp was not pushed then */
3157 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3160 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3161 size = AOP_SIZE(IC_LEFT(ic));
3164 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3167 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3172 /*-----------------------------------------------------------------*/
3173 /* unsaverbank - restores the resgister bank from stack */
3174 /*-----------------------------------------------------------------*/
3175 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3177 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3185 if (options.useXstack) {
3187 r = getFreePtr(ic,&aop,FALSE);
3190 pic16_emitcode("mov","%s,_spx",r->name);
3191 pic16_emitcode("movx","a,@%s",r->name);
3192 pic16_emitcode("mov","psw,a");
3193 pic16_emitcode("dec","%s",r->name);
3196 pic16_emitcode ("pop","psw");
3199 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3200 if (options.useXstack) {
3201 pic16_emitcode("movx","a,@%s",r->name);
3202 //pic16_emitcode("mov","(%s+%d),a",
3203 // regspic16[i].base,8*bank+regspic16[i].offset);
3204 pic16_emitcode("dec","%s",r->name);
3207 pic16_emitcode("pop",""); //"(%s+%d)",
3208 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3211 if (options.useXstack) {
3213 pic16_emitcode("mov","_spx,%s",r->name);
3214 pic16_freeAsmop(NULL,aop,ic,TRUE);
3220 /*-----------------------------------------------------------------*/
3221 /* saverbank - saves an entire register bank on the stack */
3222 /*-----------------------------------------------------------------*/
3223 static void saverbank (int bank, iCode *ic, bool pushPsw)
3225 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3232 if (options.useXstack) {
3235 r = getFreePtr(ic,&aop,FALSE);
3236 pic16_emitcode("mov","%s,_spx",r->name);
3240 for (i = 0 ; i < pic16_nRegs ;i++) {
3241 if (options.useXstack) {
3242 pic16_emitcode("inc","%s",r->name);
3243 //pic16_emitcode("mov","a,(%s+%d)",
3244 // regspic16[i].base,8*bank+regspic16[i].offset);
3245 pic16_emitcode("movx","@%s,a",r->name);
3247 pic16_emitcode("push","");// "(%s+%d)",
3248 //regspic16[i].base,8*bank+regspic16[i].offset);
3252 if (options.useXstack) {
3253 pic16_emitcode("mov","a,psw");
3254 pic16_emitcode("movx","@%s,a",r->name);
3255 pic16_emitcode("inc","%s",r->name);
3256 pic16_emitcode("mov","_spx,%s",r->name);
3257 pic16_freeAsmop (NULL,aop,ic,TRUE);
3260 pic16_emitcode("push","psw");
3262 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3270 static int wparamCmp(void *p1, void *p2)
3272 return (!strcmp((char *)p1, (char *)p2));
3275 int inWparamList(char *s)
3277 return isinSetWith(wparamList, s, wparamCmp);
3281 /*-----------------------------------------------------------------*/
3282 /* genCall - generates a call statement */
3283 /*-----------------------------------------------------------------*/
3284 static void genCall (iCode *ic)
3294 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3295 /* if caller saves & we have not saved then */
3296 // if (!ic->regsSaved)
3297 // saveRegisters(ic);
3299 /* initialise stackParms for IPUSH pushes */
3300 // stackParms = psuedoStkPtr;
3301 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3302 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3303 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3306 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3309 /* if send set is not empty the assign */
3312 int psuedoStkPtr=-1;
3313 int firstTimeThruLoop = 1;
3316 /* reverse sendSet if function is not reentrant */
3317 if(!IFFUNC_ISREENT(ftype))
3318 _G.sendSet = reverseSet(_G.sendSet);
3320 /* First figure how many parameters are getting passed */
3324 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3328 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329 size = AOP_SIZE(IC_LEFT(sic));
3333 /* pass the last byte through WREG */
3337 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3339 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3341 if(!firstTimeThruLoop) {
3342 /* If this is not the first time we've been through the loop
3343 * then we need to save the parameter in a temporary
3344 * register. The last byte of the last parameter is
3348 // --psuedoStkPtr; // sanity check
3352 firstTimeThruLoop=0;
3354 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3359 /* all arguments are passed via stack */
3363 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3367 // pushaop(AOP(IC_LEFT(sic)), size);
3368 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3375 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3379 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3380 pushw(); /* save last parameter to stack if functions has varargs */
3384 } else use_wreg = 0;
3386 _G.stackRegSet = _G.sendSet;
3391 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3395 /* if we need to assign a result value */
3396 if ((IS_ITEMP(IC_RESULT(ic))
3397 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3398 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3399 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3402 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3405 /* Must not assign an 8-bit result to a 16-bit variable;
3406 * this would use (used...) the uninitialized PRODL! */
3407 /* FIXME: Need a proper way to obtain size of function result type,
3408 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3409 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3411 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3414 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3417 if(!stackParms && ic->parmBytes) {
3418 stackParms = ic->parmBytes;
3421 stackParms -= use_wreg;
3424 if(stackParms == 1) {
3425 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3427 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3428 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3430 if(STACK_MODEL_LARGE) {
3432 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3437 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3440 /* adjust the stack for parameters if required */
3441 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3444 /* if register bank was saved then pop them */
3446 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3448 /* if we hade saved some registers then unsave them */
3449 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3450 unsaveRegisters (ic);
3456 /*-----------------------------------------------------------------*/
3457 /* genPcall - generates a call by pointer statement */
3458 /* new version, created from genCall - HJD */
3459 /*-----------------------------------------------------------------*/
3460 static void genPcall (iCode *ic)
3464 symbol *retlbl = newiTempLabel(NULL);
3465 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3469 fntype = operandType( IC_LEFT(ic) )->next;
3471 /* if send set is not empty the assign */
3474 int psuedoStkPtr=-1;
3476 /* reverse sendSet if function is not reentrant */
3477 if(!IFFUNC_ISREENT(fntype))
3478 _G.sendSet = reverseSet(_G.sendSet);
3482 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3485 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3486 size = AOP_SIZE(IC_LEFT(sic));
3489 /* all parameters are passed via stack, since WREG is clobbered
3490 * by the calling sequence */
3492 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3493 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3494 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3496 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3500 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3503 _G.stackRegSet = _G.sendSet;
3507 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3509 // push return address
3510 // push $ on return stack, then replace with retlbl
3512 /* Thanks to Thorsten Klose for pointing out that the following
3513 * snippet should be interrupt safe */
3514 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3515 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3517 pic16_emitpcodeNULLop(POC_PUSH);
3519 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3520 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3521 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3522 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3523 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3524 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3527 /* restore interrupt control register */
3528 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3529 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3531 /* make the call by writing the pointer into pc */
3532 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3533 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3535 // note: MOVFF to PCL not allowed
3536 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3540 /* return address is here: (X) */
3541 pic16_emitpLabelFORCE(retlbl->key);
3543 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3546 /* if we need assign a result value */
3547 if ((IS_ITEMP(IC_RESULT(ic))
3548 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3549 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3550 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3553 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3556 /* FIXME: Need proper way to obtain the function result's type.
3557 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3558 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3560 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3561 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3563 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3566 // stackParms -= use_wreg;
3569 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3570 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3571 if(STACK_MODEL_LARGE) {
3573 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3578 /*-----------------------------------------------------------------*/
3579 /* resultRemat - result is rematerializable */
3580 /*-----------------------------------------------------------------*/
3581 static int resultRemat (iCode *ic)
3583 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3584 if (SKIP_IC(ic) || ic->op == IFX)
3587 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3588 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3589 if (sym->remat && !POINTER_SET(ic))
3596 #if defined(__BORLANDC__) || defined(_MSC_VER)
3597 #define STRCASECMP stricmp
3599 #define STRCASECMP strcasecmp
3603 /*-----------------------------------------------------------------*/
3604 /* inExcludeList - return 1 if the string is in exclude Reg list */
3605 /*-----------------------------------------------------------------*/
3606 static bool inExcludeList(char *s)
3608 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3611 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3612 if (options.excludeRegs[i] &&
3613 STRCASECMP(options.excludeRegs[i],"none") == 0)
3616 for ( i = 0 ; options.excludeRegs[i]; i++) {
3617 if (options.excludeRegs[i] &&
3618 STRCASECMP(s,options.excludeRegs[i]) == 0)
3625 /*-----------------------------------------------------------------*/
3626 /* genFunction - generated code for function entry */
3627 /*-----------------------------------------------------------------*/
3628 static void genFunction (iCode *ic)
3634 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3636 pic16_labelOffset += (max_key+4);
3641 ftype = operandType(IC_LEFT(ic));
3642 sym = OP_SYMBOL(IC_LEFT(ic));
3644 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3645 /* create an absolute section at the interrupt vector:
3646 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3651 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3653 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3654 sprintf(asymname, "ivec_%s", sym->name);
3656 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3658 /* when an interrupt is declared as naked, do not emit the special
3659 * wrapper segment at vector address. The user should take care for
3660 * this instead. -- VR */
3662 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3663 asym = newSymbol(asymname, 0);
3664 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3665 pic16_addpBlock( apb );
3667 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3668 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3669 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3670 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3671 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3673 /* mark the end of this tiny function */
3674 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3676 sprintf(asymname, "%s", sym->rname);
3682 abSym = Safe_calloc(1, sizeof(absSym));
3683 strcpy(abSym->name, asymname);
3685 switch( FUNC_INTNO(sym->type) ) {
3686 case 0: abSym->address = 0x000000; break;
3687 case 1: abSym->address = 0x000008; break;
3688 case 2: abSym->address = 0x000018; break;
3691 // fprintf(stderr, "no interrupt number is given\n");
3692 abSym->address = -1; break;
3695 /* relocate interrupt vectors if needed */
3696 if(abSym->address != -1)
3697 abSym->address += pic16_options.ivt_loc;
3699 addSet(&absSymSet, abSym);
3703 /* create the function header */
3704 pic16_emitcode(";","-----------------------------------------");
3705 pic16_emitcode(";"," function %s",sym->name);
3706 pic16_emitcode(";","-----------------------------------------");
3708 /* prevent this symbol from being emitted as 'extern' */
3709 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3711 pic16_emitcode("","%s:",sym->rname);
3712 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3717 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3718 if(!strcmp(ab->name, sym->rname)) {
3719 pic16_pBlockConvert2Absolute(pb);
3725 if(IFFUNC_ISNAKED(ftype)) {
3726 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3730 /* if critical function then turn interrupts off */
3731 if (IFFUNC_ISCRITICAL(ftype)) {
3732 //pic16_emitcode("clr","ea");
3735 currFunc = sym; /* update the currFunc symbol */
3736 _G.fregsUsed = sym->regsUsed;
3737 _G.sregsAlloc = newBitVect(128);
3740 /* if this is an interrupt service routine then
3741 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3742 if (IFFUNC_ISISR(sym->type)) {
3743 _G.usefastretfie = 1; /* use shadow registers by default */
3745 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3746 if(!FUNC_ISSHADOWREGS(sym->type)) {
3747 /* do not save WREG,STATUS,BSR for high priority interrupts
3748 * because they are stored in the hardware shadow registers already */
3749 _G.usefastretfie = 0;
3750 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3751 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3752 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3755 /* these should really be optimized somehow, because not all
3756 * interrupt handlers modify them */
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3758 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3759 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3762 // pic16_pBlockConvert2ISR(pb);
3765 /* emit code to setup stack frame if user enabled,
3766 * and function is not main() */
3768 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3769 if(strcmp(sym->name, "main")) {
3771 || !options.ommitFramePtr
3773 || IFFUNC_ARGS(sym->type)
3774 || FUNC_HASSTACKPARM(sym->etype)
3776 /* setup the stack frame */
3777 if(STACK_MODEL_LARGE)
3778 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3779 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3781 if(STACK_MODEL_LARGE)
3782 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3783 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3787 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3790 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3792 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3793 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3795 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3798 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3799 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3806 /* if callee-save to be used for this function
3807 * then save the registers being used in this function */
3808 // if (IFFUNC_CALLEESAVES(sym->type))
3809 if(strcmp(sym->name, "main")) {
3812 /* if any registers used */
3813 if (sym->regsUsed) {
3814 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3817 /* save the registers used */
3818 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3819 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3820 if (bitVectBitValue(sym->regsUsed,i)) {
3822 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3824 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3827 if(!pic16_regWithIdx(i)->wasUsed) {
3828 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3829 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3830 pic16_regWithIdx(i)->wasUsed = 1;
3837 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3838 for(i=0;i<sym->regsUsed->size;i++) {
3839 if(bitVectBitValue(sym->regsUsed, i)) {
3844 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3847 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3852 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3853 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3856 /*-----------------------------------------------------------------*/
3857 /* genEndFunction - generates epilogue for functions */
3858 /*-----------------------------------------------------------------*/
3859 static void genEndFunction (iCode *ic)
3861 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3865 if(IFFUNC_ISNAKED(sym->type)) {
3866 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3872 /* add code for ISCRITICAL */
3873 if(IFFUNC_ISCRITICAL(sym->type)) {
3874 /* if critical function, turn on interrupts */
3876 /* TODO: add code here -- VR */
3879 // sym->regsUsed = _G.fregsUsed;
3881 /* now we need to restore the registers */
3882 /* if any registers used */
3884 /* first restore registers that might be used for stack access */
3885 if(_G.sregsAllocSet) {
3888 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3889 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3890 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3894 if (strcmp(sym->name, "main") && sym->regsUsed) {
3897 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3898 /* restore registers used */
3899 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3900 for ( i = sym->regsUsed->size; i >= 0; i--) {
3901 if (bitVectBitValue(sym->regsUsed,i)) {
3902 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3906 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3911 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3913 if (sym->stack == 1) {
3914 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3915 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3917 // we have to add more than one...
3918 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3919 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3920 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3922 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3923 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3924 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3928 if(strcmp(sym->name, "main")) {
3930 || !options.ommitFramePtr
3932 || IFFUNC_ARGS(sym->type)
3933 || FUNC_HASSTACKPARM(sym->etype)
3935 /* restore stack frame */
3936 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3937 if(STACK_MODEL_LARGE)
3938 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3944 if (IFFUNC_ISISR(sym->type)) {
3945 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3946 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3947 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3948 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3950 if(!FUNC_ISSHADOWREGS(sym->type)) {
3951 /* do not restore interrupt vector for WREG,STATUS,BSR
3952 * for high priority interrupt, see genFunction */
3953 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3954 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3955 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3957 // _G.interruptvector = 0; /* sanity check */
3960 /* if debug then send end of function */
3961 /* if (options.debug && currFunc) */
3963 debugFile->writeEndFunction (currFunc, ic, 1);
3966 if(_G.usefastretfie)
3967 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3969 pic16_emitpcodeNULLop(POC_RETFIE);
3971 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3973 _G.usefastretfie = 0;
3977 if (IFFUNC_ISCRITICAL(sym->type)) {
3978 pic16_emitcode("setb","ea");
3981 /* if debug then send end of function */
3983 debugFile->writeEndFunction (currFunc, ic, 1);
3986 /* insert code to restore stack frame, if user enabled it
3987 * and function is not main() */
3990 pic16_emitpcodeNULLop(POC_RETURN);
3992 /* Mark the end of a function */
3993 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3997 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3999 unsigned long lit=1;
4004 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4005 if(AOP_TYPE(op) == AOP_LIT) {
4006 if(!IS_FLOAT(operandType( op ))) {
4007 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4010 unsigned long lit_int;
4014 /* take care if literal is a float */
4015 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4020 if (AOP_TYPE(op) == AOP_LIT) {
4021 /* FIXME: broken for
4022 * char __at(0x456) foo;
4024 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4025 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4026 } else if (AOP_TYPE(op) == AOP_PCODE
4027 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4028 /* char *s= "aaa"; return s; */
4029 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4030 * that the generic pointer is interpreted correctly
4031 * as referring to __code space, but this is fragile! */
4032 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4033 /* XXX: should check that dest != WREG */
4034 pic16_emitpcode(POC_MOVWF, dest);
4036 if(dest->type == PO_WREG && (offset == 0)) {
4037 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4040 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4044 /*-----------------------------------------------------------------*/
4045 /* genRet - generate code for return statement */
4046 /*-----------------------------------------------------------------*/
4047 static void genRet (iCode *ic)
4053 /* if we have no return value then
4054 * just generate the "ret" */
4059 /* we have something to return then
4060 * move the return value into place */
4061 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4062 size = AOP_SIZE(IC_LEFT(ic));
4066 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4069 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4072 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4074 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4077 /* >32-bits, setup stack and FSR0 */
4079 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4080 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4082 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4084 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4089 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4090 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4092 if(STACK_MODEL_LARGE) {
4093 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4094 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4096 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4101 /* old code, left here for reference -- VR */
4105 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4107 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4108 pic16_emitpcomment("push %s",l);
4111 DEBUGpic16_emitcode(";", "%d", __LINE__);
4112 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4113 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4115 if (strcmp(fReturn[offset],l)) {
4116 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4117 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4118 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4120 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4124 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4134 if (strcmp(fReturn[pushed],"a"))
4135 pic16_emitcode("pop",fReturn[pushed]);
4137 pic16_emitcode("pop","acc");
4143 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4146 /* generate a jump to the return label
4147 * if the next is not the return statement */
4148 if (!(ic->next && ic->next->op == LABEL
4149 && IC_LABEL(ic->next) == returnLabel)) {
4151 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4152 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4156 /*-----------------------------------------------------------------*/
4157 /* genLabel - generates a label */
4158 /*-----------------------------------------------------------------*/
4159 static void genLabel (iCode *ic)
4163 /* special case never generate */
4164 if (IC_LABEL(ic) == entryLabel)
4167 pic16_emitpLabel(IC_LABEL(ic)->key);
4168 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4171 /*-----------------------------------------------------------------*/
4172 /* genGoto - generates a goto */
4173 /*-----------------------------------------------------------------*/
4175 static void genGoto (iCode *ic)
4178 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4179 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4183 /*-----------------------------------------------------------------*/
4184 /* genMultbits :- multiplication of bits */
4185 /*-----------------------------------------------------------------*/
4186 static void genMultbits (operand *left,
4192 if(!pic16_sameRegs(AOP(result),AOP(right)))
4193 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4195 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4196 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4197 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4202 /*-----------------------------------------------------------------*/
4203 /* genMultOneByte : 8 bit multiplication & division */
4204 /*-----------------------------------------------------------------*/
4205 static void genMultOneByte (operand *left,
4211 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4212 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4214 /* (if two literals, the value is computed before) */
4215 /* if one literal, literal on the right */
4216 if (AOP_TYPE(left) == AOP_LIT){
4222 /* size is already checked in genMult == 1 */
4223 // size = AOP_SIZE(result);
4225 if (AOP_TYPE(right) == AOP_LIT){
4226 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4227 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4228 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4229 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4231 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4232 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4233 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4234 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4237 pic16_genMult8X8_n (left, right,result);
4241 /*-----------------------------------------------------------------*/
4242 /* genMultOneWord : 16 bit multiplication */
4243 /*-----------------------------------------------------------------*/
4244 static void genMultOneWord (operand *left,
4249 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4250 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4252 /* (if two literals, the value is computed before)
4253 * if one literal, literal on the right */
4254 if (AOP_TYPE(left) == AOP_LIT){
4260 /* size is checked already == 2 */
4261 // size = AOP_SIZE(result);
4263 if (AOP_TYPE(right) == AOP_LIT) {
4264 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4265 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4266 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4267 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4269 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4270 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4271 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4272 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4275 pic16_genMult16X16_16(left, right,result);
4280 /*-----------------------------------------------------------------*/
4281 /* genMultOneLong : 32 bit multiplication */
4282 /*-----------------------------------------------------------------*/
4283 static void genMultOneLong (operand *left,
4288 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4289 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4291 /* (if two literals, the value is computed before)
4292 * if one literal, literal on the right */
4293 if (AOP_TYPE(left) == AOP_LIT){
4299 /* size is checked already == 4 */
4300 // size = AOP_SIZE(result);
4302 if (AOP_TYPE(right) == AOP_LIT) {
4303 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4304 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4305 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4306 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4308 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4309 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4310 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4311 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4314 pic16_genMult32X32_32(left, right,result);
4320 /*-----------------------------------------------------------------*/
4321 /* genMult - generates code for multiplication */
4322 /*-----------------------------------------------------------------*/
4323 static void genMult (iCode *ic)
4325 operand *left = IC_LEFT(ic);
4326 operand *right = IC_RIGHT(ic);
4327 operand *result= IC_RESULT(ic);
4330 /* assign the amsops */
4331 pic16_aopOp (left,ic,FALSE);
4332 pic16_aopOp (right,ic,FALSE);
4333 pic16_aopOp (result,ic,TRUE);
4335 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4337 /* special cases first *
4339 if (AOP_TYPE(left) == AOP_CRY
4340 && AOP_TYPE(right)== AOP_CRY) {
4341 genMultbits(left,right,result);
4345 /* if both are of size == 1 */
4346 if(AOP_SIZE(left) == 1
4347 && AOP_SIZE(right) == 1) {
4348 genMultOneByte(left,right,result);
4353 /* if both are of size == 2 */
4354 if(AOP_SIZE(left) == 2
4355 && AOP_SIZE(right) == 2) {
4356 genMultOneWord(left, right, result);
4360 /* if both are of size == 4 */
4361 if(AOP_SIZE(left) == 4
4362 && AOP_SIZE(right) == 4) {
4363 genMultOneLong(left, right, result);
4368 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4369 assert( !"Multiplication should have been transformed into function call!" );
4371 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4374 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4375 /* should have been converted to function call */
4379 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4380 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4381 pic16_freeAsmop(result,NULL,ic,TRUE);
4385 /*-----------------------------------------------------------------*/
4386 /* genDivbits :- division of bits */
4387 /*-----------------------------------------------------------------*/
4388 static void genDivbits (operand *left,
4395 /* the result must be bit */
4396 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4397 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4401 pic16_emitcode("div","ab");
4402 pic16_emitcode("rrc","a");
4403 pic16_aopPut(AOP(result),"c",0);
4406 /*-----------------------------------------------------------------*/
4407 /* genDivOneByte : 8 bit division */
4408 /*-----------------------------------------------------------------*/
4409 static void genDivOneByte (operand *left,
4413 sym_link *opetype = operandType(result);
4418 /* result = divident / divisor
4419 * - divident may be a register or a literal,
4420 * - divisor may be a register or a literal,
4421 * so there are 3 cases (literal / literal is optimized
4422 * by the front-end) to handle.
4423 * In addition we must handle signed and unsigned, which
4424 * result in 6 final different cases -- VR */
4428 size = AOP_SIZE(result) - 1;
4430 /* signed or unsigned */
4431 if (SPEC_USIGN(opetype)) {
4432 pCodeOp *pct1, /* count */
4435 symbol *label1, *label2, *label3;;
4438 /* unsigned is easy */
4440 pct1 = pic16_popGetTempReg(1);
4441 pct2 = pic16_popGetTempReg(1);
4442 pct3 = pic16_popGetTempReg(1);
4444 label1 = newiTempLabel(NULL);
4445 label2 = newiTempLabel(NULL);
4446 label3 = newiTempLabel(NULL);
4448 /* the following algorithm is extracted from divuint.c */
4450 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4451 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4453 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4457 pic16_emitpLabel(label1->key);
4460 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4464 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4468 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4470 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4471 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4473 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4474 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4475 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4477 pic16_emitpLabel( label3->key );
4478 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4479 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4483 pic16_emitpLabel(label2->key);
4484 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4485 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4486 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4488 /* result is in wreg */
4489 if(AOP_TYPE(result) != AOP_ACC)
4490 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4492 pic16_popReleaseTempReg( pct3, 1);
4493 pic16_popReleaseTempReg( pct2, 1);
4494 pic16_popReleaseTempReg( pct1, 1);
4499 /* signed is a little bit more difficult */
4501 /* save the signs of the operands */
4502 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4504 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4505 pic16_emitcode("push","acc"); /* save it on the stack */
4507 /* now sign adjust for both left & right */
4508 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4510 lbl = newiTempLabel(NULL);
4511 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4512 pic16_emitcode("cpl","a");
4513 pic16_emitcode("inc","a");
4514 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4515 pic16_emitcode("mov","b,a");
4517 /* sign adjust left side */
4518 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4521 lbl = newiTempLabel(NULL);
4522 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4523 pic16_emitcode("cpl","a");
4524 pic16_emitcode("inc","a");
4525 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4527 /* now the division */
4528 pic16_emitcode("div","ab");
4529 /* we are interested in the lower order
4531 pic16_emitcode("mov","b,a");
4532 lbl = newiTempLabel(NULL);
4533 pic16_emitcode("pop","acc");
4534 /* if there was an over flow we don't
4535 adjust the sign of the result */
4536 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4537 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4539 pic16_emitcode("clr","a");
4540 pic16_emitcode("subb","a,b");
4541 pic16_emitcode("mov","b,a");
4542 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4544 /* now we are done */
4545 pic16_aopPut(AOP(result),"b",0);
4547 pic16_emitcode("mov","c,b.7");
4548 pic16_emitcode("subb","a,acc");
4551 pic16_aopPut(AOP(result),"a",offset++);
4556 /*-----------------------------------------------------------------*/
4557 /* genDiv - generates code for division */
4558 /*-----------------------------------------------------------------*/
4559 static void genDiv (iCode *ic)
4561 operand *left = IC_LEFT(ic);
4562 operand *right = IC_RIGHT(ic);
4563 operand *result= IC_RESULT(ic);
4565 int leftVal = 0, rightVal = 0;
4567 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4570 /* Division is a very lengthy algorithm, so it is better
4571 * to call support routines than inlining algorithm.
4572 * Division functions written here just in case someone
4573 * wants to inline and not use the support libraries -- VR */
4577 /* assign the amsops */
4578 pic16_aopOp (left,ic,FALSE);
4579 pic16_aopOp (right,ic,FALSE);
4580 pic16_aopOp (result,ic,TRUE);
4584 else if (ic->op == '%')
4587 assert( !"invalid operation requested in genDivMod" );
4589 /* get literal values */
4590 if (IS_VALOP(left)) {
4591 leftVal = (int)floatFromVal( OP_VALUE(left) );
4592 assert( leftVal >= -128 && leftVal < 256 );
4593 if (leftVal < 0) { signedLits++; }
4595 if (IS_VALOP(right)) {
4596 rightVal = (int)floatFromVal( OP_VALUE(right) );
4597 assert( rightVal >= -128 && rightVal < 256 );
4598 if (rightVal < 0) { signedLits++; }
4601 /* We should only come here to convert all
4602 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4603 * with exactly one operand being s8_t into
4604 * u8_t x u8_t -> u8_t. All other cases should have been
4605 * turned into calls to support routines beforehand... */
4606 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4607 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4609 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4610 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4612 /* Both operands are signed or negative, use _divschar
4613 * instead of _divuchar */
4614 pushaop(AOP(right), 0);
4615 pushaop(AOP(left), 0);
4617 /* call _divschar */
4618 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4622 sym = newSymbol( functions[op][0], 0 );
4624 strcpy(sym->rname, functions[op][0]);
4625 checkAddSym(&externs, sym);
4629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4630 if (AOP_SIZE(result) > 1)
4632 pic16_emitpcode(POC_MOVFF,
4633 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4634 pic16_popGet(AOP(result), 1)));
4636 pic16_addSign(result, 2, 1);
4639 /* clean up stack */
4640 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4641 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4646 /* push right operand */
4647 if (IS_VALOP(right)) {
4649 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4652 pushaop(AOP(right), 0);
4654 } else if (!IS_UNSIGNED(operandType(right))) {
4655 pic16_mov2w(AOP(right), 0);
4656 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4657 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4658 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4661 pushaop(AOP(right), 0);
4664 /* push left operand */
4665 if (IS_VALOP(left)) {
4667 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4670 pushaop(AOP(left), 0);
4672 } else if (!IS_UNSIGNED(operandType(left))) {
4673 pic16_mov2w(AOP(left),0);
4674 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4675 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4676 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4679 pushaop(AOP(left), 0);
4682 /* call _divuchar */
4683 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4687 sym = newSymbol( functions[op][1], 0 );
4689 strcpy(sym->rname, functions[op][1]);
4690 checkAddSym(&externs, sym);
4693 /* Revert negation(s) from above.
4694 * This is inefficient: if both operands are negative, this
4695 * should not touch WREG. However, determining that exactly
4696 * one operand was negated costs at least 3 instructions,
4697 * so there is nothing to be gained here, is there?
4699 * I negate WREG because either operand might share registers with
4700 * result, so assigning first might destroy an operand. */
4702 /* For the modulus operator, (a/b)*b == a shall hold.
4703 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4704 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4705 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4706 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4707 * Only invert the result if the left operand is negative (sigh).
4709 if (AOP_SIZE(result) <= 1 || !negated)
4713 if (IS_VALOP(right)) {
4715 /* we negated this operand above */
4716 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4718 } else if (!IS_UNSIGNED(operandType(right))) {
4719 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4720 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4724 if (IS_VALOP(left)) {
4726 /* we negated this operand above */
4727 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4729 } else if (!IS_UNSIGNED(operandType(left))) {
4730 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4731 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4734 /* Move result to destination. */
4735 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4737 /* Zero-extend: no operand was signed (or result is just a byte). */
4738 pic16_addSign(result, 1, 0);
4740 assert( AOP_SIZE(result) > 1 );
4741 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4744 if (IS_VALOP(right)) {
4746 /* we negated this operand above */
4747 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4749 } else if (!IS_UNSIGNED(operandType(right))) {
4750 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4751 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4755 if (IS_VALOP(left)) {
4757 /* we negated this operand above */
4758 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4760 } else if (!IS_UNSIGNED(operandType(left))) {
4761 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4762 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4765 /* Move result to destination. */
4766 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4768 /* Negate result if required. */
4769 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4770 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4773 pic16_addSign(result, 2, 1);
4776 /* clean up stack */
4777 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4778 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4783 /* special cases first */
4785 if (AOP_TYPE(left) == AOP_CRY &&
4786 AOP_TYPE(right)== AOP_CRY) {
4787 genDivbits(left,right,result);
4791 /* if both are of size == 1 */
4792 if (AOP_SIZE(left) == 1 &&
4793 AOP_SIZE(right) == 1 ) {
4794 genDivOneByte(left,right,result);
4799 /* should have been converted to function call */
4802 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4803 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804 pic16_freeAsmop(result,NULL,ic,TRUE);
4808 /*-----------------------------------------------------------------*/
4809 /* genModbits :- modulus of bits */
4810 /*-----------------------------------------------------------------*/
4811 static void genModbits (operand *left,
4819 werror(W_POSSBUG2, __FILE__, __LINE__);
4820 /* the result must be bit */
4821 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4822 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4826 pic16_emitcode("div","ab");
4827 pic16_emitcode("mov","a,b");
4828 pic16_emitcode("rrc","a");
4829 pic16_aopPut(AOP(result),"c",0);
4832 /*-----------------------------------------------------------------*/
4833 /* genModOneByte : 8 bit modulus */
4834 /*-----------------------------------------------------------------*/
4835 static void genModOneByte (operand *left,
4839 sym_link *opetype = operandType(result);
4844 werror(W_POSSBUG2, __FILE__, __LINE__);
4846 /* signed or unsigned */
4847 if (SPEC_USIGN(opetype)) {
4848 /* unsigned is easy */
4849 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4850 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4852 pic16_emitcode("div","ab");
4853 pic16_aopPut(AOP(result),"b",0);
4857 /* signed is a little bit more difficult */
4859 /* save the signs of the operands */
4860 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4863 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4864 pic16_emitcode("push","acc"); /* save it on the stack */
4866 /* now sign adjust for both left & right */
4867 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4870 lbl = newiTempLabel(NULL);
4871 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4872 pic16_emitcode("cpl","a");
4873 pic16_emitcode("inc","a");
4874 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4875 pic16_emitcode("mov","b,a");
4877 /* sign adjust left side */
4878 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4881 lbl = newiTempLabel(NULL);
4882 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4883 pic16_emitcode("cpl","a");
4884 pic16_emitcode("inc","a");
4885 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4887 /* now the multiplication */
4888 pic16_emitcode("div","ab");
4889 /* we are interested in the lower order
4891 lbl = newiTempLabel(NULL);
4892 pic16_emitcode("pop","acc");
4893 /* if there was an over flow we don't
4894 adjust the sign of the result */
4895 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4896 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4898 pic16_emitcode("clr","a");
4899 pic16_emitcode("subb","a,b");
4900 pic16_emitcode("mov","b,a");
4901 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4903 /* now we are done */
4904 pic16_aopPut(AOP(result),"b",0);
4909 /*-----------------------------------------------------------------*/
4910 /* genMod - generates code for division */
4911 /*-----------------------------------------------------------------*/
4912 static void genMod (iCode *ic)
4914 /* Task deferred to genDiv */
4917 operand *left = IC_LEFT(ic);
4918 operand *right = IC_RIGHT(ic);
4919 operand *result= IC_RESULT(ic);
4923 /* assign the amsops */
4924 pic16_aopOp (left,ic,FALSE);
4925 pic16_aopOp (right,ic,FALSE);
4926 pic16_aopOp (result,ic,TRUE);
4928 /* special cases first */
4930 if (AOP_TYPE(left) == AOP_CRY &&
4931 AOP_TYPE(right)== AOP_CRY) {
4932 genModbits(left,right,result);
4936 /* if both are of size == 1 */
4937 if (AOP_SIZE(left) == 1 &&
4938 AOP_SIZE(right) == 1 ) {
4939 genModOneByte(left,right,result);
4943 /* should have been converted to function call */
4947 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4948 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4949 pic16_freeAsmop(result,NULL,ic,TRUE);
4953 /*-----------------------------------------------------------------*/
4954 /* genIfxJump :- will create a jump depending on the ifx */
4955 /*-----------------------------------------------------------------*/
4957 note: May need to add parameter to indicate when a variable is in bit space.
4959 static void genIfxJump (iCode *ic, char *jval)
4963 /* if true label then we jump if condition
4965 if ( IC_TRUE(ic) ) {
4967 if(strcmp(jval,"a") == 0)
4969 else if (strcmp(jval,"c") == 0)
4972 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4973 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4977 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4981 /* false label is present */
4982 if(strcmp(jval,"a") == 0)
4984 else if (strcmp(jval,"c") == 0)
4987 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4988 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4991 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4992 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4997 /* mark the icode as generated */
5001 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5005 /* if true label then we jump if condition
5007 if ( IC_TRUE(ic) ) {
5008 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5009 pic16_emitpcode(POC_BTFSC, jop);
5011 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5012 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5015 /* false label is present */
5016 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5017 pic16_emitpcode(POC_BTFSS, jop);
5019 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5020 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5024 /* mark the icode as generated */
5031 /*-----------------------------------------------------------------*/
5033 /*-----------------------------------------------------------------*/
5034 static void genSkip(iCode *ifx,int status_bit)
5036 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5040 if ( IC_TRUE(ifx) ) {
5041 switch(status_bit) {
5056 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5057 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5061 switch(status_bit) {
5075 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5076 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5083 /*-----------------------------------------------------------------*/
5085 /*-----------------------------------------------------------------*/
5086 static void genSkipc(resolvedIfx *rifx)
5088 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5098 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5099 rifx->generated = 1;
5102 #if !(USE_SIMPLE_GENCMP)
5103 /*-----------------------------------------------------------------*/
5105 /*-----------------------------------------------------------------*/
5106 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5108 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5113 if( (rifx->condition ^ invert_condition) & 1)
5118 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5119 rifx->generated = 1;
5124 /*-----------------------------------------------------------------*/
5126 /*-----------------------------------------------------------------*/
5127 static void genSkipz(iCode *ifx, int condition)
5138 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5140 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5143 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5145 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5150 #if !(USE_SIMPLE_GENCMP)
5151 /*-----------------------------------------------------------------*/
5153 /*-----------------------------------------------------------------*/
5154 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5160 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5162 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5165 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5166 rifx->generated = 1;
5171 /*-----------------------------------------------------------------*/
5172 /* genChkZeroes :- greater or less than comparison */
5173 /* For each byte in a literal that is zero, inclusive or the */
5174 /* the corresponding byte in the operand with W */
5175 /* returns true if any of the bytes are zero */
5176 /*-----------------------------------------------------------------*/
5177 static int genChkZeroes(operand *op, int lit, int size)
5184 i = (lit >> (size*8)) & 0xff;
5188 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5190 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5200 /*-----------------------------------------------------------------*/
5201 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5202 /* aop (if it's NOT a literal) or from lit (if */
5203 /* aop is a literal) */
5204 /*-----------------------------------------------------------------*/
5205 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5206 if (aop->type == AOP_LIT) {
5207 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5209 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5213 /*-----------------------------------------------------------------*/
5214 /* genCmp :- greater or less than comparison */
5215 /*-----------------------------------------------------------------*/
5217 #if USE_SIMPLE_GENCMP /* { */
5219 /* genCmp performs a left < right comparison, stores
5220 * the outcome in result (if != NULL) and generates
5221 * control flow code for the ifx (if != NULL).
5223 * This version leaves in sequences like
5224 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5225 * which should be optmized by the peephole
5226 * optimizer - RN 2005-01-01 */
5227 static void genCmp (operand *left,operand *right,
5228 operand *result, iCode *ifx, int sign)
5241 assert (left && right);
5242 assert (AOP_SIZE(left) == AOP_SIZE(right));
5244 size = AOP_SIZE(right) - 1;
5245 mask = (0x100UL << (size*8)) - 1;
5246 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5251 resolveIfx (&rIfx, ifx);
5253 /* handle for special cases */
5254 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5257 /**********************************************************************
5258 * handle bits - bit compares are promoted to int compares seemingly! *
5259 **********************************************************************/
5261 // THIS IS COMPLETELY UNTESTED!
5262 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5263 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5264 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5265 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5268 // 1 < {0,1} is false --> clear C by skipping the next instruction
5269 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5270 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5271 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5272 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5273 emitCLRC; // only skipped for left=0 && right=1
5275 goto correct_result_in_carry;
5279 /*************************************************
5280 * make sure that left is register (or the like) *
5281 *************************************************/
5282 if (!isAOP_REGlike(left)) {
5283 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5284 assert (isAOP_LIT(left));
5285 assert (isAOP_REGlike(right));
5286 // swap left and right
5287 // left < right <==> right > left <==> (right >= left + 1)
5288 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5290 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5291 // MAXVALUE < right? always false
5292 if (performedLt) emitCLRC; else emitSETC;
5293 goto correct_result_in_carry;
5296 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5297 // that's why we handled it above.
5304 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5305 } else if (isAOP_LIT(right)) {
5306 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5309 assert (isAOP_REGlike(left)); // left must be register or the like
5310 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5312 /*************************************************
5313 * special cases go here *
5314 *************************************************/
5316 if (isAOP_LIT(right)) {
5318 // unsigned comparison to a literal
5319 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5321 // unsigned left < 0? always false
5322 if (performedLt) emitCLRC; else emitSETC;
5323 goto correct_result_in_carry;
5326 // signed comparison to a literal
5327 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5328 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5329 // signed left < 0x80000000? always false
5330 if (performedLt) emitCLRC; else emitSETC;
5331 goto correct_result_in_carry;
5332 } else if (lit == 0) {
5333 // compare left < 0; set CARRY if SIGNBIT(left) is set
5334 if (performedLt) emitSETC; else emitCLRC;
5335 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5336 if (performedLt) emitCLRC; else emitSETC;
5337 goto correct_result_in_carry;
5340 } // right is literal
5342 /*************************************************
5343 * perform a general case comparison *
5344 * make sure we get CARRY==1 <==> left >= right *
5345 *************************************************/
5346 // compare most significant bytes
5347 //DEBUGpc ("comparing bytes at offset %d", size);
5349 // unsigned comparison
5350 mov2w_regOrLit (AOP(right), lit, size);
5351 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5353 // signed comparison
5354 // (add 2^n to both operands then perform an unsigned comparison)
5355 if (isAOP_LIT(right)) {
5356 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5357 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5359 if (litbyte == 0x80) {
5360 // left >= 0x80 -- always true, but more bytes to come
5361 pic16_mov2w (AOP(left), size);
5362 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5365 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5366 pic16_mov2w (AOP(left), size);
5367 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5368 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5371 /* using PRODL as a temporary register here */
5372 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5373 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5374 pic16_mov2w (AOP(left), size);
5375 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5376 pic16_emitpcode (POC_MOVWF, pctemp);
5377 pic16_mov2w (AOP(right), size);
5378 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5379 pic16_emitpcode (POC_SUBFW, pctemp);
5380 //pic16_popReleaseTempReg(pctemp, 1);
5384 // compare remaining bytes (treat as unsigned case from above)
5385 templbl = newiTempLabel ( NULL );
5388 //DEBUGpc ("comparing bytes at offset %d", offs);
5389 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5390 mov2w_regOrLit (AOP(right), lit, offs);
5391 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5393 pic16_emitpLabel (templbl->key);
5394 goto result_in_carry;
5398 /****************************************************
5399 * now CARRY contains the result of the comparison: *
5400 * SUBWF sets CARRY iff *
5401 * F-W >= 0 <==> F >= W <==> !(F < W) *
5402 * (F=left, W=right) *
5403 ****************************************************/
5406 if (result && AOP_TYPE(result) != AOP_CRY) {
5407 // value will be stored
5410 // value wil only be used in the following genSkipc()
5411 rIfx.condition ^= 1;
5415 correct_result_in_carry:
5417 // assign result to variable (if neccessary)
5418 if (result && AOP_TYPE(result) != AOP_CRY) {
5419 //DEBUGpc ("assign result");
5420 size = AOP_SIZE(result);
5422 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5424 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5427 // perform conditional jump
5429 //DEBUGpc ("generate control flow");
5438 static void genCmp (operand *left,operand *right,
5439 operand *result, iCode *ifx, int sign)
5441 int size; //, offset = 0 ;
5442 unsigned long lit = 0L,i = 0;
5443 resolvedIfx rFalseIfx;
5444 // resolvedIfx rTrueIfx;
5446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5449 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5450 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5456 resolveIfx(&rFalseIfx,ifx);
5457 truelbl = newiTempLabel(NULL);
5458 size = max(AOP_SIZE(left),AOP_SIZE(right));
5460 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5464 /* if literal is on the right then swap with left */
5465 if ((AOP_TYPE(right) == AOP_LIT)) {
5466 operand *tmp = right ;
5467 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5468 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5471 lit = (lit - 1) & mask;
5474 rFalseIfx.condition ^= 1;
5477 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5478 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5482 //if(IC_TRUE(ifx) == NULL)
5483 /* if left & right are bit variables */
5484 if (AOP_TYPE(left) == AOP_CRY &&
5485 AOP_TYPE(right) == AOP_CRY ) {
5486 assert (0 && "bit variables used in genCmp");
5487 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5488 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5490 /* subtract right from left if at the
5491 end the carry flag is set then we know that
5492 left is greater than right */
5494 symbol *lbl = newiTempLabel(NULL);
5497 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5498 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5502 if(AOP_TYPE(right) == AOP_LIT) {
5504 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5506 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5513 genSkipCond(&rFalseIfx,left,size-1,7);
5515 /* no need to compare to 0...*/
5516 /* NOTE: this is a de-generate compare that most certainly
5517 * creates some dead code. */
5518 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5520 if(ifx) ifx->generated = 1;
5527 //i = (lit >> (size*8)) & 0xff;
5528 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5530 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5532 i = ((0-lit) & 0xff);
5535 /* lit is 0x7f, all signed chars are less than
5536 * this except for 0x7f itself */
5537 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5538 genSkipz2(&rFalseIfx,0);
5540 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5541 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5542 genSkipc(&rFalseIfx);
5547 genSkipz2(&rFalseIfx,1);
5549 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5550 genSkipc(&rFalseIfx);
5554 if(ifx) ifx->generated = 1;
5558 /* chars are out of the way. now do ints and longs */
5561 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5568 genSkipCond(&rFalseIfx,left,size,7);
5569 if(ifx) ifx->generated = 1;
5574 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5576 //rFalseIfx.condition ^= 1;
5577 //genSkipCond(&rFalseIfx,left,size,7);
5578 //rFalseIfx.condition ^= 1;
5580 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5581 if(rFalseIfx.condition)
5582 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5584 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5586 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5587 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5588 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5591 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5593 if(rFalseIfx.condition) {
5595 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5601 genSkipc(&rFalseIfx);
5602 pic16_emitpLabel(truelbl->key);
5603 if(ifx) ifx->generated = 1;
5610 if( (lit & 0xff) == 0) {
5611 /* lower byte is zero */
5612 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5613 i = ((lit >> 8) & 0xff) ^0x80;
5614 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5615 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5616 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5617 genSkipc(&rFalseIfx);
5620 if(ifx) ifx->generated = 1;
5625 /* Special cases for signed longs */
5626 if( (lit & 0xffffff) == 0) {
5627 /* lower byte is zero */
5628 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5629 i = ((lit >> 8*3) & 0xff) ^0x80;
5630 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5631 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5632 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5633 genSkipc(&rFalseIfx);
5636 if(ifx) ifx->generated = 1;
5644 if(lit & (0x80 << (size*8))) {
5645 /* lit is negative */
5646 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5648 //genSkipCond(&rFalseIfx,left,size,7);
5650 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5652 if(rFalseIfx.condition)
5653 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5655 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5659 /* lit is positive */
5660 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5661 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5662 if(rFalseIfx.condition)
5663 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5665 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5670 This works, but is only good for ints.
5671 It also requires a "known zero" register.
5672 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5673 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5674 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5675 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5676 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5677 genSkipc(&rFalseIfx);
5679 pic16_emitpLabel(truelbl->key);
5680 if(ifx) ifx->generated = 1;
5684 /* There are no more special cases, so perform a general compare */
5686 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5687 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5693 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5695 //rFalseIfx.condition ^= 1;
5696 genSkipc(&rFalseIfx);
5698 pic16_emitpLabel(truelbl->key);
5700 if(ifx) ifx->generated = 1;
5707 /* sign is out of the way. So now do an unsigned compare */
5708 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5711 /* General case - compare to an unsigned literal on the right.*/
5713 i = (lit >> (size*8)) & 0xff;
5714 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5715 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5717 i = (lit >> (size*8)) & 0xff;
5720 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5722 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5724 /* this byte of the lit is zero,
5725 *if it's not the last then OR in the variable */
5727 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5732 pic16_emitpLabel(lbl->key);
5733 // pic16_emitpLabel(truelbl->key);
5734 //if(emitFinalCheck)
5735 genSkipc(&rFalseIfx);
5737 pic16_emitpLabel(truelbl->key);
5739 if(ifx) ifx->generated = 1;
5746 if(AOP_TYPE(left) == AOP_LIT) {
5747 //symbol *lbl = newiTempLabel(NULL);
5749 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5752 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5755 if((lit == 0) && (sign == 0)){
5758 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5760 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5762 genSkipz2(&rFalseIfx,0);
5763 if(ifx) ifx->generated = 1;
5770 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5771 /* degenerate compare can never be true */
5772 if(rFalseIfx.condition == 0)
5773 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5775 if(ifx) ifx->generated = 1;
5780 /* signed comparisons to a literal byte */
5782 int lp1 = (lit+1) & 0xff;
5784 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5787 rFalseIfx.condition ^= 1;
5788 genSkipCond(&rFalseIfx,right,0,7);
5791 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5792 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5793 genSkipz2(&rFalseIfx,1);
5796 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5797 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5798 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5799 rFalseIfx.condition ^= 1;
5800 genSkipc(&rFalseIfx);
5804 /* unsigned comparisons to a literal byte */
5806 switch(lit & 0xff ) {
5808 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5809 genSkipz2(&rFalseIfx,0);
5812 rFalseIfx.condition ^= 1;
5813 genSkipCond(&rFalseIfx,right,0,7);
5817 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5818 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5820 rFalseIfx.condition ^= 1;
5821 if (AOP_TYPE(result) == AOP_CRY)
5822 genSkipc(&rFalseIfx);
5824 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5825 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5831 if(ifx) ifx->generated = 1;
5832 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5838 /* Size is greater than 1 */
5846 /* this means lit = 0xffffffff, or -1 */
5849 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5850 rFalseIfx.condition ^= 1;
5851 genSkipCond(&rFalseIfx,right,size,7);
5852 if(ifx) ifx->generated = 1;
5854 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5863 if(rFalseIfx.condition) {
5864 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5865 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5868 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5870 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5874 if(rFalseIfx.condition) {
5875 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5876 pic16_emitpLabel(truelbl->key);
5878 rFalseIfx.condition ^= 1;
5879 genSkipCond(&rFalseIfx,right,s,7);
5882 if(ifx) ifx->generated = 1;
5884 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5890 if((size == 1) && (0 == (lp1&0xff))) {
5891 /* lower byte of signed word is zero */
5892 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5893 i = ((lp1 >> 8) & 0xff) ^0x80;
5894 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5895 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5896 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5898 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5900 if(ifx) ifx->generated = 1;
5903 rFalseIfx.condition ^= 1;
5904 genSkipc(&rFalseIfx);
5905 if(ifx) ifx->generated = 1;
5911 if(lit & (0x80 << (size*8))) {
5912 /* Lit is less than zero */
5913 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5914 //rFalseIfx.condition ^= 1;
5915 //genSkipCond(&rFalseIfx,left,size,7);
5916 //rFalseIfx.condition ^= 1;
5917 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5918 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5920 if(rFalseIfx.condition)
5921 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5923 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5927 /* Lit is greater than or equal to zero */
5928 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5929 //rFalseIfx.condition ^= 1;
5930 //genSkipCond(&rFalseIfx,right,size,7);
5931 //rFalseIfx.condition ^= 1;
5933 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5934 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5936 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5937 if(rFalseIfx.condition)
5938 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5940 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5944 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5945 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5951 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5953 rFalseIfx.condition ^= 1;
5954 //rFalseIfx.condition = 1;
5955 genSkipc(&rFalseIfx);
5957 pic16_emitpLabel(truelbl->key);
5959 if(ifx) ifx->generated = 1;
5962 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5969 /* compare word or long to an unsigned literal on the right.*/
5974 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5977 break; /* handled above */
5980 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5982 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5983 genSkipz2(&rFalseIfx,0);
5987 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5989 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5992 if(rFalseIfx.condition)
5993 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5995 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5998 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5999 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6001 rFalseIfx.condition ^= 1;
6002 genSkipc(&rFalseIfx);
6005 pic16_emitpLabel(truelbl->key);
6007 if(ifx) ifx->generated = 1;
6009 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6017 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6018 i = (lit >> (size*8)) & 0xff;
6020 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6021 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6024 i = (lit >> (size*8)) & 0xff;
6027 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6029 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6031 /* this byte of the lit is zero,
6032 * if it's not the last then OR in the variable */
6034 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6039 pic16_emitpLabel(lbl->key);
6041 rFalseIfx.condition ^= 1;
6043 genSkipc(&rFalseIfx);
6047 pic16_emitpLabel(truelbl->key);
6048 if(ifx) ifx->generated = 1;
6050 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6056 /* Compare two variables */
6058 DEBUGpic16_emitcode(";sign","%d",sign);
6062 /* Sigh. thus sucks... */
6066 pctemp = pic16_popGetTempReg(1);
6067 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6068 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6070 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6071 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6072 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6073 pic16_popReleaseTempReg(pctemp, 1);
6075 /* Signed char comparison */
6076 /* Special thanks to Nikolai Golovchenko for this snippet */
6077 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6078 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6079 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6080 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6081 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6082 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6084 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6085 genSkipc(&rFalseIfx);
6087 if(ifx) ifx->generated = 1;
6089 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6097 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6098 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6102 /* The rest of the bytes of a multi-byte compare */
6106 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6109 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6110 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6115 pic16_emitpLabel(lbl->key);
6117 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6118 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6119 (AOP_TYPE(result) == AOP_REG)) {
6120 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6121 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6123 genSkipc(&rFalseIfx);
6125 //genSkipc(&rFalseIfx);
6126 if(ifx) ifx->generated = 1;
6129 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6137 if ((AOP_TYPE(result) != AOP_CRY)
6138 && AOP_SIZE(result)) {
6139 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6141 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6143 pic16_outBitC(result);
6145 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6146 /* if the result is used in the next
6147 ifx conditional branch then generate
6148 code a little differently */
6150 genIfxJump (ifx,"c");
6152 pic16_outBitC(result);
6153 /* leave the result in acc */
6158 #elif 0 /* VR version of genCmp() */ /* } else { */
6160 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6161 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6162 operand *result, int offset, int invert_op)
6166 /* check condition, > or < ?? */
6167 if(rIfx->condition != 0)invert_op ^= 1;
6169 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6171 if(!ifx)invert_op ^= 1;
6173 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6174 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6177 if(!invert_op)return POC_CPFSGT;
6178 else return POC_CPFSLT;
6181 static int compareAopfirstpass=1;
6183 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6184 operand *oper, int offset, operand *result,
6185 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6191 /* invert if there is a result to be loaded, in order to fit,
6192 * SETC/CLRC sequence */
6193 if(AOP_SIZE(result))invert_op ^= 1;
6195 // if(sign && !offset)invert_op ^= 1;
6197 // if(sign)invert_op ^= 1;
6199 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6201 if(AOP_SIZE(result) && compareAopfirstpass) {
6204 pic16_emitpcode(POC_SETF, pcop2);
6209 pic16_emitpcode(POC_CLRF, pcop2);
6215 compareAopfirstpass = 0;
6217 /* there is a bug when comparing operands with size > 1,
6218 * because higher bytes can be equal and test should be performed
6219 * to the next lower byte, current algorithm, considers operands
6220 * inequal in these cases! -- VR 20041107 */
6224 pic16_emitpcode(op, pcop);
6226 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6229 if((!sign || !offset) && AOP_SIZE(result)) {
6232 pic16_emitpcode(POC_CLRF, pcop2);
6237 pic16_emitpcode(POC_SETF, pcop2);
6242 /* don't emit final branch (offset == 0) */
6246 pic16_emitpcode(POC_RRCF, pcop2);
6248 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6251 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6252 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6253 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6255 truelbl = newiTempLabel( NULL );
6256 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6257 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6258 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6260 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6261 pic16_emitpLabel(truelbl->key);
6263 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6268 static void genCmp (operand *left, operand *right,
6269 operand *result, iCode *ifx, int sign)
6273 resolvedIfx rFalseIfx;
6274 symbol *falselbl, *tlbl;
6278 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6280 resolveIfx(&rFalseIfx, ifx);
6281 size = max(AOP_SIZE(left), AOP_SIZE(right));
6283 /* if left & right are bit variables */
6284 if(AOP_TYPE(left) == AOP_CRY
6285 && AOP_TYPE(right) == AOP_CRY ) {
6287 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6288 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6290 werror(W_POSSBUG2, __FILE__, __LINE__);
6294 /* if literal is on the right then swap with left */
6295 if((AOP_TYPE(right) == AOP_LIT)) {
6296 operand *tmp = right ;
6297 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6299 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6301 // lit = (lit - 1) & mask;
6304 rFalseIfx.condition ^= 1; /* reverse compare */
6306 if ((AOP_TYPE(left) == AOP_LIT)) {
6307 /* float compares are handled by support functions */
6308 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6311 /* actual comparing algorithm */
6312 // size = AOP_SIZE( right );
6314 falselbl = newiTempLabel( NULL );
6315 if(AOP_TYPE(left) == AOP_LIT) {
6316 /* compare to literal */
6317 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6320 pCodeOp *pct, *pct2;
6323 /* signed compare */
6324 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6326 /* using PRODL:PRODH as a temporary register here */
6327 pct = pic16_popCopyReg(&pic16_pc_prodl);
6328 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6329 tlbl = newiTempLabel( NULL );
6331 /* first compare signs:
6332 * a. if both are positive, compare just like unsigned
6333 * b. if both are negative, invert cmpop, compare just like unsigned
6334 * c. if different signs, determine the result directly */
6340 tlbl1 = newiTempLabel( NULL );
6341 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6345 /* literal is zero or positive:
6346 * a. if carry is zero, too, continue compare,
6347 * b. if carry is set, then continue depending on cmpop ^ condition:
6348 * 1. '<' return false (literal < variable),
6349 * 2. '>' return true (literal > variable) */
6350 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6351 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6354 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6355 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6359 /* literal is negative:
6360 * a. if carry is set, too, continue compare,
6361 * b. if carry is zero, then continue depending on cmpop ^ condition:
6362 * 1. '<' return true (literal < variable),
6363 * 2. '>' return false (literal > variable) */
6364 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6365 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6367 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6368 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6373 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6375 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6376 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6381 pic16_emitpLabel( tlbl1->key );
6384 compareAopfirstpass=1;
6385 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6386 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6387 // pic16_emitpcode(POC_MOVWF, pct);
6389 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6390 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6391 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6392 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6396 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6397 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6398 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6399 // pic16_emitpcode(POC_MOVWF, pct);
6401 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6402 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6403 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6404 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6405 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6408 if(ifx)ifx->generated = 1;
6410 if(AOP_SIZE(result)) {
6411 pic16_emitpLabel(tlbl->key);
6412 pic16_emitpLabel(falselbl->key);
6413 pic16_outBitOp( result, pct2 );
6415 pic16_emitpLabel(tlbl->key);
6419 /* unsigned compare */
6420 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6422 compareAopfirstpass=1;
6425 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6426 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6429 if(ifx)ifx->generated = 1;
6431 if(AOP_SIZE(result)) {
6432 pic16_emitpLabel(falselbl->key);
6433 pic16_outBitC( result );
6438 /* compare registers */
6439 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6443 pCodeOp *pct, *pct2;
6445 /* signed compare */
6446 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6448 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6449 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6450 tlbl = newiTempLabel( NULL );
6452 compareAopfirstpass=1;
6455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6456 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6457 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6458 pic16_emitpcode(POC_MOVWF, pct);
6460 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6461 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6462 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6464 /* WREG already holds left + 0x80 */
6465 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6468 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6469 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6470 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6471 pic16_emitpcode(POC_MOVWF, pct);
6473 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6474 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6475 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6477 /* WREG already holds left + 0x80 */
6478 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6479 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6482 if(ifx)ifx->generated = 1;
6484 if(AOP_SIZE(result)) {
6485 pic16_emitpLabel(tlbl->key);
6486 pic16_emitpLabel(falselbl->key);
6487 pic16_outBitOp( result, pct2 );
6489 pic16_emitpLabel(tlbl->key);
6493 /* unsigned compare */
6494 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6496 compareAopfirstpass=1;
6499 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6500 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6504 if(ifx)ifx->generated = 1;
6505 if(AOP_SIZE(result)) {
6507 pic16_emitpLabel(falselbl->key);
6508 pic16_outBitC( result );
6519 /*-----------------------------------------------------------------*/
6520 /* genCmpGt :- greater than comparison */
6521 /*-----------------------------------------------------------------*/
6522 static void genCmpGt (iCode *ic, iCode *ifx)
6524 operand *left, *right, *result;
6525 sym_link *letype , *retype;
6531 right= IC_RIGHT(ic);
6532 result = IC_RESULT(ic);
6534 letype = getSpec(operandType(left));
6535 retype =getSpec(operandType(right));
6536 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6537 /* assign the amsops */
6538 pic16_aopOp (left,ic,FALSE);
6539 pic16_aopOp (right,ic,FALSE);
6540 pic16_aopOp (result,ic,TRUE);
6542 genCmp(right, left, result, ifx, sign);
6544 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6545 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6546 pic16_freeAsmop(result,NULL,ic,TRUE);
6549 /*-----------------------------------------------------------------*/
6550 /* genCmpLt - less than comparisons */
6551 /*-----------------------------------------------------------------*/
6552 static void genCmpLt (iCode *ic, iCode *ifx)
6554 operand *left, *right, *result;
6555 sym_link *letype , *retype;
6561 right= IC_RIGHT(ic);
6562 result = IC_RESULT(ic);
6564 letype = getSpec(operandType(left));
6565 retype =getSpec(operandType(right));
6566 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6568 /* assign the amsops */
6569 pic16_aopOp (left,ic,FALSE);
6570 pic16_aopOp (right,ic,FALSE);
6571 pic16_aopOp (result,ic,TRUE);
6573 genCmp(left, right, result, ifx, sign);
6575 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6576 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6577 pic16_freeAsmop(result,NULL,ic,TRUE);
6582 // FIXME reenable literal optimisation when the pic16 port is stable
6584 /*-----------------------------------------------------------------*/
6585 /* genc16bit2lit - compare a 16 bit value to a literal */
6586 /*-----------------------------------------------------------------*/
6587 static void genc16bit2lit(operand *op, int lit, int offset)
6591 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6592 if( (lit&0xff) == 0)
6597 switch( BYTEofLONG(lit,i)) {
6599 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6602 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6605 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6608 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6609 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6614 switch( BYTEofLONG(lit,i)) {
6616 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6620 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6624 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6627 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6629 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6638 /*-----------------------------------------------------------------*/
6639 /* gencjneshort - compare and jump if not equal */
6640 /*-----------------------------------------------------------------*/
6641 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6643 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6645 int res_offset = 0; /* the result may be a different size then left or right */
6646 int res_size = AOP_SIZE(result);
6648 symbol *lbl, *lbl_done;
6650 unsigned long lit = 0L;
6651 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6653 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6654 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6656 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6657 resolveIfx(&rIfx,ifx);
6658 lbl = newiTempLabel(NULL);
6659 lbl_done = newiTempLabel(NULL);
6662 /* if the left side is a literal or
6663 if the right is in a pointer register and left
6665 if ((AOP_TYPE(left) == AOP_LIT) ||
6666 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6671 if(AOP_TYPE(right) == AOP_LIT)
6672 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6674 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6675 preserve_result = 1;
6677 if(result && !preserve_result)
6680 for(i = 0; i < AOP_SIZE(result); i++)
6681 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6685 /* if the right side is a literal then anything goes */
6686 if (AOP_TYPE(right) == AOP_LIT &&
6687 AOP_TYPE(left) != AOP_DIR ) {
6690 genc16bit2lit(left, lit, 0);
6692 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6698 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6699 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6701 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6707 if(res_offset < res_size-1)
6715 /* if the right side is in a register or in direct space or
6716 if the left is a pointer register & right is not */
6717 else if (AOP_TYPE(right) == AOP_REG ||
6718 AOP_TYPE(right) == AOP_DIR ||
6719 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6720 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6721 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6722 int lbl_key = lbl->key;
6725 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6726 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6728 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6729 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6730 __FUNCTION__,__LINE__);
6734 /* switch(size) { */
6736 /* genc16bit2lit(left, lit, 0); */
6738 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6743 if((AOP_TYPE(left) == AOP_DIR) &&
6744 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6746 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6747 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6749 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6751 switch (lit & 0xff) {
6753 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6756 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6757 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6758 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6762 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6763 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6764 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6769 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6770 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6775 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6778 if(AOP_TYPE(result) == AOP_CRY) {
6779 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6784 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6786 /* fix me. probably need to check result size too */
6787 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6792 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6793 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6800 if(res_offset < res_size-1)
6805 } else if(AOP_TYPE(right) == AOP_REG &&
6806 AOP_TYPE(left) != AOP_DIR){
6809 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6810 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6811 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6818 if(res_offset < res_size-1)
6823 /* right is a pointer reg need both a & b */
6825 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6827 pic16_emitcode("mov","b,%s",l);
6828 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6829 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6834 if(result && preserve_result)
6837 for(i = 0; i < AOP_SIZE(result); i++)
6838 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6841 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6843 if(result && preserve_result)
6844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6847 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6849 pic16_emitpLabel(lbl->key);
6851 if(result && preserve_result)
6854 for(i = 0; i < AOP_SIZE(result); i++)
6855 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6857 pic16_emitpLabel(lbl_done->key);
6860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6868 /*-----------------------------------------------------------------*/
6869 /* gencjne - compare and jump if not equal */
6870 /*-----------------------------------------------------------------*/
6871 static void gencjne(operand *left, operand *right, iCode *ifx)
6873 symbol *tlbl = newiTempLabel(NULL);
6875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6876 gencjneshort(left, right, lbl);
6878 pic16_emitcode("mov","a,%s",one);
6879 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6880 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6881 pic16_emitcode("clr","a");
6882 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6884 pic16_emitpLabel(lbl->key);
6885 pic16_emitpLabel(tlbl->key);
6891 /*-----------------------------------------------------------------*/
6892 /* is_LitOp - check if operand has to be treated as literal */
6893 /*-----------------------------------------------------------------*/
6894 static bool is_LitOp(operand *op)
6896 return ((AOP_TYPE(op) == AOP_LIT)
6897 || ( (AOP_TYPE(op) == AOP_PCODE)
6898 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6899 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6902 /*-----------------------------------------------------------------*/
6903 /* is_LitAOp - check if operand has to be treated as literal */
6904 /*-----------------------------------------------------------------*/
6905 static bool is_LitAOp(asmop *aop)
6907 return ((aop->type == AOP_LIT)
6908 || ( (aop->type == AOP_PCODE)
6909 && ( (aop->aopu.pcop->type == PO_LITERAL)
6910 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6915 /*-----------------------------------------------------------------*/
6916 /* genCmpEq - generates code for equal to */
6917 /*-----------------------------------------------------------------*/
6918 static void genCmpEq (iCode *ic, iCode *ifx)
6920 operand *left, *right, *result;
6921 symbol *falselbl = newiTempLabel(NULL);
6922 symbol *donelbl = newiTempLabel(NULL);
6924 int preserve_result = 0;
6925 int generate_result = 0;
6927 unsigned long lit = -1;
6931 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6932 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6933 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6935 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6937 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6939 werror(W_POSSBUG2, __FILE__, __LINE__);
6940 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6941 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6945 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6947 operand *tmp = right ;
6952 if (AOP_TYPE(right) == AOP_LIT) {
6953 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6956 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6957 preserve_result = 1;
6959 if(result && AOP_SIZE(result))
6960 generate_result = 1;
6962 if(generate_result && !preserve_result)
6964 for(i = 0; i < AOP_SIZE(result); i++)
6965 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6968 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6969 for(i=0; i < AOP_SIZE(left); i++)
6971 if(AOP_TYPE(left) != AOP_ACC)
6974 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6976 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6978 if(is_LitOp(right)) {
6979 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6980 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6983 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6985 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6990 if(generate_result && preserve_result)
6992 for(i = 0; i < AOP_SIZE(result); i++)
6993 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6997 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6999 if(generate_result && preserve_result)
7000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7002 if(ifx && IC_TRUE(ifx))
7003 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7005 if(ifx && IC_FALSE(ifx))
7006 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7008 pic16_emitpLabel(falselbl->key);
7012 if(ifx && IC_FALSE(ifx))
7013 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7015 if(generate_result && preserve_result)
7017 for(i = 0; i < AOP_SIZE(result); i++)
7018 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7021 pic16_emitpLabel(donelbl->key);
7027 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7028 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7029 pic16_freeAsmop(result,NULL,ic,TRUE);
7035 // old version kept for reference
7037 /*-----------------------------------------------------------------*/
7038 /* genCmpEq - generates code for equal to */
7039 /*-----------------------------------------------------------------*/
7040 static void genCmpEq (iCode *ic, iCode *ifx)
7042 operand *left, *right, *result;
7043 unsigned long lit = 0L;
7045 symbol *falselbl = newiTempLabel(NULL);
7048 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7051 DEBUGpic16_emitcode ("; ifx is non-null","");
7053 DEBUGpic16_emitcode ("; ifx is null","");
7055 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7056 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7057 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7059 size = max(AOP_SIZE(left),AOP_SIZE(right));
7061 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7063 /* if literal, literal on the right or
7064 if the right is in a pointer register and left
7066 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7067 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7068 operand *tmp = right ;
7074 if(ifx && !AOP_SIZE(result)){
7076 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7077 /* if they are both bit variables */
7078 if (AOP_TYPE(left) == AOP_CRY &&
7079 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7080 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7081 if(AOP_TYPE(right) == AOP_LIT){
7082 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7084 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7085 pic16_emitcode("cpl","c");
7086 } else if(lit == 1L) {
7087 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7089 pic16_emitcode("clr","c");
7091 /* AOP_TYPE(right) == AOP_CRY */
7093 symbol *lbl = newiTempLabel(NULL);
7094 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7095 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7096 pic16_emitcode("cpl","c");
7097 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7099 /* if true label then we jump if condition
7101 tlbl = newiTempLabel(NULL);
7102 if ( IC_TRUE(ifx) ) {
7103 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7104 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7106 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7107 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7109 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7112 /* left and right are both bit variables, result is carry */
7115 resolveIfx(&rIfx,ifx);
7117 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7118 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7119 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7120 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7125 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7127 /* They're not both bit variables. Is the right a literal? */
7128 if(AOP_TYPE(right) == AOP_LIT) {
7129 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7134 switch(lit & 0xff) {
7136 if ( IC_TRUE(ifx) ) {
7137 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7139 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7141 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7142 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7146 if ( IC_TRUE(ifx) ) {
7147 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7149 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7151 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7152 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7156 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7158 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7163 /* end of size == 1 */
7167 genc16bit2lit(left,lit,offset);
7170 /* end of size == 2 */
7175 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7176 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7177 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7178 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7181 /* search for patterns that can be optimized */
7183 genc16bit2lit(left,lit,0);
7187 emitSKPZ; // if hi word unequal
7189 emitSKPNZ; // if hi word equal
7191 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7192 genc16bit2lit(left,lit,2);
7195 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7196 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7200 pic16_emitpLabel(falselbl->key);
7209 } else if(AOP_TYPE(right) == AOP_CRY ) {
7210 /* we know the left is not a bit, but that the right is */
7211 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7212 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7213 pic16_popGet(AOP(right),offset));
7214 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7216 /* if the two are equal, then W will be 0 and the Z bit is set
7217 * we could test Z now, or go ahead and check the high order bytes if
7218 * the variable we're comparing is larger than a byte. */
7221 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7223 if ( IC_TRUE(ifx) ) {
7225 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7226 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7229 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7230 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7234 /* They're both variables that are larger than bits */
7237 tlbl = newiTempLabel(NULL);
7240 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7241 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7243 if ( IC_TRUE(ifx) ) {
7247 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7249 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7250 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7254 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7257 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7258 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7263 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7266 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7270 if(s>1 && IC_TRUE(ifx)) {
7271 pic16_emitpLabel(tlbl->key);
7272 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7276 /* mark the icode as generated */
7281 /* if they are both bit variables */
7282 if (AOP_TYPE(left) == AOP_CRY &&
7283 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7284 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7285 if(AOP_TYPE(right) == AOP_LIT){
7286 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7288 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7289 pic16_emitcode("cpl","c");
7290 } else if(lit == 1L) {
7291 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7293 pic16_emitcode("clr","c");
7295 /* AOP_TYPE(right) == AOP_CRY */
7297 symbol *lbl = newiTempLabel(NULL);
7298 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7299 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7300 pic16_emitcode("cpl","c");
7301 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7304 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7305 pic16_outBitC(result);
7309 genIfxJump (ifx,"c");
7312 /* if the result is used in an arithmetic operation
7313 then put the result in place */
7314 pic16_outBitC(result);
7317 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7318 gencjne(left,right,result,ifx);
7321 gencjne(left,right,newiTempLabel(NULL));
7323 if(IC_TRUE(ifx)->key)
7324 gencjne(left,right,IC_TRUE(ifx)->key);
7326 gencjne(left,right,IC_FALSE(ifx)->key);
7330 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7331 pic16_aopPut(AOP(result),"a",0);
7336 genIfxJump (ifx,"a");
7340 /* if the result is used in an arithmetic operation
7341 then put the result in place */
7343 if (AOP_TYPE(result) != AOP_CRY)
7344 pic16_outAcc(result);
7346 /* leave the result in acc */
7350 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7351 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7352 pic16_freeAsmop(result,NULL,ic,TRUE);
7356 /*-----------------------------------------------------------------*/
7357 /* ifxForOp - returns the icode containing the ifx for operand */
7358 /*-----------------------------------------------------------------*/
7359 static iCode *ifxForOp ( operand *op, iCode *ic )
7363 /* if true symbol then needs to be assigned */
7364 if (IS_TRUE_SYMOP(op))
7367 /* if this has register type condition and
7368 the next instruction is ifx with the same operand
7369 and live to of the operand is upto the ifx only then */
7371 && ic->next->op == IFX
7372 && IC_COND(ic->next)->key == op->key
7373 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7375 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7381 ic->next->op == IFX &&
7382 IC_COND(ic->next)->key == op->key) {
7383 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7388 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7390 ic->next->op == IFX)
7391 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7394 ic->next->op == IFX &&
7395 IC_COND(ic->next)->key == op->key) {
7396 DEBUGpic16_emitcode ("; "," key is okay");
7397 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7398 OP_SYMBOL(op)->liveTo,
7403 /* the code below is completely untested
7404 * it just allows ulong2fs.c compile -- VR */
7407 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7408 __FILE__, __FUNCTION__, __LINE__);
7410 /* if this has register type condition and
7411 the next instruction is ifx with the same operand
7412 and live to of the operand is upto the ifx only then */
7414 ic->next->op == IFX &&
7415 IC_COND(ic->next)->key == op->key &&
7416 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7420 ic->next->op == IFX &&
7421 IC_COND(ic->next)->key == op->key) {
7422 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7426 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7427 __FILE__, __FUNCTION__, __LINE__);
7429 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7434 /*-----------------------------------------------------------------*/
7435 /* genAndOp - for && operation */
7436 /*-----------------------------------------------------------------*/
7437 static void genAndOp (iCode *ic)
7439 operand *left,*right, *result;
7444 /* note here that && operations that are in an
7445 if statement are taken away by backPatchLabels
7446 only those used in arthmetic operations remain */
7447 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7448 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7449 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7451 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7453 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7454 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7455 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7457 /* if both are bit variables */
7458 /* if (AOP_TYPE(left) == AOP_CRY && */
7459 /* AOP_TYPE(right) == AOP_CRY ) { */
7460 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7461 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7462 /* pic16_outBitC(result); */
7464 /* tlbl = newiTempLabel(NULL); */
7465 /* pic16_toBoolean(left); */
7466 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7467 /* pic16_toBoolean(right); */
7468 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7469 /* pic16_outBitAcc(result); */
7472 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7473 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7474 pic16_freeAsmop(result,NULL,ic,TRUE);
7478 /*-----------------------------------------------------------------*/
7479 /* genOrOp - for || operation */
7480 /*-----------------------------------------------------------------*/
7483 modified this code, but it doesn't appear to ever get called
7486 static void genOrOp (iCode *ic)
7488 operand *left,*right, *result;
7493 /* note here that || operations that are in an
7494 if statement are taken away by backPatchLabels
7495 only those used in arthmetic operations remain */
7496 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7497 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7498 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7500 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7502 /* if both are bit variables */
7503 if (AOP_TYPE(left) == AOP_CRY &&
7504 AOP_TYPE(right) == AOP_CRY ) {
7505 pic16_emitcode("clrc","");
7506 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7507 AOP(left)->aopu.aop_dir,
7508 AOP(left)->aopu.aop_dir);
7509 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7510 AOP(right)->aopu.aop_dir,
7511 AOP(right)->aopu.aop_dir);
7512 pic16_emitcode("setc","");
7515 tlbl = newiTempLabel(NULL);
7516 pic16_toBoolean(left);
7518 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7519 pic16_toBoolean(right);
7520 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7522 pic16_outBitAcc(result);
7525 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7526 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7527 pic16_freeAsmop(result,NULL,ic,TRUE);
7530 /*-----------------------------------------------------------------*/
7531 /* isLiteralBit - test if lit == 2^n */
7532 /*-----------------------------------------------------------------*/
7533 static int isLiteralBit(unsigned long lit)
7535 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7536 0x100L,0x200L,0x400L,0x800L,
7537 0x1000L,0x2000L,0x4000L,0x8000L,
7538 0x10000L,0x20000L,0x40000L,0x80000L,
7539 0x100000L,0x200000L,0x400000L,0x800000L,
7540 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7541 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7545 for(idx = 0; idx < 32; idx++)
7551 /*-----------------------------------------------------------------*/
7552 /* continueIfTrue - */
7553 /*-----------------------------------------------------------------*/
7554 static void continueIfTrue (iCode *ic)
7558 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7562 /*-----------------------------------------------------------------*/
7564 /*-----------------------------------------------------------------*/
7565 static void jumpIfTrue (iCode *ic)
7569 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7573 /*-----------------------------------------------------------------*/
7574 /* jmpTrueOrFalse - */
7575 /*-----------------------------------------------------------------*/
7576 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7578 // ugly but optimized by peephole
7581 symbol *nlbl = newiTempLabel(NULL);
7582 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7583 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7584 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7585 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7587 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7588 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7593 /*-----------------------------------------------------------------*/
7594 /* genAnd - code for and */
7595 /*-----------------------------------------------------------------*/
7596 static void genAnd (iCode *ic, iCode *ifx)
7598 operand *left, *right, *result;
7600 unsigned long lit = 0L;
7606 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7607 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7608 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7610 resolveIfx(&rIfx,ifx);
7612 /* if left is a literal & right is not then exchange them */
7613 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7614 AOP_NEEDSACC(left)) {
7615 operand *tmp = right ;
7620 /* if result = right then exchange them */
7621 if(pic16_sameRegs(AOP(result),AOP(right))){
7622 operand *tmp = right ;
7627 /* if right is bit then exchange them */
7628 if (AOP_TYPE(right) == AOP_CRY &&
7629 AOP_TYPE(left) != AOP_CRY){
7630 operand *tmp = right ;
7634 if(AOP_TYPE(right) == AOP_LIT)
7635 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7637 size = AOP_SIZE(result);
7639 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7642 // result = bit & yy;
7643 if (AOP_TYPE(left) == AOP_CRY){
7644 // c = bit & literal;
7645 if(AOP_TYPE(right) == AOP_LIT){
7647 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7650 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7653 if(size && (AOP_TYPE(result) == AOP_CRY)){
7654 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7657 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7661 pic16_emitcode("clr","c");
7664 if (AOP_TYPE(right) == AOP_CRY){
7666 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7667 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7670 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7672 pic16_emitcode("rrc","a");
7673 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7679 pic16_outBitC(result);
7681 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7682 genIfxJump(ifx, "c");
7686 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7687 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7688 if((AOP_TYPE(right) == AOP_LIT) &&
7689 (AOP_TYPE(result) == AOP_CRY) &&
7690 (AOP_TYPE(left) != AOP_CRY)){
7691 int posbit = isLiteralBit(lit);
7695 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7698 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7704 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7707 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7708 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7711 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7712 size = AOP_SIZE(left);
7715 int bp = posbit, ofs=0;
7722 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7723 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7727 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7728 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7730 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7737 symbol *tlbl = newiTempLabel(NULL);
7738 int sizel = AOP_SIZE(left);
7744 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7746 /* patch provided by Aaron Colwell */
7747 if((posbit = isLiteralBit(bytelit)) != 0) {
7748 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7749 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7750 (posbit-1),0, PO_GPR_REGISTER));
7752 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7753 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7755 if (bytelit == 0xff) {
7756 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7757 * a peephole could optimize it out -- VR */
7758 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7760 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7764 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7765 pic16_popGetLabel(tlbl->key));
7769 /* old code, left here for reference -- VR 09/2004 */
7770 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7772 if((posbit = isLiteralBit(bytelit)) != 0)
7773 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7775 if(bytelit != 0x0FFL)
7776 pic16_emitcode("anl","a,%s",
7777 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7778 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7784 // bit = left & literal
7787 pic16_emitpLabel(tlbl->key);
7789 // if(left & literal)
7792 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7795 pic16_emitpLabel(tlbl->key);
7800 pic16_outBitC(result);
7804 /* if left is same as result */
7805 if(pic16_sameRegs(AOP(result),AOP(left))){
7807 for(;size--; offset++,lit>>=8) {
7808 if(AOP_TYPE(right) == AOP_LIT){
7809 switch(lit & 0xff) {
7811 /* and'ing with 0 has clears the result */
7812 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7813 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7816 /* and'ing with 0xff is a nop when the result and left are the same */
7821 int p = pic16_my_powof2( (~lit) & 0xff );
7823 /* only one bit is set in the literal, so use a bcf instruction */
7824 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7825 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7828 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7829 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7830 if(know_W != (lit&0xff))
7831 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7833 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7838 if (AOP_TYPE(left) == AOP_ACC) {
7839 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7841 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7842 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7849 // left & result in different registers
7850 if(AOP_TYPE(result) == AOP_CRY){
7852 // if(size), result in bit
7853 // if(!size && ifx), conditional oper: if(left & right)
7854 symbol *tlbl = newiTempLabel(NULL);
7855 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7857 pic16_emitcode("setb","c");
7859 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7860 pic16_emitcode("anl","a,%s",
7861 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7862 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7867 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7868 pic16_outBitC(result);
7870 jmpTrueOrFalse(ifx, tlbl);
7872 for(;(size--);offset++) {
7874 // result = left & right
7875 if(AOP_TYPE(right) == AOP_LIT){
7876 int t = (lit >> (offset*8)) & 0x0FFL;
7879 pic16_emitcode("clrf","%s",
7880 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7881 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7884 pic16_emitcode("movf","%s,w",
7885 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7886 pic16_emitcode("movwf","%s",
7887 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7888 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7889 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7892 pic16_emitcode("movlw","0x%x",t);
7893 pic16_emitcode("andwf","%s,w",
7894 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7895 pic16_emitcode("movwf","%s",
7896 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7898 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7899 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7900 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7905 if (AOP_TYPE(left) == AOP_ACC) {
7906 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7907 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7909 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910 pic16_emitcode("andwf","%s,w",
7911 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7912 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7913 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7915 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7916 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7922 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7923 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7924 pic16_freeAsmop(result,NULL,ic,TRUE);
7927 /*-----------------------------------------------------------------*/
7928 /* genOr - code for or */
7929 /*-----------------------------------------------------------------*/
7930 static void genOr (iCode *ic, iCode *ifx)
7932 operand *left, *right, *result;
7934 unsigned long lit = 0L;
7936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7939 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7940 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7941 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7943 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7945 /* if left is a literal & right is not then exchange them */
7946 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7947 AOP_NEEDSACC(left)) {
7948 operand *tmp = right ;
7953 /* if result = right then exchange them */
7954 if(pic16_sameRegs(AOP(result),AOP(right))){
7955 operand *tmp = right ;
7960 /* if right is bit then exchange them */
7961 if (AOP_TYPE(right) == AOP_CRY &&
7962 AOP_TYPE(left) != AOP_CRY){
7963 operand *tmp = right ;
7968 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7970 if(AOP_TYPE(right) == AOP_LIT)
7971 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7973 size = AOP_SIZE(result);
7977 if (AOP_TYPE(left) == AOP_CRY){
7978 if(AOP_TYPE(right) == AOP_LIT){
7979 // c = bit & literal;
7981 // lit != 0 => result = 1
7982 if(AOP_TYPE(result) == AOP_CRY){
7984 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7985 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7986 // AOP(result)->aopu.aop_dir,
7987 // AOP(result)->aopu.aop_dir);
7989 continueIfTrue(ifx);
7993 // lit == 0 => result = left
7994 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7996 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7999 if (AOP_TYPE(right) == AOP_CRY){
8000 if(pic16_sameRegs(AOP(result),AOP(left))){
8002 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8003 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8004 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8006 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8007 AOP(result)->aopu.aop_dir,
8008 AOP(result)->aopu.aop_dir);
8009 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8010 AOP(right)->aopu.aop_dir,
8011 AOP(right)->aopu.aop_dir);
8012 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8013 AOP(result)->aopu.aop_dir,
8014 AOP(result)->aopu.aop_dir);
8016 if( AOP_TYPE(result) == AOP_ACC) {
8017 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8018 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8019 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8020 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8024 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8025 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8026 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8027 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8029 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8030 AOP(result)->aopu.aop_dir,
8031 AOP(result)->aopu.aop_dir);
8032 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8033 AOP(right)->aopu.aop_dir,
8034 AOP(right)->aopu.aop_dir);
8035 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8036 AOP(left)->aopu.aop_dir,
8037 AOP(left)->aopu.aop_dir);
8038 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8039 AOP(result)->aopu.aop_dir,
8040 AOP(result)->aopu.aop_dir);
8045 symbol *tlbl = newiTempLabel(NULL);
8046 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8049 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8050 if( AOP_TYPE(right) == AOP_ACC) {
8051 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8053 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8054 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8059 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8060 pic16_emitcode(";XXX setb","c");
8061 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8062 AOP(left)->aopu.aop_dir,tlbl->key+100);
8063 pic16_toBoolean(right);
8064 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8065 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8066 jmpTrueOrFalse(ifx, tlbl);
8070 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8077 pic16_outBitC(result);
8079 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8080 genIfxJump(ifx, "c");
8084 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8085 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8086 if((AOP_TYPE(right) == AOP_LIT) &&
8087 (AOP_TYPE(result) == AOP_CRY) &&
8088 (AOP_TYPE(left) != AOP_CRY)){
8090 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8093 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8095 continueIfTrue(ifx);
8098 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8099 // lit = 0, result = boolean(left)
8101 pic16_emitcode(";XXX setb","c");
8102 pic16_toBoolean(right);
8104 symbol *tlbl = newiTempLabel(NULL);
8105 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8107 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8109 genIfxJump (ifx,"a");
8113 pic16_outBitC(result);
8117 /* if left is same as result */
8118 if(pic16_sameRegs(AOP(result),AOP(left))){
8120 for(;size--; offset++,lit>>=8) {
8121 if(AOP_TYPE(right) == AOP_LIT){
8122 if((lit & 0xff) == 0)
8123 /* or'ing with 0 has no effect */
8126 int p = pic16_my_powof2(lit & 0xff);
8128 /* only one bit is set in the literal, so use a bsf instruction */
8129 pic16_emitpcode(POC_BSF,
8130 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8132 if(know_W != (lit & 0xff))
8133 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8134 know_W = lit & 0xff;
8135 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8140 if (AOP_TYPE(left) == AOP_ACC) {
8141 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8142 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8144 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8145 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8147 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8154 // left & result in different registers
8155 if(AOP_TYPE(result) == AOP_CRY){
8157 // if(size), result in bit
8158 // if(!size && ifx), conditional oper: if(left | right)
8159 symbol *tlbl = newiTempLabel(NULL);
8160 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8161 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8165 pic16_emitcode(";XXX setb","c");
8167 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8168 pic16_emitcode(";XXX orl","a,%s",
8169 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8170 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8175 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8176 pic16_outBitC(result);
8178 jmpTrueOrFalse(ifx, tlbl);
8179 } else for(;(size--);offset++){
8181 // result = left & right
8182 if(AOP_TYPE(right) == AOP_LIT){
8183 int t = (lit >> (offset*8)) & 0x0FFL;
8186 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8189 // pic16_emitcode("movf","%s,w",
8190 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191 // pic16_emitcode("movwf","%s",
8192 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8195 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8196 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8197 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8199 // pic16_emitcode("movlw","0x%x",t);
8200 // pic16_emitcode("iorwf","%s,w",
8201 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8202 // pic16_emitcode("movwf","%s",
8203 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8209 // faster than result <- left, anl result,right
8210 // and better if result is SFR
8211 if (AOP_TYPE(left) == AOP_ACC) {
8212 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8213 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8215 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8216 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8218 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8219 // pic16_emitcode("iorwf","%s,w",
8220 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8223 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8228 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8230 pic16_freeAsmop(result,NULL,ic,TRUE);
8233 /*-----------------------------------------------------------------*/
8234 /* genXor - code for xclusive or */
8235 /*-----------------------------------------------------------------*/
8236 static void genXor (iCode *ic, iCode *ifx)
8238 operand *left, *right, *result;
8240 unsigned long lit = 0L;
8242 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8245 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8246 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8247 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8249 /* if left is a literal & right is not ||
8250 if left needs acc & right does not */
8251 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8252 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8253 operand *tmp = right ;
8258 /* if result = right then exchange them */
8259 if(pic16_sameRegs(AOP(result),AOP(right))){
8260 operand *tmp = right ;
8265 /* if right is bit then exchange them */
8266 if (AOP_TYPE(right) == AOP_CRY &&
8267 AOP_TYPE(left) != AOP_CRY){
8268 operand *tmp = right ;
8272 if(AOP_TYPE(right) == AOP_LIT)
8273 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8275 size = AOP_SIZE(result);
8279 if (AOP_TYPE(left) == AOP_CRY){
8280 if(AOP_TYPE(right) == AOP_LIT){
8281 // c = bit & literal;
8283 // lit>>1 != 0 => result = 1
8284 if(AOP_TYPE(result) == AOP_CRY){
8286 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8287 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8289 continueIfTrue(ifx);
8292 pic16_emitcode("setb","c");
8296 // lit == 0, result = left
8297 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8299 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8301 // lit == 1, result = not(left)
8302 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8303 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8304 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8305 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8308 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8309 pic16_emitcode("cpl","c");
8316 symbol *tlbl = newiTempLabel(NULL);
8317 if (AOP_TYPE(right) == AOP_CRY){
8319 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8322 int sizer = AOP_SIZE(right);
8324 // if val>>1 != 0, result = 1
8325 pic16_emitcode("setb","c");
8327 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8329 // test the msb of the lsb
8330 pic16_emitcode("anl","a,#0xfe");
8331 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8335 pic16_emitcode("rrc","a");
8337 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8338 pic16_emitcode("cpl","c");
8339 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8344 pic16_outBitC(result);
8346 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8347 genIfxJump(ifx, "c");
8351 if(pic16_sameRegs(AOP(result),AOP(left))){
8352 /* if left is same as result */
8353 for(;size--; offset++) {
8354 if(AOP_TYPE(right) == AOP_LIT){
8355 int t = (lit >> (offset*8)) & 0x0FFL;
8359 if (IS_AOP_PREG(left)) {
8360 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8361 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8362 pic16_aopPut(AOP(result),"a",offset);
8364 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8365 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8366 pic16_emitcode("xrl","%s,%s",
8367 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8368 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371 if (AOP_TYPE(left) == AOP_ACC)
8372 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8374 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8375 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8377 if (IS_AOP_PREG(left)) {
8378 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8379 pic16_aopPut(AOP(result),"a",offset);
8381 pic16_emitcode("xrl","%s,a",
8382 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8388 // left & result in different registers
8389 if(AOP_TYPE(result) == AOP_CRY){
8391 // if(size), result in bit
8392 // if(!size && ifx), conditional oper: if(left ^ right)
8393 symbol *tlbl = newiTempLabel(NULL);
8394 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8396 pic16_emitcode("setb","c");
8398 if((AOP_TYPE(right) == AOP_LIT) &&
8399 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8400 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8402 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8403 pic16_emitcode("xrl","a,%s",
8404 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8406 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8411 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8412 pic16_outBitC(result);
8414 jmpTrueOrFalse(ifx, tlbl);
8415 } else for(;(size--);offset++){
8417 // result = left & right
8418 if(AOP_TYPE(right) == AOP_LIT){
8419 int t = (lit >> (offset*8)) & 0x0FFL;
8422 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8423 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8424 pic16_emitcode("movf","%s,w",
8425 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8426 pic16_emitcode("movwf","%s",
8427 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8430 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8431 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8432 pic16_emitcode("comf","%s,w",
8433 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8434 pic16_emitcode("movwf","%s",
8435 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8438 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8439 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8440 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8441 pic16_emitcode("movlw","0x%x",t);
8442 pic16_emitcode("xorwf","%s,w",
8443 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8444 pic16_emitcode("movwf","%s",
8445 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8451 // faster than result <- left, anl result,right
8452 // and better if result is SFR
8453 if (AOP_TYPE(left) == AOP_ACC) {
8454 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8455 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8457 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8458 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8459 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8460 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8462 if ( AOP_TYPE(result) != AOP_ACC){
8463 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8464 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8470 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8471 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8472 pic16_freeAsmop(result,NULL,ic,TRUE);
8475 /*-----------------------------------------------------------------*/
8476 /* genInline - write the inline code out */
8477 /*-----------------------------------------------------------------*/
8478 static void genInline (iCode *ic)
8480 char *buffer, *bp, *bp1;
8482 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8484 _G.inLine += (!options.asmpeep);
8486 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8487 strcpy(buffer,IC_INLINE(ic));
8489 while((bp1=strstr(bp, "\\n"))) {
8497 /* This is an experimental code for #pragma inline
8498 and is temporarily disabled for 2.5.0 release */
8506 cbuf = Safe_strdup(buffer);
8507 cblen = strlen(buffer)+1;
8508 memset(cbuf, 0, cblen);
8513 if(*bp != '%')*bp1++ = *bp++;
8519 if(i>elementsInSet(asmInlineMap))break;
8522 s = indexSet(asmInlineMap, i);
8523 DEBUGpc("searching symbol s = `%s'", s);
8524 sym = findSym(SymbolTab, NULL, s);
8527 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8529 strcat(bp1, sym->rname);
8535 if(strlen(bp1) > cblen - 16) {
8536 int i = strlen(cbuf);
8538 cbuf = realloc(cbuf, cblen);
8539 memset(cbuf+i, 0, 50);
8545 buffer = Safe_strdup( cbuf );
8552 /* emit each line as a code */
8558 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8566 /* print label, use this special format with NULL directive
8567 * to denote that the argument should not be indented with tab */
8568 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8571 /* advance to end of line (prevent splitting of comments at ':' */
8572 while (*bp && *bp != '\n') {
8580 if ((bp1 != bp) && *bp1)
8581 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8586 _G.inLine -= (!options.asmpeep);
8589 /*-----------------------------------------------------------------*/
8590 /* genRRC - rotate right with carry */
8591 /*-----------------------------------------------------------------*/
8592 static void genRRC (iCode *ic)
8594 operand *left , *result ;
8595 int size, offset = 0, same;
8597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8599 /* rotate right with carry */
8601 result=IC_RESULT(ic);
8602 pic16_aopOp (left,ic,FALSE);
8603 pic16_aopOp (result,ic,TRUE);
8605 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8607 same = pic16_sameRegs(AOP(result),AOP(left));
8609 size = AOP_SIZE(result);
8611 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8613 /* get the lsb and put it into the carry */
8614 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8621 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8623 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8630 pic16_freeAsmop(left,NULL,ic,TRUE);
8631 pic16_freeAsmop(result,NULL,ic,TRUE);
8634 /*-----------------------------------------------------------------*/
8635 /* genRLC - generate code for rotate left with carry */
8636 /*-----------------------------------------------------------------*/
8637 static void genRLC (iCode *ic)
8639 operand *left , *result ;
8640 int size, offset = 0;
8643 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8644 /* rotate right with carry */
8646 result=IC_RESULT(ic);
8647 pic16_aopOp (left,ic,FALSE);
8648 pic16_aopOp (result,ic,TRUE);
8650 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8652 same = pic16_sameRegs(AOP(result),AOP(left));
8654 /* move it to the result */
8655 size = AOP_SIZE(result);
8657 /* get the msb and put it into the carry */
8658 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8665 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8667 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8675 pic16_freeAsmop(left,NULL,ic,TRUE);
8676 pic16_freeAsmop(result,NULL,ic,TRUE);
8680 /* gpasm can get the highest order bit with HIGH/UPPER
8681 * so the following probably is not needed -- VR */
8683 /*-----------------------------------------------------------------*/
8684 /* genGetHbit - generates code get highest order bit */
8685 /*-----------------------------------------------------------------*/
8686 static void genGetHbit (iCode *ic)
8688 operand *left, *result;
8690 result=IC_RESULT(ic);
8691 pic16_aopOp (left,ic,FALSE);
8692 pic16_aopOp (result,ic,FALSE);
8694 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8695 /* get the highest order byte into a */
8696 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8697 if(AOP_TYPE(result) == AOP_CRY){
8698 pic16_emitcode("rlc","a");
8699 pic16_outBitC(result);
8702 pic16_emitcode("rl","a");
8703 pic16_emitcode("anl","a,#0x01");
8704 pic16_outAcc(result);
8708 pic16_freeAsmop(left,NULL,ic,TRUE);
8709 pic16_freeAsmop(result,NULL,ic,TRUE);
8713 /*-----------------------------------------------------------------*/
8714 /* AccRol - rotate left accumulator by known count */
8715 /*-----------------------------------------------------------------*/
8716 static void AccRol (int shCount)
8718 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8719 shCount &= 0x0007; // shCount : 0..7
8724 pic16_emitcode("rl","a");
8727 pic16_emitcode("rl","a");
8728 pic16_emitcode("rl","a");
8731 pic16_emitcode("swap","a");
8732 pic16_emitcode("rr","a");
8735 pic16_emitcode("swap","a");
8738 pic16_emitcode("swap","a");
8739 pic16_emitcode("rl","a");
8742 pic16_emitcode("rr","a");
8743 pic16_emitcode("rr","a");
8746 pic16_emitcode("rr","a");
8752 /*-----------------------------------------------------------------*/
8753 /* AccLsh - left shift accumulator by known count */
8754 /*-----------------------------------------------------------------*/
8755 static void AccLsh (int shCount, int doMask)
8757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8763 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8766 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8767 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8770 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8771 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8774 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8777 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8778 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8781 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8782 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8785 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789 /* no masking is required in genPackBits */
8790 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8794 /*-----------------------------------------------------------------*/
8795 /* AccRsh - right shift accumulator by known count */
8796 /*-----------------------------------------------------------------*/
8797 static void AccRsh (int shCount, int andmask)
8799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8804 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8807 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8808 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8811 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8812 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8818 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8822 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8823 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8826 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8831 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8833 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8837 /*-----------------------------------------------------------------*/
8838 /* AccSRsh - signed right shift accumulator by known count */
8839 /*-----------------------------------------------------------------*/
8840 static void AccSRsh (int shCount)
8843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8846 pic16_emitcode("mov","c,acc.7");
8847 pic16_emitcode("rrc","a");
8848 } else if(shCount == 2){
8849 pic16_emitcode("mov","c,acc.7");
8850 pic16_emitcode("rrc","a");
8851 pic16_emitcode("mov","c,acc.7");
8852 pic16_emitcode("rrc","a");
8854 tlbl = newiTempLabel(NULL);
8855 /* rotate right accumulator */
8856 AccRol(8 - shCount);
8857 /* and kill the higher order bits */
8858 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8859 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8860 pic16_emitcode("orl","a,#0x%02x",
8861 (unsigned char)~SRMask[shCount]);
8862 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8868 /*-----------------------------------------------------------------*/
8869 /* shiftR1Left2Result - shift right one byte from left to result */
8870 /*-----------------------------------------------------------------*/
8871 static void shiftR1Left2ResultSigned (operand *left, int offl,
8872 operand *result, int offr,
8877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8879 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8883 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8885 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8888 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8894 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8896 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8898 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8899 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8902 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8910 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8911 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8914 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8915 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8916 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8918 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8919 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8921 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8925 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8926 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8927 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8928 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8940 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8941 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8948 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8950 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8951 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8956 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8958 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8964 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8965 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8966 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8971 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8979 /*-----------------------------------------------------------------*/
8980 /* shiftR1Left2Result - shift right one byte from left to result */
8981 /*-----------------------------------------------------------------*/
8982 static void shiftR1Left2Result (operand *left, int offl,
8983 operand *result, int offr,
8984 int shCount, int sign)
8988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8990 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8992 /* Copy the msb into the carry if signed. */
8994 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9004 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9015 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9016 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9027 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9031 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9038 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9039 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9044 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9045 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9052 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9053 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9055 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9056 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9061 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9062 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9063 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9072 /*-----------------------------------------------------------------*/
9073 /* shiftL1Left2Result - shift left one byte from left to result */
9074 /*-----------------------------------------------------------------*/
9075 static void shiftL1Left2Result (operand *left, int offl,
9076 operand *result, int offr, int shCount)
9081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9083 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9084 DEBUGpic16_emitcode ("; ***","same = %d",same);
9085 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9087 /* shift left accumulator */
9088 //AccLsh(shCount, 1); // don't comment out just yet...
9089 // pic16_aopPut(AOP(result),"a",offr);
9093 /* Shift left 1 bit position */
9094 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9096 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9098 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9099 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9104 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9105 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9110 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9111 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9117 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9118 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9122 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9123 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9124 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9128 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9129 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9130 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9135 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9136 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9140 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9145 /*-----------------------------------------------------------------*/
9146 /* movLeft2Result - move byte from left to result */
9147 /*-----------------------------------------------------------------*/
9148 static void movLeft2Result (operand *left, int offl,
9149 operand *result, int offr)
9152 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9153 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9154 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9156 if (*l == '@' && (IS_AOP_PREG(result))) {
9157 pic16_emitcode("mov","a,%s",l);
9158 pic16_aopPut(AOP(result),"a",offr);
9160 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9161 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9166 /*-----------------------------------------------------------------*/
9167 /* shiftL2Left2Result - shift left two bytes from left to result */
9168 /*-----------------------------------------------------------------*/
9169 static void shiftL2Left2Result (operand *left, int offl,
9170 operand *result, int offr, int shCount)
9172 int same = pic16_sameRegs(AOP(result), AOP(left));
9175 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9177 if (same && (offl != offr)) { // shift bytes
9180 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9181 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9183 } else { // just treat as different later on
9196 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9197 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9198 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9202 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9203 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9209 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9210 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9211 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9212 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9213 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9214 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9217 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9218 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9222 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9223 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9224 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9225 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9226 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9227 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9228 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9229 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9230 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9231 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9234 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9235 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9236 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9237 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9238 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9248 /* note, use a mov/add for the shift since the mov has a
9249 chance of getting optimized out */
9250 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9252 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9253 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9258 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9259 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9265 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9266 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9267 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9268 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9269 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9270 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9271 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9272 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9276 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9277 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9281 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9282 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9283 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9284 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9286 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9287 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9288 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9289 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9290 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9291 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9292 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9293 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9297 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9298 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9300 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9305 /*-----------------------------------------------------------------*/
9306 /* shiftR2Left2Result - shift right two bytes from left to result */
9307 /*-----------------------------------------------------------------*/
9308 static void shiftR2Left2Result (operand *left, int offl,
9309 operand *result, int offr,
9310 int shCount, int sign)
9312 int same = pic16_sameRegs(AOP(result), AOP(left));
9314 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9316 if (same && (offl != offr)) { // shift right bytes
9319 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9320 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9322 } else { // just treat as different later on
9333 /* obtain sign from left operand */
9335 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9340 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9341 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9343 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9344 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9345 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9346 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9351 /* now get sign from already assigned result (avoid BANKSEL) */
9352 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9355 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9356 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9363 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9364 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9365 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9367 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9368 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9369 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9370 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9372 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9373 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9374 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9376 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9377 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9378 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9379 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9380 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9384 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9385 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9389 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9390 pic16_emitpcode(POC_BTFSC,
9391 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9392 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9400 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9401 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9403 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9404 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9405 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9406 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9408 pic16_emitpcode(POC_BTFSC,
9409 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9410 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9412 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9413 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9414 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9415 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9417 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9418 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9419 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9420 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9421 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9422 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9423 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9424 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9426 pic16_emitpcode(POC_BTFSC,
9427 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9428 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9430 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9431 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9438 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9439 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9440 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9441 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9444 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9446 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9451 /*-----------------------------------------------------------------*/
9452 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9453 /*-----------------------------------------------------------------*/
9454 static void shiftLLeftOrResult (operand *left, int offl,
9455 operand *result, int offr, int shCount)
9457 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9459 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9460 /* shift left accumulator */
9462 /* or with result */
9463 /* back to result */
9464 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9467 /*-----------------------------------------------------------------*/
9468 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9469 /*-----------------------------------------------------------------*/
9470 static void shiftRLeftOrResult (operand *left, int offl,
9471 operand *result, int offr, int shCount)
9473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9475 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9476 /* shift right accumulator */
9478 /* or with result */
9479 /* back to result */
9480 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9483 /*-----------------------------------------------------------------*/
9484 /* genlshOne - left shift a one byte quantity by known count */
9485 /*-----------------------------------------------------------------*/
9486 static void genlshOne (operand *result, operand *left, int shCount)
9488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9489 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9492 /*-----------------------------------------------------------------*/
9493 /* genlshTwo - left shift two bytes by known amount != 0 */
9494 /*-----------------------------------------------------------------*/
9495 static void genlshTwo (operand *result,operand *left, int shCount)
9499 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9500 size = pic16_getDataSize(result);
9502 /* if shCount >= 8 */
9508 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9510 movLeft2Result(left, LSB, result, MSB16);
9512 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9515 /* 1 <= shCount <= 7 */
9518 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9520 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9524 /*-----------------------------------------------------------------*/
9525 /* shiftLLong - shift left one long from left to result */
9526 /* offr = LSB or MSB16 */
9527 /*-----------------------------------------------------------------*/
9528 static void shiftLLong (operand *left, operand *result, int offr )
9530 int size = AOP_SIZE(result);
9531 int same = pic16_sameRegs(AOP(left),AOP(result));
9534 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9536 if (same && (offr == MSB16)) { //shift one byte
9537 for(i=size-1;i>=MSB16;i--) {
9538 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9539 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9542 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9545 if (size > LSB+offr ){
9547 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9549 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9550 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9554 if(size > MSB16+offr){
9556 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9558 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9559 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9563 if(size > MSB24+offr){
9565 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9567 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9568 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9572 if(size > MSB32+offr){
9574 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9576 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9577 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9581 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9585 /*-----------------------------------------------------------------*/
9586 /* genlshFour - shift four byte by a known amount != 0 */
9587 /*-----------------------------------------------------------------*/
9588 static void genlshFour (operand *result, operand *left, int shCount)
9592 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9593 size = AOP_SIZE(result);
9595 /* if shifting more that 3 bytes */
9596 if (shCount >= 24 ) {
9599 /* lowest order of left goes to the highest
9600 order of the destination */
9601 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9603 movLeft2Result(left, LSB, result, MSB32);
9605 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9606 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9607 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9612 /* more than two bytes */
9613 else if ( shCount >= 16 ) {
9614 /* lower order two bytes goes to higher order two bytes */
9616 /* if some more remaining */
9618 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9620 movLeft2Result(left, MSB16, result, MSB32);
9621 movLeft2Result(left, LSB, result, MSB24);
9623 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9624 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9628 /* if more than 1 byte */
9629 else if ( shCount >= 8 ) {
9630 /* lower order three bytes goes to higher order three bytes */
9634 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9636 movLeft2Result(left, LSB, result, MSB16);
9638 else{ /* size = 4 */
9640 movLeft2Result(left, MSB24, result, MSB32);
9641 movLeft2Result(left, MSB16, result, MSB24);
9642 movLeft2Result(left, LSB, result, MSB16);
9643 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9645 else if(shCount == 1)
9646 shiftLLong(left, result, MSB16);
9648 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9649 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9650 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9651 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9656 /* 1 <= shCount <= 7 */
9657 else if(shCount <= 3)
9659 shiftLLong(left, result, LSB);
9660 while(--shCount >= 1)
9661 shiftLLong(result, result, LSB);
9663 /* 3 <= shCount <= 7, optimize */
9665 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9666 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9667 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9671 /*-----------------------------------------------------------------*/
9672 /* genLeftShiftLiteral - left shifting by known count */
9673 /*-----------------------------------------------------------------*/
9674 void pic16_genLeftShiftLiteral (operand *left,
9679 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9683 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9684 pic16_freeAsmop(right,NULL,ic,TRUE);
9686 pic16_aopOp(left,ic,FALSE);
9687 pic16_aopOp(result,ic,TRUE);
9689 size = getSize(operandType(result));
9692 pic16_emitcode("; shift left ","result %d, left %d",size,
9696 /* I suppose that the left size >= result size */
9699 movLeft2Result(left, size, result, size);
9703 else if(shCount >= (size * 8))
9705 pic16_aopPut(AOP(result),zero,size);
9709 genlshOne (result,left,shCount);
9714 genlshTwo (result,left,shCount);
9718 genlshFour (result,left,shCount);
9722 pic16_freeAsmop(left,NULL,ic,TRUE);
9723 pic16_freeAsmop(result,NULL,ic,TRUE);
9726 /*-----------------------------------------------------------------*
9727 * genMultiAsm - repeat assembly instruction for size of register.
9728 * if endian == 1, then the high byte (i.e base address + size of
9729 * register) is used first else the low byte is used first;
9730 *-----------------------------------------------------------------*/
9731 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9749 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9755 #if !(USE_GENERIC_SIGNED_SHIFT)
9756 /*-----------------------------------------------------------------*/
9757 /* genLeftShift - generates code for left shifting */
9758 /*-----------------------------------------------------------------*/
9759 static void genLeftShift (iCode *ic)
9761 operand *left,*right, *result;
9764 symbol *tlbl , *tlbl1;
9767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9769 right = IC_RIGHT(ic);
9771 result = IC_RESULT(ic);
9773 pic16_aopOp(right,ic,FALSE);
9775 /* if the shift count is known then do it
9776 as efficiently as possible */
9777 if (AOP_TYPE(right) == AOP_LIT) {
9778 pic16_genLeftShiftLiteral (left,right,result,ic);
9782 /* shift count is unknown then we have to form
9783 * a loop. Get the loop count in WREG : Note: we take
9784 * only the lower order byte since shifting
9785 * more than 32 bits make no sense anyway, ( the
9786 * largest size of an object can be only 32 bits ) */
9788 pic16_aopOp(left,ic,FALSE);
9789 pic16_aopOp(result,ic,FALSE);
9791 /* now move the left to the result if they are not the
9792 * same, and if size > 1,
9793 * and if right is not same to result (!!!) -- VR */
9794 if (!pic16_sameRegs(AOP(left),AOP(result))
9795 && (AOP_SIZE(result) > 1)) {
9797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9799 size = AOP_SIZE(result);
9804 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9805 if (*l == '@' && (IS_AOP_PREG(result))) {
9807 pic16_emitcode("mov","a,%s",l);
9808 pic16_aopPut(AOP(result),"a",offset);
9812 /* we don't know if left is a literal or a register, take care -- VR */
9813 pic16_mov2f(AOP(result), AOP(left), offset);
9819 size = AOP_SIZE(result);
9821 /* if it is only one byte then */
9823 if(optimized_for_speed) {
9824 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9825 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9826 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9827 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9828 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9829 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9830 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9831 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9832 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9833 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9834 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9835 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9840 tlbl = newiTempLabel(NULL);
9843 /* this is already done, why change it? */
9844 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9845 pic16_mov2f(AOP(result), AOP(left), 0);
9849 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9850 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9851 pic16_emitpLabel(tlbl->key);
9852 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9853 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9860 if (pic16_sameRegs(AOP(left),AOP(result))) {
9862 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9864 tlbl = newiTempLabel(NULL);
9865 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9866 genMultiAsm(POC_RRCF, result, size,1);
9867 pic16_emitpLabel(tlbl->key);
9868 genMultiAsm(POC_RLCF, result, size,0);
9869 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9875 //tlbl = newiTempLabel(NULL);
9877 //tlbl1 = newiTempLabel(NULL);
9879 //reAdjustPreg(AOP(result));
9881 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9882 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9883 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9885 //pic16_emitcode("add","a,acc");
9886 //pic16_aopPut(AOP(result),"a",offset++);
9888 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9890 // pic16_emitcode("rlc","a");
9891 // pic16_aopPut(AOP(result),"a",offset++);
9893 //reAdjustPreg(AOP(result));
9895 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9896 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9899 tlbl = newiTempLabel(NULL);
9900 tlbl1= newiTempLabel(NULL);
9902 size = AOP_SIZE(result);
9905 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9907 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9909 /* offset should be 0, 1 or 3 */
9911 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9913 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9915 pic16_emitpcode(POC_MOVWF, pctemp);
9918 pic16_emitpLabel(tlbl->key);
9921 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9923 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9925 pic16_emitpcode(POC_DECFSZ, pctemp);
9926 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9927 pic16_emitpLabel(tlbl1->key);
9929 pic16_popReleaseTempReg(pctemp,1);
9933 pic16_freeAsmop (right,NULL,ic,TRUE);
9934 pic16_freeAsmop(left,NULL,ic,TRUE);
9935 pic16_freeAsmop(result,NULL,ic,TRUE);
9941 #error old code (left here for reference)
9942 /*-----------------------------------------------------------------*/
9943 /* genLeftShift - generates code for left shifting */
9944 /*-----------------------------------------------------------------*/
9945 static void genLeftShift (iCode *ic)
9947 operand *left,*right, *result;
9950 symbol *tlbl , *tlbl1;
9953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9955 right = IC_RIGHT(ic);
9957 result = IC_RESULT(ic);
9959 pic16_aopOp(right,ic,FALSE);
9961 /* if the shift count is known then do it
9962 as efficiently as possible */
9963 if (AOP_TYPE(right) == AOP_LIT) {
9964 pic16_genLeftShiftLiteral (left,right,result,ic);
9968 /* shift count is unknown then we have to form
9969 a loop get the loop count in B : Note: we take
9970 only the lower order byte since shifting
9971 more that 32 bits make no sense anyway, ( the
9972 largest size of an object can be only 32 bits ) */
9975 pic16_aopOp(left,ic,FALSE);
9976 pic16_aopOp(result,ic,FALSE);
9978 /* now move the left to the result if they are not the
9980 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9981 AOP_SIZE(result) > 1) {
9983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9985 size = AOP_SIZE(result);
9988 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9989 if (*l == '@' && (IS_AOP_PREG(result))) {
9991 pic16_emitcode("mov","a,%s",l);
9992 pic16_aopPut(AOP(result),"a",offset);
9995 /* we don't know if left is a literal or a register, take care -- VR */
9996 pic16_mov2f(AOP(result), AOP(left), offset);
10002 size = AOP_SIZE(result);
10004 /* if it is only one byte then */
10006 if(optimized_for_speed) {
10007 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10008 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10009 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10010 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10012 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10013 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10014 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10015 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10016 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10017 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10018 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10023 tlbl = newiTempLabel(NULL);
10024 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10025 pic16_mov2f(AOP(result), AOP(left), 0);
10027 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10028 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10031 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10032 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10033 pic16_emitpLabel(tlbl->key);
10034 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10035 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10037 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10042 if (pic16_sameRegs(AOP(left),AOP(result))) {
10044 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10046 tlbl = newiTempLabel(NULL);
10047 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10048 genMultiAsm(POC_RRCF, result, size,1);
10049 pic16_emitpLabel(tlbl->key);
10050 genMultiAsm(POC_RLCF, result, size,0);
10051 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10053 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10057 //tlbl = newiTempLabel(NULL);
10059 //tlbl1 = newiTempLabel(NULL);
10061 //reAdjustPreg(AOP(result));
10063 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10064 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10065 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10067 //pic16_emitcode("add","a,acc");
10068 //pic16_aopPut(AOP(result),"a",offset++);
10070 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10072 // pic16_emitcode("rlc","a");
10073 // pic16_aopPut(AOP(result),"a",offset++);
10075 //reAdjustPreg(AOP(result));
10077 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10078 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10081 tlbl = newiTempLabel(NULL);
10082 tlbl1= newiTempLabel(NULL);
10084 size = AOP_SIZE(result);
10087 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10089 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10091 /* offset should be 0, 1 or 3 */
10093 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10095 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10097 pic16_emitpcode(POC_MOVWF, pctemp);
10100 pic16_emitpLabel(tlbl->key);
10103 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10105 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10107 pic16_emitpcode(POC_DECFSZ, pctemp);
10108 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10109 pic16_emitpLabel(tlbl1->key);
10111 pic16_popReleaseTempReg(pctemp,1);
10115 pic16_freeAsmop (right,NULL,ic,TRUE);
10116 pic16_freeAsmop(left,NULL,ic,TRUE);
10117 pic16_freeAsmop(result,NULL,ic,TRUE);
10121 /*-----------------------------------------------------------------*/
10122 /* genrshOne - right shift a one byte quantity by known count */
10123 /*-----------------------------------------------------------------*/
10124 static void genrshOne (operand *result, operand *left,
10125 int shCount, int sign)
10127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10128 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10131 /*-----------------------------------------------------------------*/
10132 /* genrshTwo - right shift two bytes by known amount != 0 */
10133 /*-----------------------------------------------------------------*/
10134 static void genrshTwo (operand *result,operand *left,
10135 int shCount, int sign)
10137 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10138 /* if shCount >= 8 */
10139 if (shCount >= 8) {
10142 shiftR1Left2Result(left, MSB16, result, LSB,
10145 movLeft2Result(left, MSB16, result, LSB);
10147 pic16_addSign (result, 1, sign);
10150 /* 1 <= shCount <= 7 */
10152 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10155 /*-----------------------------------------------------------------*/
10156 /* shiftRLong - shift right one long from left to result */
10157 /* offl = LSB or MSB16 */
10158 /*-----------------------------------------------------------------*/
10159 static void shiftRLong (operand *left, int offl,
10160 operand *result, int sign)
10162 int size = AOP_SIZE(result);
10163 int same = pic16_sameRegs(AOP(left),AOP(result));
10165 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10167 if (same && (offl == MSB16)) { //shift one byte right
10168 for(i=MSB16;i<size;i++) {
10169 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10170 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10175 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10181 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10183 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10184 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10187 if(offl == MSB16) {
10188 /* add sign of "a" */
10189 pic16_addSign(result, MSB32, sign);
10193 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10195 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10196 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10200 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10202 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10203 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10207 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10210 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10211 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10216 /*-----------------------------------------------------------------*/
10217 /* genrshFour - shift four byte by a known amount != 0 */
10218 /*-----------------------------------------------------------------*/
10219 static void genrshFour (operand *result, operand *left,
10220 int shCount, int sign)
10222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10223 /* if shifting more that 3 bytes */
10224 if(shCount >= 24 ) {
10227 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10229 movLeft2Result(left, MSB32, result, LSB);
10231 pic16_addSign(result, MSB16, sign);
10233 else if(shCount >= 16){
10236 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10238 movLeft2Result(left, MSB24, result, LSB);
10239 movLeft2Result(left, MSB32, result, MSB16);
10241 pic16_addSign(result, MSB24, sign);
10243 else if(shCount >= 8){
10246 shiftRLong(left, MSB16, result, sign);
10247 else if(shCount == 0){
10248 movLeft2Result(left, MSB16, result, LSB);
10249 movLeft2Result(left, MSB24, result, MSB16);
10250 movLeft2Result(left, MSB32, result, MSB24);
10251 pic16_addSign(result, MSB32, sign);
10253 else{ //shcount >= 2
10254 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10255 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10256 /* the last shift is signed */
10257 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10258 pic16_addSign(result, MSB32, sign);
10261 else{ /* 1 <= shCount <= 7 */
10263 shiftRLong(left, LSB, result, sign);
10265 shiftRLong(result, LSB, result, sign);
10268 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10269 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10270 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10275 /*-----------------------------------------------------------------*/
10276 /* genRightShiftLiteral - right shifting by known count */
10277 /*-----------------------------------------------------------------*/
10278 static void genRightShiftLiteral (operand *left,
10284 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10285 int lsize,res_size;
10287 pic16_freeAsmop(right,NULL,ic,TRUE);
10289 pic16_aopOp(left,ic,FALSE);
10290 pic16_aopOp(result,ic,TRUE);
10292 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10295 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10299 lsize = pic16_getDataSize(left);
10300 res_size = pic16_getDataSize(result);
10301 /* test the LEFT size !!! */
10303 /* I suppose that the left size >= result size */
10305 assert (res_size <= lsize);
10306 while (res_size--) {
10307 pic16_mov2f (AOP(result), AOP(left), res_size);
10311 else if(shCount >= (lsize * 8)){
10313 if(res_size == 1) {
10314 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10316 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10317 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10322 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10323 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10324 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10326 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10331 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10336 switch (res_size) {
10338 genrshOne (result,left,shCount,sign);
10342 genrshTwo (result,left,shCount,sign);
10346 genrshFour (result,left,shCount,sign);
10354 pic16_freeAsmop(left,NULL,ic,TRUE);
10355 pic16_freeAsmop(result,NULL,ic,TRUE);
10358 #if !(USE_GENERIC_SIGNED_SHIFT)
10359 /*-----------------------------------------------------------------*/
10360 /* genSignedRightShift - right shift of signed number */
10361 /*-----------------------------------------------------------------*/
10362 static void genSignedRightShift (iCode *ic)
10364 operand *right, *left, *result;
10367 symbol *tlbl, *tlbl1 ;
10370 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10372 /* we do it the hard way put the shift count in b
10373 and loop thru preserving the sign */
10374 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10376 right = IC_RIGHT(ic);
10377 left = IC_LEFT(ic);
10378 result = IC_RESULT(ic);
10380 pic16_aopOp(right,ic,FALSE);
10381 pic16_aopOp(left,ic,FALSE);
10382 pic16_aopOp(result,ic,FALSE);
10385 if ( AOP_TYPE(right) == AOP_LIT) {
10386 genRightShiftLiteral (left,right,result,ic,1);
10389 /* shift count is unknown then we have to form
10390 a loop get the loop count in B : Note: we take
10391 only the lower order byte since shifting
10392 more that 32 bits make no sense anyway, ( the
10393 largest size of an object can be only 32 bits ) */
10395 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10396 //pic16_emitcode("inc","b");
10397 //pic16_freeAsmop (right,NULL,ic,TRUE);
10398 //pic16_aopOp(left,ic,FALSE);
10399 //pic16_aopOp(result,ic,FALSE);
10401 /* now move the left to the result if they are not the
10403 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10404 AOP_SIZE(result) > 1) {
10406 size = AOP_SIZE(result);
10410 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10411 if (*l == '@' && IS_AOP_PREG(result)) {
10413 pic16_emitcode("mov","a,%s",l);
10414 pic16_aopPut(AOP(result),"a",offset);
10416 pic16_aopPut(AOP(result),l,offset);
10418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10419 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10425 /* mov the highest order bit to OVR */
10426 tlbl = newiTempLabel(NULL);
10427 tlbl1= newiTempLabel(NULL);
10429 size = AOP_SIZE(result);
10432 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10434 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10436 /* offset should be 0, 1 or 3 */
10437 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10439 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10441 pic16_emitpcode(POC_MOVWF, pctemp);
10444 pic16_emitpLabel(tlbl->key);
10446 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10447 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10450 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10453 pic16_emitpcode(POC_DECFSZ, pctemp);
10454 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10455 pic16_emitpLabel(tlbl1->key);
10457 pic16_popReleaseTempReg(pctemp,1);
10459 size = AOP_SIZE(result);
10461 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10462 pic16_emitcode("rlc","a");
10463 pic16_emitcode("mov","ov,c");
10464 /* if it is only one byte then */
10466 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10468 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10469 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10470 pic16_emitcode("mov","c,ov");
10471 pic16_emitcode("rrc","a");
10472 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10473 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10474 pic16_aopPut(AOP(result),"a",0);
10478 reAdjustPreg(AOP(result));
10479 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10480 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10481 pic16_emitcode("mov","c,ov");
10483 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10485 pic16_emitcode("rrc","a");
10486 pic16_aopPut(AOP(result),"a",offset--);
10488 reAdjustPreg(AOP(result));
10489 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10490 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10495 pic16_freeAsmop(left,NULL,ic,TRUE);
10496 pic16_freeAsmop(result,NULL,ic,TRUE);
10497 pic16_freeAsmop(right,NULL,ic,TRUE);
10501 #if !(USE_GENERIC_SIGNED_SHIFT)
10502 #warning This implementation of genRightShift() is incomplete!
10503 /*-----------------------------------------------------------------*/
10504 /* genRightShift - generate code for right shifting */
10505 /*-----------------------------------------------------------------*/
10506 static void genRightShift (iCode *ic)
10508 operand *right, *left, *result;
10512 symbol *tlbl, *tlbl1 ;
10514 /* if signed then we do it the hard way preserve the
10515 sign bit moving it inwards */
10516 letype = getSpec(operandType(IC_LEFT(ic)));
10517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10519 if (!SPEC_USIGN(letype)) {
10520 genSignedRightShift (ic);
10524 /* signed & unsigned types are treated the same : i.e. the
10525 signed is NOT propagated inwards : quoting from the
10526 ANSI - standard : "for E1 >> E2, is equivalent to division
10527 by 2**E2 if unsigned or if it has a non-negative value,
10528 otherwise the result is implementation defined ", MY definition
10529 is that the sign does not get propagated */
10531 right = IC_RIGHT(ic);
10532 left = IC_LEFT(ic);
10533 result = IC_RESULT(ic);
10535 pic16_aopOp(right,ic,FALSE);
10537 /* if the shift count is known then do it
10538 as efficiently as possible */
10539 if (AOP_TYPE(right) == AOP_LIT) {
10540 genRightShiftLiteral (left,right,result,ic, 0);
10544 /* shift count is unknown then we have to form
10545 a loop get the loop count in B : Note: we take
10546 only the lower order byte since shifting
10547 more that 32 bits make no sense anyway, ( the
10548 largest size of an object can be only 32 bits ) */
10550 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10551 pic16_emitcode("inc","b");
10552 pic16_aopOp(left,ic,FALSE);
10553 pic16_aopOp(result,ic,FALSE);
10555 /* now move the left to the result if they are not the
10557 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10558 AOP_SIZE(result) > 1) {
10560 size = AOP_SIZE(result);
10563 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10564 if (*l == '@' && IS_AOP_PREG(result)) {
10566 pic16_emitcode("mov","a,%s",l);
10567 pic16_aopPut(AOP(result),"a",offset);
10569 pic16_aopPut(AOP(result),l,offset);
10574 tlbl = newiTempLabel(NULL);
10575 tlbl1= newiTempLabel(NULL);
10576 size = AOP_SIZE(result);
10579 /* if it is only one byte then */
10582 tlbl = newiTempLabel(NULL);
10583 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10588 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10589 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10590 pic16_emitpLabel(tlbl->key);
10591 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10592 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10599 reAdjustPreg(AOP(result));
10600 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10601 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10604 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10606 pic16_emitcode("rrc","a");
10607 pic16_aopPut(AOP(result),"a",offset--);
10609 reAdjustPreg(AOP(result));
10611 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10612 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10615 pic16_freeAsmop(left,NULL,ic,TRUE);
10616 pic16_freeAsmop (right,NULL,ic,TRUE);
10617 pic16_freeAsmop(result,NULL,ic,TRUE);
10621 #if (USE_GENERIC_SIGNED_SHIFT)
10622 /*-----------------------------------------------------------------*/
10623 /* genGenericShift - generates code for left or right shifting */
10624 /*-----------------------------------------------------------------*/
10625 static void genGenericShift (iCode *ic, int isShiftLeft) {
10626 operand *left,*right, *result;
10628 int sign, signedCount;
10629 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10630 PIC_OPCODE pos_shift, neg_shift;
10634 right = IC_RIGHT(ic);
10635 left = IC_LEFT(ic);
10636 result = IC_RESULT(ic);
10638 pic16_aopOp(right,ic,FALSE);
10639 pic16_aopOp(left,ic,FALSE);
10640 pic16_aopOp(result,ic,TRUE);
10642 sign = !SPEC_USIGN(operandType (left));
10643 signedCount = !SPEC_USIGN(operandType (right));
10645 /* if the shift count is known then do it
10646 as efficiently as possible */
10647 if (AOP_TYPE(right) == AOP_LIT) {
10648 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10649 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10650 // we should modify right->aopu.aop_lit here!
10651 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10652 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10654 pic16_genLeftShiftLiteral (left,right,result,ic);
10656 genRightShiftLiteral (left,right,result,ic, sign);
10659 } // if (right is literal)
10661 /* shift count is unknown then we have to form a loop.
10662 * Note: we take only the lower order byte since shifting
10663 * more than 32 bits make no sense anyway, ( the
10664 * largest size of an object can be only 32 bits )
10665 * Note: we perform arithmetic shifts if the left operand is
10666 * signed and we do an (effective) right shift, i. e. we
10667 * shift in the sign bit from the left. */
10669 label_complete = newiTempLabel ( NULL );
10670 label_loop_pos = newiTempLabel ( NULL );
10671 label_loop_neg = NULL;
10672 label_negative = NULL;
10673 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10674 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10677 // additional labels needed
10678 label_loop_neg = newiTempLabel ( NULL );
10679 label_negative = newiTempLabel ( NULL );
10682 // copy source to result -- this will effectively truncate the left operand to the size of result!
10683 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10684 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10685 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10686 pic16_mov2f (AOP(result),AOP(left), offset);
10689 // if result is longer than left, fill with zeros (or sign)
10690 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10691 if (sign && AOP_SIZE(left) > 0) {
10692 // shift signed operand -- fill with sign
10693 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10694 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10695 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10696 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10697 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10700 // shift unsigned operand -- fill result with zeros
10701 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10702 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10705 } // if (size mismatch)
10707 pic16_mov2w (AOP(right), 0);
10708 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10709 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10712 // perform a shift by one (shift count is positive)
10713 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10714 // 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])
10715 pic16_emitpLabel (label_loop_pos->key);
10717 if (sign && (pos_shift == POC_RRCF)) {
10718 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10721 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10722 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10723 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10725 // perform a shift by one (shift count is positive)
10726 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10727 // 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])
10728 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10729 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10731 pic16_emitpLabel (label_loop_pos->key);
10732 if (sign && (pos_shift == POC_RRCF)) {
10733 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10736 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10737 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10738 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10739 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10743 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10745 pic16_emitpLabel (label_negative->key);
10746 // perform a shift by -1 (shift count is negative)
10747 // 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)
10749 pic16_emitpLabel (label_loop_neg->key);
10750 if (sign && (neg_shift == POC_RRCF)) {
10751 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10754 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10755 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10756 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10757 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10758 } // if (signedCount)
10760 pic16_emitpLabel (label_complete->key);
10763 pic16_freeAsmop (right,NULL,ic,TRUE);
10764 pic16_freeAsmop(left,NULL,ic,TRUE);
10765 pic16_freeAsmop(result,NULL,ic,TRUE);
10768 static void genLeftShift (iCode *ic) {
10769 genGenericShift (ic, 1);
10772 static void genRightShift (iCode *ic) {
10773 genGenericShift (ic, 0);
10778 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10779 void pic16_loadFSR0(operand *op, int lit)
10781 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10782 if (AOP_TYPE(op) == AOP_LIT) {
10783 /* handle 12 bit integers correctly */
10784 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10785 if ((val & 0x0fff) != val) {
10786 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10787 val, (val & 0x0fff) );
10790 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10792 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10795 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10796 // set up FSR0 with address of result
10797 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10798 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10802 /*----------------------------------------------------------------*/
10803 /* pic16_derefPtr - move one byte from the location ptr points to */
10804 /* to WREG (doWrite == 0) or one byte from WREG */
10805 /* to the location ptr points to (doWrite != 0) */
10806 /*----------------------------------------------------------------*/
10807 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10809 if (!IS_PTR(operandType(ptr)))
10811 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10812 else pic16_mov2w (AOP(ptr), 0);
10816 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10817 /* We might determine pointer type right here: */
10818 p_type = DCL_TYPE(operandType(ptr));
10823 if (!fsr0_setup || !*fsr0_setup)
10825 pic16_loadFSR0( ptr, 0 );
10826 if (fsr0_setup) *fsr0_setup = 1;
10829 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10831 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10835 if (AOP(ptr)->aopu.aop_reg[2]) {
10836 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10837 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10838 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10839 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10840 pic16_mov2w(AOP(ptr), 2);
10841 pic16_callGenericPointerRW(doWrite, 1);
10843 // data pointer (just 2 byte given)
10844 if (!fsr0_setup || !*fsr0_setup)
10846 pic16_loadFSR0( ptr, 0 );
10847 if (fsr0_setup) *fsr0_setup = 1;
10850 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10852 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10857 assert (0 && "invalid pointer type specified");
10862 /*-----------------------------------------------------------------*/
10863 /* genUnpackBits - generates code for unpacking bits */
10864 /*-----------------------------------------------------------------*/
10865 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10868 sym_link *etype, *letype;
10869 int blen=0, bstr=0;
10874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10875 etype = getSpec(operandType(result));
10876 letype = getSpec(operandType(left));
10878 // if(IS_BITFIELD(etype)) {
10879 blen = SPEC_BLEN(etype);
10880 bstr = SPEC_BSTR(etype);
10883 lbstr = SPEC_BSTR( letype );
10885 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10886 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10889 if((blen == 1) && (bstr < 8)
10890 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10891 /* it is a single bit, so use the appropriate bit instructions */
10892 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10894 same = pic16_sameRegs(AOP(left),AOP(result));
10895 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10896 pic16_emitpcode(POC_CLRF, op);
10898 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10899 /* workaround to reduce the extra lfsr instruction */
10900 pic16_emitpcode(POC_BTFSC,
10901 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10903 assert (PIC_IS_DATA_PTR (operandType(left)));
10904 pic16_loadFSR0 (left, 0);
10905 pic16_emitpcode(POC_BTFSC,
10906 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10909 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10910 /* unsigned bitfields result in either 0 or 1 */
10911 pic16_emitpcode(POC_INCF, op);
10913 /* signed bitfields result in either 0 or -1 */
10914 pic16_emitpcode(POC_DECF, op);
10917 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10920 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10926 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10927 // access symbol directly
10928 pic16_mov2w (AOP(left), 0);
10930 pic16_derefPtr (left, ptype, 0, NULL);
10933 /* if we have bitdisplacement then it fits */
10934 /* into this byte completely or if length is */
10935 /* less than a byte */
10936 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10938 /* shift right acc */
10941 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10942 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10944 /* VR -- normally I would use the following, but since we use the hack,
10945 * to avoid the masking from AccRsh, why not mask it right now? */
10948 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10951 /* extend signed bitfields to 8 bits */
10952 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10954 assert (blen + bstr > 0);
10955 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10956 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10961 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10965 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10966 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10967 exit(EXIT_FAILURE);
10973 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10975 int size, offset = 0, leoffset=0 ;
10977 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10978 pic16_aopOp(result, ic, TRUE);
10982 size = AOP_SIZE(result);
10983 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10987 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10988 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10989 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10994 if(AOP(left)->aopu.pcop->type == PO_DIR)
10995 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10997 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11000 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11002 // pic16_DumpOp("(result)",result);
11003 if(is_LitAOp(AOP(result))) {
11004 pic16_mov2w(AOP(left), offset); // patch 8
11005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11007 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11008 pic16_popGet(AOP(left), offset), //patch 8
11009 pic16_popGet(AOP(result), offset)));
11017 pic16_freeAsmop(result,NULL,ic,TRUE);
11022 /*-----------------------------------------------------------------*/
11023 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11024 /*-----------------------------------------------------------------*/
11025 static void genNearPointerGet (operand *left,
11029 // asmop *aop = NULL;
11030 //regs *preg = NULL ;
11031 sym_link *rtype, *retype;
11032 sym_link *ltype, *letype;
11036 rtype = operandType(result);
11037 retype= getSpec(rtype);
11038 ltype = operandType(left);
11039 letype= getSpec(ltype);
11041 pic16_aopOp(left,ic,FALSE);
11043 // pic16_DumpOp("(left)",left);
11044 // pic16_DumpOp("(result)",result);
11046 /* if left is rematerialisable and
11047 * result is not bit variable type and
11048 * the left is pointer to data space i.e
11049 * lower 128 bytes of space */
11051 if (AOP_TYPE(left) == AOP_PCODE
11052 && !IS_BITFIELD(retype)
11053 && DCL_TYPE(ltype) == POINTER) {
11055 genDataPointerGet (left,result,ic);
11056 pic16_freeAsmop(left, NULL, ic, TRUE);
11060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11061 pic16_aopOp (result,ic,TRUE);
11063 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11066 if(IS_BITFIELD( retype )
11067 && (SPEC_BLEN(operandType(result))==1)
11071 int bitstrt, bytestrt;
11073 /* if this is bitfield of size 1, see if we are checking the value
11074 * of a single bit in an if-statement,
11075 * if yes, then don't generate usual code, but execute the
11076 * genIfx directly -- VR */
11080 /* CHECK: if next iCode is IFX
11081 * and current result operand is nextic's conditional operand
11082 * and current result operand live ranges ends at nextic's key number
11084 if((nextic->op == IFX)
11085 && (result == IC_COND(nextic))
11086 && (OP_LIVETO(result) == nextic->seq)
11087 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11089 /* everything is ok then */
11090 /* find a way to optimize the genIfx iCode */
11092 bytestrt = SPEC_BSTR(operandType(result))/8;
11093 bitstrt = SPEC_BSTR(operandType(result))%8;
11095 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11097 genIfxpCOpJump(nextic, jop);
11099 pic16_freeAsmop(left, NULL, ic, TRUE);
11100 pic16_freeAsmop(result, NULL, ic, TRUE);
11106 /* if bitfield then unpack the bits */
11107 if (IS_BITFIELD(letype))
11108 genUnpackBits (result, left, NULL, POINTER);
11110 /* we have can just get the values */
11111 int size = AOP_SIZE(result);
11114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11116 pic16_loadFSR0( left, 0 );
11120 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11121 pic16_popGet(AOP(result), offset++)));
11123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11124 pic16_popGet(AOP(result), offset++)));
11130 /* now some housekeeping stuff */
11132 /* we had to allocate for this iCode */
11133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11134 pic16_freeAsmop(NULL,aop,ic,TRUE);
11136 /* we did not allocate which means left
11137 * already in a pointer register, then
11138 * if size > 0 && this could be used again
11139 * we have to point it back to where it
11141 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11142 if (AOP_SIZE(result) > 1
11143 && !OP_SYMBOL(left)->remat
11144 && ( OP_SYMBOL(left)->liveTo > ic->seq
11146 // int size = AOP_SIZE(result) - 1;
11148 // pic16_emitcode("dec","%s",rname);
11154 pic16_freeAsmop(left,NULL,ic,TRUE);
11155 pic16_freeAsmop(result,NULL,ic,TRUE);
11158 /*-----------------------------------------------------------------*/
11159 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11160 /*-----------------------------------------------------------------*/
11161 static void genPagedPointerGet (operand *left,
11166 regs *preg = NULL ;
11168 sym_link *rtype, *retype;
11170 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11172 rtype = operandType(result);
11173 retype= getSpec(rtype);
11175 pic16_aopOp(left,ic,FALSE);
11177 /* if the value is already in a pointer register
11178 then don't need anything more */
11179 if (!AOP_INPREG(AOP(left))) {
11180 /* otherwise get a free pointer register */
11182 preg = getFreePtr(ic,&aop,FALSE);
11183 pic16_emitcode("mov","%s,%s",
11185 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11186 rname = preg->name ;
11188 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11190 pic16_freeAsmop(left,NULL,ic,TRUE);
11191 pic16_aopOp (result,ic,TRUE);
11193 /* if bitfield then unpack the bits */
11194 if (IS_BITFIELD(retype))
11195 genUnpackBits (result,left,rname,PPOINTER);
11197 /* we have can just get the values */
11198 int size = AOP_SIZE(result);
11203 pic16_emitcode("movx","a,@%s",rname);
11204 pic16_aopPut(AOP(result),"a",offset);
11209 pic16_emitcode("inc","%s",rname);
11213 /* now some housekeeping stuff */
11215 /* we had to allocate for this iCode */
11216 pic16_freeAsmop(NULL,aop,ic,TRUE);
11218 /* we did not allocate which means left
11219 already in a pointer register, then
11220 if size > 0 && this could be used again
11221 we have to point it back to where it
11223 if (AOP_SIZE(result) > 1 &&
11224 !OP_SYMBOL(left)->remat &&
11225 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11227 int size = AOP_SIZE(result) - 1;
11229 pic16_emitcode("dec","%s",rname);
11234 pic16_freeAsmop(result,NULL,ic,TRUE);
11240 /* This code is not adjusted to PIC16 and fails utterly.
11241 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11243 /*-----------------------------------------------------------------*/
11244 /* genFarPointerGet - gget value from far space */
11245 /*-----------------------------------------------------------------*/
11246 static void genFarPointerGet (operand *left,
11247 operand *result, iCode *ic)
11250 sym_link *retype = getSpec(operandType(result));
11252 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11254 pic16_aopOp(left,ic,FALSE);
11256 /* if the operand is already in dptr
11257 then we do nothing else we move the value to dptr */
11258 if (AOP_TYPE(left) != AOP_STR) {
11259 /* if this is remateriazable */
11260 if (AOP_TYPE(left) == AOP_IMMD)
11261 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11262 else { /* we need to get it byte by byte */
11263 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11264 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11265 if (options.model == MODEL_FLAT24)
11267 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11271 /* so dptr know contains the address */
11272 pic16_freeAsmop(left,NULL,ic,TRUE);
11273 pic16_aopOp(result,ic,TRUE);
11275 /* if bit then unpack */
11276 if (IS_BITFIELD(retype))
11277 genUnpackBits(result,left,"dptr",FPOINTER);
11279 size = AOP_SIZE(result);
11283 pic16_emitcode("movx","a,@dptr");
11284 pic16_aopPut(AOP(result),"a",offset++);
11286 pic16_emitcode("inc","dptr");
11290 pic16_freeAsmop(result,NULL,ic,TRUE);
11295 /*-----------------------------------------------------------------*/
11296 /* genCodePointerGet - get value from code space */
11297 /*-----------------------------------------------------------------*/
11298 static void genCodePointerGet (operand *left,
11299 operand *result, iCode *ic)
11302 sym_link *retype = getSpec(operandType(result));
11304 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11306 pic16_aopOp(left,ic,FALSE);
11308 /* if the operand is already in dptr
11309 then we do nothing else we move the value to dptr */
11310 if (AOP_TYPE(left) != AOP_STR) {
11311 /* if this is remateriazable */
11312 if (AOP_TYPE(left) == AOP_IMMD)
11313 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11314 else { /* we need to get it byte by byte */
11315 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11316 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11317 if (options.model == MODEL_FLAT24)
11319 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11323 /* so dptr know contains the address */
11324 pic16_freeAsmop(left,NULL,ic,TRUE);
11325 pic16_aopOp(result,ic,FALSE);
11327 /* if bit then unpack */
11328 if (IS_BITFIELD(retype))
11329 genUnpackBits(result,left,"dptr",CPOINTER);
11331 size = AOP_SIZE(result);
11335 pic16_emitcode("clr","a");
11336 pic16_emitcode("movc","a,@a+dptr");
11337 pic16_aopPut(AOP(result),"a",offset++);
11339 pic16_emitcode("inc","dptr");
11343 pic16_freeAsmop(result,NULL,ic,TRUE);
11348 /*-----------------------------------------------------------------*/
11349 /* genGenPointerGet - gget value from generic pointer space */
11350 /*-----------------------------------------------------------------*/
11351 static void genGenPointerGet (operand *left,
11352 operand *result, iCode *ic)
11354 int size, offset, lit;
11355 sym_link *retype = getSpec(operandType(result));
11357 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11358 pic16_aopOp(left,ic,FALSE);
11359 pic16_aopOp(result,ic,FALSE);
11360 size = AOP_SIZE(result);
11362 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11364 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11366 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11367 // load FSR0 from immediate
11368 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11370 // pic16_loadFSR0( left );
11375 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11377 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11384 else { /* we need to get it byte by byte */
11385 // set up FSR0 with address from left
11386 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11387 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11393 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11402 /* if bit then unpack */
11403 if (IS_BITFIELD(retype))
11404 genUnpackBits(result,left,"BAD",GPOINTER);
11407 pic16_freeAsmop(left,NULL,ic,TRUE);
11408 pic16_freeAsmop(result,NULL,ic,TRUE);
11414 /*-----------------------------------------------------------------*/
11415 /* genGenPointerGet - gget value from generic pointer space */
11416 /*-----------------------------------------------------------------*/
11417 static void genGenPointerGet (operand *left,
11418 operand *result, iCode *ic)
11420 int size, offset, lit;
11421 sym_link *letype = getSpec(operandType(left));
11423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11424 pic16_aopOp(left,ic,FALSE);
11425 pic16_aopOp(result,ic,TRUE);
11426 size = AOP_SIZE(result);
11428 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11430 /* if bit then unpack */
11431 if (IS_BITFIELD(letype)) {
11432 genUnpackBits(result,left,"BAD",GPOINTER);
11436 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11438 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11439 // load FSR0 from immediate
11440 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11442 werror(W_POSSBUG2, __FILE__, __LINE__);
11447 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11456 } else { /* we need to get it byte by byte */
11458 /* set up WREG:PRODL:FSR0L with address from left */
11459 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11460 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11461 pic16_mov2w(AOP(left), 2);
11462 pic16_callGenericPointerRW(0, size);
11464 assignResultValue(result, size, 1);
11470 pic16_freeAsmop(left,NULL,ic,TRUE);
11471 pic16_freeAsmop(result,NULL,ic,TRUE);
11474 /*-----------------------------------------------------------------*/
11475 /* genConstPointerGet - get value from const generic pointer space */
11476 /*-----------------------------------------------------------------*/
11477 static void genConstPointerGet (operand *left,
11478 operand *result, iCode *ic)
11480 //sym_link *retype = getSpec(operandType(result));
11481 // symbol *albl = newiTempLabel(NULL); // patch 15
11482 // symbol *blbl = newiTempLabel(NULL); //
11483 // PIC_OPCODE poc; // patch 15
11487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11488 pic16_aopOp(left,ic,FALSE);
11489 pic16_aopOp(result,ic,TRUE);
11490 size = AOP_SIZE(result);
11492 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11494 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11496 // set up table pointer
11497 if( (AOP_TYPE(left) == AOP_PCODE)
11498 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11499 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11501 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11502 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11503 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11504 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11505 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11506 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11508 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11509 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11510 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11514 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11515 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11519 pic16_freeAsmop(left,NULL,ic,TRUE);
11520 pic16_freeAsmop(result,NULL,ic,TRUE);
11524 /*-----------------------------------------------------------------*/
11525 /* genPointerGet - generate code for pointer get */
11526 /*-----------------------------------------------------------------*/
11527 static void genPointerGet (iCode *ic)
11529 operand *left, *result ;
11530 sym_link *type, *etype;
11535 left = IC_LEFT(ic);
11536 result = IC_RESULT(ic) ;
11538 /* depending on the type of pointer we need to
11539 move it to the correct pointer register */
11540 type = operandType(left);
11541 etype = getSpec(type);
11544 if (IS_PTR_CONST(type))
11546 if (IS_CODEPTR(type))
11548 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11550 /* if left is of type of pointer then it is simple */
11551 if (IS_PTR(type) && !IS_FUNC(type->next))
11552 p_type = DCL_TYPE(type);
11554 /* we have to go by the storage class */
11555 p_type = PTR_TYPE(SPEC_OCLS(etype));
11557 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11559 if (SPEC_OCLS(etype)->codesp ) {
11560 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11561 //p_type = CPOINTER ;
11563 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11564 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11565 /*p_type = FPOINTER ;*/
11567 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11568 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11569 /* p_type = PPOINTER; */
11571 if (SPEC_OCLS(etype) == idata ) {
11572 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11573 /* p_type = IPOINTER; */
11575 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11576 /* p_type = POINTER ; */
11580 /* now that we have the pointer type we assign
11581 the pointer values */
11586 genNearPointerGet (left,result,ic);
11590 genPagedPointerGet(left,result,ic);
11594 /* PICs do not support FAR pointers... */
11595 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11597 genFarPointerGet (left,result,ic);
11602 genConstPointerGet (left,result,ic);
11603 //pic16_emitcodePointerGet (left,result,ic);
11608 if (IS_PTR_CONST(type))
11609 genConstPointerGet (left,result,ic);
11612 genGenPointerGet (left,result,ic);
11616 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11617 "genPointerGet: illegal pointer type");
11622 /*-----------------------------------------------------------------*/
11623 /* genPackBits - generates code for packed bit storage */
11624 /*-----------------------------------------------------------------*/
11625 static void genPackBits (sym_link *etype , operand *result,
11627 char *rname, int p_type)
11633 int shifted_and_masked = 0;
11634 unsigned long lit = (unsigned long)-1;
11637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11638 blen = SPEC_BLEN(etype);
11639 bstr = SPEC_BSTR(etype);
11641 retype = getSpec(operandType(right));
11643 if(AOP_TYPE(right) == AOP_LIT) {
11644 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11646 if((blen == 1) && (bstr < 8)) {
11647 /* it is a single bit, so use the appropriate bit instructions */
11649 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11651 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11652 /* workaround to reduce the extra lfsr instruction */
11654 pic16_emitpcode(POC_BSF,
11655 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11657 pic16_emitpcode(POC_BCF,
11658 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11661 if (PIC_IS_DATA_PTR(operandType(result))) {
11662 pic16_loadFSR0(result, 0);
11663 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11664 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11666 /* get old value */
11667 pic16_derefPtr (result, p_type, 0, NULL);
11668 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11669 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11670 /* write back new value */
11671 pic16_derefPtr (result, p_type, 1, NULL);
11677 /* IORLW below is more efficient */
11678 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11679 lit = (lit & ((1UL << blen) - 1)) << bstr;
11680 shifted_and_masked = 1;
11683 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11684 && IS_BITFIELD(retype)
11685 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11689 rblen = SPEC_BLEN( retype );
11690 rbstr = SPEC_BSTR( retype );
11692 if(IS_BITFIELD(etype)) {
11693 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11694 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11696 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11699 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11701 if(IS_BITFIELD(etype)) {
11702 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11704 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11707 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11711 /* move right to W */
11712 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11715 /* if the bit length is less than or */
11716 /* it exactly fits a byte then */
11717 if((shCnt=SPEC_BSTR(etype))
11718 || SPEC_BLEN(etype) <= 8 ) {
11719 int fsr0_setup = 0;
11721 if (blen != 8 || bstr != 0) {
11722 // we need to combine the value with the old value
11723 if(!shifted_and_masked)
11725 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11727 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11728 SPEC_BSTR(etype), SPEC_BLEN(etype));
11730 /* shift left acc, do NOT mask the result again */
11733 /* using PRODH as a temporary register here */
11734 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11737 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11738 || IS_DIRECT(result)) {
11739 /* access symbol directly */
11740 pic16_mov2w (AOP(result), 0);
11742 /* get old value */
11743 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11746 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11747 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11748 (unsigned char)(0xff >> (8-bstr))) ));
11749 if (!shifted_and_masked) {
11750 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11752 /* We have the shifted and masked (literal) right value in `lit' */
11754 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11756 } // if (blen != 8 || bstr != 0)
11758 /* write new value back */
11759 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11760 || IS_DIRECT(result)) {
11761 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11763 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11772 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11773 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11774 exit(EXIT_FAILURE);
11778 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11779 rLen = SPEC_BLEN(etype)-8;
11781 /* now generate for lengths greater than one byte */
11785 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11791 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11797 pic16_emitcode("movx","@dptr,a");
11802 DEBUGpic16_emitcode(";lcall","__gptrput");
11810 pic16_mov2w(AOP(right), offset++);
11813 /* last last was not complete */
11815 /* save the byte & read byte */
11818 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11819 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11824 pic16_emitcode ("mov","b,a");
11825 pic16_emitcode("movx","a,@dptr");
11829 pic16_emitcode ("push","b");
11830 pic16_emitcode ("push","acc");
11831 pic16_emitcode ("lcall","__gptrget");
11832 pic16_emitcode ("pop","b");
11838 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11839 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11840 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11841 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11842 // pic16_emitcode ("orl","a,b");
11845 // if (p_type == GPOINTER)
11846 // pic16_emitcode("pop","b");
11851 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11852 // pic16_emitcode("mov","@%s,a",rname);
11856 pic16_emitcode("movx","@dptr,a");
11860 DEBUGpic16_emitcode(";lcall","__gptrput");
11867 // pic16_freeAsmop(right, NULL, ic, TRUE);
11870 /*-----------------------------------------------------------------*/
11871 /* genDataPointerSet - remat pointer to data space */
11872 /*-----------------------------------------------------------------*/
11873 static void genDataPointerSet(operand *right,
11877 int size, offset = 0, resoffset=0 ;
11879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11880 pic16_aopOp(right,ic,FALSE);
11882 size = AOP_SIZE(right);
11884 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11887 if ( AOP_TYPE(result) == AOP_PCODE) {
11888 fprintf(stderr,"genDataPointerSet %s, %d\n",
11889 AOP(result)->aopu.pcop->name,
11890 (AOP(result)->aopu.pcop->type == PO_DIR)?
11891 PCOR(AOP(result)->aopu.pcop)->instance:
11892 PCOI(AOP(result)->aopu.pcop)->offset);
11896 if(AOP(result)->aopu.pcop->type == PO_DIR)
11897 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11900 if (AOP_TYPE(right) == AOP_LIT) {
11901 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11902 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11904 pic16_mov2w(AOP(right), offset);
11905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11911 pic16_freeAsmop(right,NULL,ic,TRUE);
11916 /*-----------------------------------------------------------------*/
11917 /* genNearPointerSet - pic16_emitcode for near pointer put */
11918 /*-----------------------------------------------------------------*/
11919 static void genNearPointerSet (operand *right,
11925 sym_link *ptype = operandType(result);
11926 sym_link *resetype;
11928 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11929 retype= getSpec(operandType(right));
11930 resetype = getSpec(operandType(result));
11932 pic16_aopOp(result,ic,FALSE);
11934 /* if the result is rematerializable &
11935 * in data space & not a bit variable */
11937 /* and result is not a bit variable */
11938 if (AOP_TYPE(result) == AOP_PCODE
11939 // && AOP_TYPE(result) == AOP_IMMD
11940 && DCL_TYPE(ptype) == POINTER
11941 && !IS_BITFIELD(retype)
11942 && !IS_BITFIELD(resetype)) {
11944 genDataPointerSet (right,result,ic);
11945 pic16_freeAsmop(result,NULL,ic,TRUE);
11949 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11950 pic16_aopOp(right,ic,FALSE);
11951 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11953 /* if bitfield then unpack the bits */
11954 if (IS_BITFIELD(resetype)) {
11955 genPackBits (resetype, result, right, NULL, POINTER);
11957 /* we have can just get the values */
11958 int size = AOP_SIZE(right);
11961 pic16_loadFSR0(result, 0);
11963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11965 if (AOP_TYPE(right) == AOP_LIT) {
11966 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11968 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11970 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11972 } else { // no literal
11974 pic16_emitpcode(POC_MOVFF,
11975 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11976 pic16_popCopyReg(&pic16_pc_postinc0)));
11978 pic16_emitpcode(POC_MOVFF,
11979 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11980 pic16_popCopyReg(&pic16_pc_indf0)));
11988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11989 /* now some housekeeping stuff */
11991 /* we had to allocate for this iCode */
11992 pic16_freeAsmop(NULL,aop,ic,TRUE);
11994 /* we did not allocate which means left
11995 * already in a pointer register, then
11996 * if size > 0 && this could be used again
11997 * we have to point it back to where it
11999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12000 if (AOP_SIZE(right) > 1
12001 && !OP_SYMBOL(result)->remat
12002 && ( OP_SYMBOL(result)->liveTo > ic->seq
12005 int size = AOP_SIZE(right) - 1;
12008 pic16_emitcode("decf","fsr0,f");
12009 //pic16_emitcode("dec","%s",rname);
12013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12016 pic16_freeAsmop(right,NULL,ic,TRUE);
12017 pic16_freeAsmop(result,NULL,ic,TRUE);
12020 /*-----------------------------------------------------------------*/
12021 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12022 /*-----------------------------------------------------------------*/
12023 static void genPagedPointerSet (operand *right,
12028 regs *preg = NULL ;
12032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12034 retype= getSpec(operandType(right));
12036 pic16_aopOp(result,ic,FALSE);
12038 /* if the value is already in a pointer register
12039 then don't need anything more */
12040 if (!AOP_INPREG(AOP(result))) {
12041 /* otherwise get a free pointer register */
12043 preg = getFreePtr(ic,&aop,FALSE);
12044 pic16_emitcode("mov","%s,%s",
12046 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12047 rname = preg->name ;
12049 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12051 pic16_freeAsmop(result,NULL,ic,TRUE);
12052 pic16_aopOp (right,ic,FALSE);
12054 /* if bitfield then unpack the bits */
12055 if (IS_BITFIELD(retype))
12056 genPackBits (retype,result,right,rname,PPOINTER);
12058 /* we have can just get the values */
12059 int size = AOP_SIZE(right);
12063 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12066 pic16_emitcode("movx","@%s,a",rname);
12069 pic16_emitcode("inc","%s",rname);
12075 /* now some housekeeping stuff */
12077 /* we had to allocate for this iCode */
12078 pic16_freeAsmop(NULL,aop,ic,TRUE);
12080 /* we did not allocate which means left
12081 already in a pointer register, then
12082 if size > 0 && this could be used again
12083 we have to point it back to where it
12085 if (AOP_SIZE(right) > 1 &&
12086 !OP_SYMBOL(result)->remat &&
12087 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12089 int size = AOP_SIZE(right) - 1;
12091 pic16_emitcode("dec","%s",rname);
12096 pic16_freeAsmop(right,NULL,ic,TRUE);
12102 /* This code is not adjusted to PIC16 and fails utterly...
12103 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12105 /*-----------------------------------------------------------------*/
12106 /* genFarPointerSet - set value from far space */
12107 /*-----------------------------------------------------------------*/
12108 static void genFarPointerSet (operand *right,
12109 operand *result, iCode *ic)
12112 sym_link *retype = getSpec(operandType(right));
12114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12115 pic16_aopOp(result,ic,FALSE);
12117 /* if the operand is already in dptr
12118 then we do nothing else we move the value to dptr */
12119 if (AOP_TYPE(result) != AOP_STR) {
12120 /* if this is remateriazable */
12121 if (AOP_TYPE(result) == AOP_IMMD)
12122 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12123 else { /* we need to get it byte by byte */
12124 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12125 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12126 if (options.model == MODEL_FLAT24)
12128 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12132 /* so dptr know contains the address */
12133 pic16_freeAsmop(result,NULL,ic,TRUE);
12134 pic16_aopOp(right,ic,FALSE);
12136 /* if bit then unpack */
12137 if (IS_BITFIELD(retype))
12138 genPackBits(retype,result,right,"dptr",FPOINTER);
12140 size = AOP_SIZE(right);
12144 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12146 pic16_emitcode("movx","@dptr,a");
12148 pic16_emitcode("inc","dptr");
12152 pic16_freeAsmop(right,NULL,ic,TRUE);
12156 /*-----------------------------------------------------------------*/
12157 /* genGenPointerSet - set value from generic pointer space */
12158 /*-----------------------------------------------------------------*/
12160 static void genGenPointerSet (operand *right,
12161 operand *result, iCode *ic)
12163 int i, size, offset, lit;
12164 sym_link *retype = getSpec(operandType(right));
12166 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12168 pic16_aopOp(result,ic,FALSE);
12169 pic16_aopOp(right,ic,FALSE);
12170 size = AOP_SIZE(right);
12173 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12175 /* if the operand is already in dptr
12176 then we do nothing else we move the value to dptr */
12177 if (AOP_TYPE(result) != AOP_STR) {
12178 /* if this is remateriazable */
12179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12180 // WARNING: anythig until "else" is untested!
12181 if (AOP_TYPE(result) == AOP_IMMD) {
12182 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12183 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12184 // load FSR0 from immediate
12185 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12189 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12191 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12197 else { /* we need to get it byte by byte */
12198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12199 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12201 // set up FSR0 with address of result
12202 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12203 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12205 /* hack hack! see if this the FSR. If so don't load W */
12206 if(AOP_TYPE(right) != AOP_ACC) {
12208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12210 if(AOP_TYPE(right) == AOP_LIT)
12213 // note: pic16_popGet handles sign extension
12214 for(i=0;i<size;i++) {
12215 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12217 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12219 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12224 for(i=0;i<size;i++) {
12226 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12227 pic16_popCopyReg(&pic16_pc_postinc0)));
12229 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12230 pic16_popCopyReg(&pic16_pc_indf0)));
12236 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12237 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12239 } // if (AOP_TYPE(result) != AOP_IMMD)
12241 } // if (AOP_TYPE(result) != AOP_STR)
12242 /* so dptr know contains the address */
12245 /* if bit then unpack */
12246 if (IS_BITFIELD(retype))
12247 genPackBits(retype,result,right,"dptr",GPOINTER);
12249 size = AOP_SIZE(right);
12252 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12254 // set up FSR0 with address of result
12255 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12256 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12259 if (AOP_TYPE(right) == AOP_LIT) {
12260 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12262 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12264 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12266 } else { // no literal
12268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12270 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12278 pic16_freeAsmop(right,NULL,ic,TRUE);
12279 pic16_freeAsmop(result,NULL,ic,TRUE);
12283 static void genGenPointerSet (operand *right,
12284 operand *result, iCode *ic)
12287 sym_link *retype = getSpec(operandType(result));
12289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12291 pic16_aopOp(result,ic,FALSE);
12292 pic16_aopOp(right,ic,FALSE);
12293 size = AOP_SIZE(right);
12295 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12298 /* if bit then unpack */
12299 if (IS_BITFIELD(retype)) {
12300 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12301 genPackBits(retype,result,right,"dptr",GPOINTER);
12305 size = AOP_SIZE(right);
12307 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12310 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12312 /* value of right+0 is placed on stack, which will be retrieved
12313 * by the support function thus restoring the stack. The important
12314 * thing is that there is no need to manually restore stack pointer
12316 pushaop(AOP(right), 0);
12317 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12318 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12319 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12320 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12322 /* load address to write to in WREG:FSR0H:FSR0L */
12323 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12324 pic16_popCopyReg(&pic16_pc_fsr0l)));
12325 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12326 pic16_popCopyReg(&pic16_pc_prodl)));
12327 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12329 pic16_callGenericPointerRW(1, size);
12332 pic16_freeAsmop(right,NULL,ic,TRUE);
12333 pic16_freeAsmop(result,NULL,ic,TRUE);
12336 /*-----------------------------------------------------------------*/
12337 /* genPointerSet - stores the value into a pointer location */
12338 /*-----------------------------------------------------------------*/
12339 static void genPointerSet (iCode *ic)
12341 operand *right, *result ;
12342 sym_link *type, *etype;
12347 right = IC_RIGHT(ic);
12348 result = IC_RESULT(ic) ;
12350 /* depending on the type of pointer we need to
12351 move it to the correct pointer register */
12352 type = operandType(result);
12353 etype = getSpec(type);
12355 /* if left is of type of pointer then it is simple */
12356 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12357 p_type = DCL_TYPE(type);
12360 /* we have to go by the storage class */
12361 p_type = PTR_TYPE(SPEC_OCLS(etype));
12363 /* if (SPEC_OCLS(etype)->codesp ) { */
12364 /* p_type = CPOINTER ; */
12367 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12368 /* p_type = FPOINTER ; */
12370 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12371 /* p_type = PPOINTER ; */
12373 /* if (SPEC_OCLS(etype) == idata ) */
12374 /* p_type = IPOINTER ; */
12376 /* p_type = POINTER ; */
12379 /* now that we have the pointer type we assign
12380 the pointer values */
12385 genNearPointerSet (right,result,ic);
12389 genPagedPointerSet (right,result,ic);
12393 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12395 genFarPointerSet (right,result,ic);
12400 genGenPointerSet (right,result,ic);
12404 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12405 "genPointerSet: illegal pointer type");
12409 /*-----------------------------------------------------------------*/
12410 /* genIfx - generate code for Ifx statement */
12411 /*-----------------------------------------------------------------*/
12412 static void genIfx (iCode *ic, iCode *popIc)
12414 operand *cond = IC_COND(ic);
12419 pic16_aopOp(cond,ic,FALSE);
12421 /* get the value into acc */
12422 if (AOP_TYPE(cond) != AOP_CRY)
12423 pic16_toBoolean(cond);
12426 /* the result is now in the accumulator */
12427 pic16_freeAsmop(cond,NULL,ic,TRUE);
12429 /* if there was something to be popped then do it */
12433 /* if the condition is a bit variable */
12434 if (isbit && IS_ITEMP(cond) &&
12436 genIfxJump(ic,"c");
12437 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12439 if (isbit && !IS_ITEMP(cond))
12440 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12442 genIfxJump(ic,"a");
12447 /*-----------------------------------------------------------------*/
12448 /* genAddrOf - generates code for address of */
12449 /*-----------------------------------------------------------------*/
12450 static void genAddrOf (iCode *ic)
12452 operand *result, *left;
12454 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12455 pCodeOp *pcop0, *pcop1, *pcop2;
12459 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12461 sym = OP_SYMBOL( IC_LEFT(ic) );
12464 /* get address of symbol on stack */
12465 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12467 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12468 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12471 // operands on stack are accessible via "FSR2 + index" with index
12472 // starting at 2 for arguments and growing from 0 downwards for
12473 // local variables (index == 0 is not assigned so we add one here)
12475 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12478 assert (soffs < 0);
12482 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12483 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12484 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12485 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12486 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12487 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12488 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12494 // if(pic16_debug_verbose) {
12495 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12496 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12499 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12500 size = AOP_SIZE(IC_RESULT(ic));
12502 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12503 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12504 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12507 pic16_emitpcode(POC_MOVLW, pcop0);
12508 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12509 pic16_emitpcode(POC_MOVLW, pcop1);
12510 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12511 pic16_emitpcode(POC_MOVLW, pcop2);
12512 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12515 pic16_emitpcode(POC_MOVLW, pcop0);
12516 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12517 pic16_emitpcode(POC_MOVLW, pcop1);
12518 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12520 pic16_emitpcode(POC_MOVLW, pcop0);
12521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12524 pic16_freeAsmop(left, NULL, ic, FALSE);
12526 pic16_freeAsmop(result,NULL,ic,TRUE);
12531 /*-----------------------------------------------------------------*/
12532 /* genFarFarAssign - assignment when both are in far space */
12533 /*-----------------------------------------------------------------*/
12534 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12536 int size = AOP_SIZE(right);
12539 /* first push the right side on to the stack */
12541 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12543 pic16_emitcode ("push","acc");
12546 pic16_freeAsmop(right,NULL,ic,FALSE);
12547 /* now assign DPTR to result */
12548 pic16_aopOp(result,ic,FALSE);
12549 size = AOP_SIZE(result);
12551 pic16_emitcode ("pop","acc");
12552 pic16_aopPut(AOP(result),"a",--offset);
12554 pic16_freeAsmop(result,NULL,ic,FALSE);
12559 /*-----------------------------------------------------------------*/
12560 /* genAssign - generate code for assignment */
12561 /*-----------------------------------------------------------------*/
12562 static void genAssign (iCode *ic)
12564 operand *result, *right;
12565 sym_link *restype, *rtype;
12566 int size, offset,know_W;
12567 unsigned long lit = 0L;
12569 result = IC_RESULT(ic);
12570 right = IC_RIGHT(ic) ;
12574 /* if they are the same */
12575 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12578 /* reversed order operands are aopOp'ed so that result operand
12579 * is effective in case right is a stack symbol. This maneauver
12580 * allows to use the _G.resDirect flag later */
12581 pic16_aopOp(result,ic,TRUE);
12582 pic16_aopOp(right,ic,FALSE);
12584 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12586 /* if they are the same registers */
12587 if (pic16_sameRegs(AOP(right),AOP(result)))
12590 /* if the result is a bit */
12591 if (AOP_TYPE(result) == AOP_CRY) {
12592 /* if the right size is a literal then
12593 we know what the value is */
12594 if (AOP_TYPE(right) == AOP_LIT) {
12596 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12597 pic16_popGet(AOP(result),0));
12599 if (((int) operandLitValue(right)))
12600 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12601 AOP(result)->aopu.aop_dir,
12602 AOP(result)->aopu.aop_dir);
12604 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12605 AOP(result)->aopu.aop_dir,
12606 AOP(result)->aopu.aop_dir);
12611 /* the right is also a bit variable */
12612 if (AOP_TYPE(right) == AOP_CRY) {
12613 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12614 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12615 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12620 /* we need to or */
12621 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12622 pic16_toBoolean(right);
12624 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12625 //pic16_aopPut(AOP(result),"a",0);
12629 /* bit variables done */
12631 size = AOP_SIZE(result);
12634 /* bit variables done */
12636 size = AOP_SIZE(result);
12637 restype = operandType(result);
12638 rtype = operandType(right);
12641 if(AOP_TYPE(right) == AOP_LIT) {
12642 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12644 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12646 /* patch tag for literals that are cast to pointers */
12647 if (IS_CODEPTR(restype)) {
12648 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12649 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12651 if (IS_GENPTR(restype))
12653 if (IS_CODEPTR(rtype)) {
12654 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12655 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12656 } else if (PIC_IS_DATA_PTR(rtype)) {
12657 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12658 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12659 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12660 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12661 } else if (IS_PTR(rtype)) {
12662 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12663 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12669 unsigned long lit_int;
12674 if(IS_FIXED16X16(operandType(right))) {
12675 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12677 /* take care if literal is a float */
12678 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12679 lit = info.lit_int;
12684 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12685 // sizeof(unsigned long int), sizeof(float));
12688 if (AOP_TYPE(right) == AOP_REG) {
12689 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12691 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12696 /* when do we have to read the program memory?
12697 * - if right itself is a symbol in code space
12698 * (we don't care what it points to if it's a pointer)
12699 * - AND right is not a function (we would want its address)
12701 if(AOP_TYPE(right) != AOP_LIT
12702 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12703 && !IS_FUNC(OP_SYM_TYPE(right))
12704 && !IS_ITEMP(right)) {
12706 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12707 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12709 // set up table pointer
12710 if(is_LitOp(right)) {
12711 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12712 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12713 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12714 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12715 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12716 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12717 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12719 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12720 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12721 pic16_popCopyReg(&pic16_pc_tblptrl)));
12722 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12723 pic16_popCopyReg(&pic16_pc_tblptrh)));
12724 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12725 pic16_popCopyReg(&pic16_pc_tblptru)));
12728 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12729 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12731 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12733 pic16_popGet(AOP(result),offset)));
12737 /* FIXME: for pointers we need to extend differently (according
12738 * to pointer type DATA/CODE/EEPROM/... :*/
12739 size = getSize(OP_SYM_TYPE(right));
12740 if(AOP_SIZE(result) > size) {
12741 size = AOP_SIZE(result) - size;
12743 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12751 /* VR - What is this?! */
12752 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12753 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12755 if(aopIdx(AOP(result),0) == 4) {
12756 /* this is a workaround to save value of right into wreg too,
12757 * value of wreg is going to be used later */
12758 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12759 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12764 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12768 size = AOP_SIZE(right);
12769 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12772 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12773 if(AOP_TYPE(right) == AOP_LIT) {
12775 if(know_W != (lit&0xff))
12776 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12778 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12780 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12784 } else if (AOP_TYPE(right) == AOP_CRY) {
12785 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12787 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12788 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12789 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12791 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12792 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12797 if(!_G.resDirect) { /* use this aopForSym feature */
12798 if(AOP_TYPE(result) == AOP_ACC) {
12799 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12801 if(AOP_TYPE(right) == AOP_ACC) {
12802 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12804 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12811 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12814 pic16_freeAsmop (right,NULL,ic,FALSE);
12815 pic16_freeAsmop (result,NULL,ic,TRUE);
12818 /*-----------------------------------------------------------------*/
12819 /* genJumpTab - generates code for jump table */
12820 /*-----------------------------------------------------------------*/
12821 static void genJumpTab (iCode *ic)
12826 pCodeOp *jt_offs_hi;
12831 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12832 /* get the condition into accumulator */
12833 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12835 /* multiply by three */
12836 pic16_emitcode("add","a,acc");
12837 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12839 jtab = newiTempLabel(NULL);
12840 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12841 pic16_emitcode("jmp","@a+dptr");
12842 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12845 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12846 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12848 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12849 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12850 pic16_emitpLabel(jtab->key);
12854 jt_offs = pic16_popGetTempReg(0);
12855 jt_offs_hi = pic16_popGetTempReg(1);
12856 jt_label = pic16_popGetLabel (jtab->key);
12857 //fprintf (stderr, "Creating jump table...\n");
12859 // calculate offset into jump table (idx * sizeof (GOTO))
12860 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12861 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12862 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12863 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12864 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12865 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12866 pic16_emitpcode(POC_MOVWF , jt_offs);
12868 // prepare PCLATx (set to first entry in jump table)
12869 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12870 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12871 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12872 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12873 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12875 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12876 pic16_emitpcode(POC_ADDWF , jt_offs);
12877 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12878 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12880 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12882 // release temporaries and prepare jump into table (new PCL --> WREG)
12883 pic16_emitpcode(POC_MOVFW , jt_offs);
12884 pic16_popReleaseTempReg (jt_offs_hi, 1);
12885 pic16_popReleaseTempReg (jt_offs, 0);
12887 // jump into the table
12888 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12890 pic16_emitpLabelFORCE(jtab->key);
12893 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12894 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12896 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12897 /* now generate the jump labels */
12898 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12899 jtab = setNextItem(IC_JTLABELS(ic))) {
12900 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12901 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12904 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12908 /*-----------------------------------------------------------------*/
12909 /* genMixedOperation - gen code for operators between mixed types */
12910 /*-----------------------------------------------------------------*/
12912 TSD - Written for the PIC port - but this unfortunately is buggy.
12913 This routine is good in that it is able to efficiently promote
12914 types to different (larger) sizes. Unfortunately, the temporary
12915 variables that are optimized out by this routine are sometimes
12916 used in other places. So until I know how to really parse the
12917 iCode tree, I'm going to not be using this routine :(.
12919 static int genMixedOperation (iCode *ic)
12922 operand *result = IC_RESULT(ic);
12923 sym_link *ctype = operandType(IC_LEFT(ic));
12924 operand *right = IC_RIGHT(ic);
12930 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12932 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12938 nextright = IC_RIGHT(nextic);
12939 nextleft = IC_LEFT(nextic);
12940 nextresult = IC_RESULT(nextic);
12942 pic16_aopOp(right,ic,FALSE);
12943 pic16_aopOp(result,ic,FALSE);
12944 pic16_aopOp(nextright, nextic, FALSE);
12945 pic16_aopOp(nextleft, nextic, FALSE);
12946 pic16_aopOp(nextresult, nextic, FALSE);
12948 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12950 operand *t = right;
12954 pic16_emitcode(";remove right +","");
12956 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12958 operand *t = right;
12962 pic16_emitcode(";remove left +","");
12966 big = AOP_SIZE(nextleft);
12967 small = AOP_SIZE(nextright);
12969 switch(nextic->op) {
12972 pic16_emitcode(";optimize a +","");
12973 /* if unsigned or not an integral type */
12974 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12975 pic16_emitcode(";add a bit to something","");
12978 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12980 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12981 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12982 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12984 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12992 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12993 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12994 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12997 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12999 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13000 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13001 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13002 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13003 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13006 pic16_emitcode("rlf","known_zero,w");
13013 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13014 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13015 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13017 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13027 pic16_freeAsmop(right,NULL,ic,TRUE);
13028 pic16_freeAsmop(result,NULL,ic,TRUE);
13029 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13030 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13032 nextic->generated = 1;
13039 /*-----------------------------------------------------------------*/
13040 /* genCast - gen code for casting */
13041 /*-----------------------------------------------------------------*/
13042 static void genCast (iCode *ic)
13044 operand *result = IC_RESULT(ic);
13045 sym_link *ctype = operandType(IC_LEFT(ic));
13046 sym_link *rtype = operandType(IC_RIGHT(ic));
13047 sym_link *restype = operandType(IC_RESULT(ic));
13048 operand *right = IC_RIGHT(ic);
13054 /* if they are equivalent then do nothing */
13055 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13058 pic16_aopOp(result,ic,FALSE);
13059 pic16_aopOp(right,ic,FALSE) ;
13061 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13064 /* if the result is a bit */
13065 if (AOP_TYPE(result) == AOP_CRY) {
13067 /* if the right size is a literal then
13068 * we know what the value is */
13069 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13071 if (AOP_TYPE(right) == AOP_LIT) {
13072 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13073 pic16_popGet(AOP(result),0));
13075 if (((int) operandLitValue(right)))
13076 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13077 AOP(result)->aopu.aop_dir,
13078 AOP(result)->aopu.aop_dir);
13080 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13081 AOP(result)->aopu.aop_dir,
13082 AOP(result)->aopu.aop_dir);
13086 /* the right is also a bit variable */
13087 if (AOP_TYPE(right) == AOP_CRY) {
13089 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13091 pic16_emitcode("clrc","");
13092 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13093 AOP(right)->aopu.aop_dir,
13094 AOP(right)->aopu.aop_dir);
13095 pic16_aopPut(AOP(result),"c",0);
13099 /* we need to or */
13100 if (AOP_TYPE(right) == AOP_REG) {
13101 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13102 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13103 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13105 pic16_toBoolean(right);
13106 pic16_aopPut(AOP(result),"a",0);
13110 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13113 size = AOP_SIZE(result);
13115 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13117 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13118 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13119 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13122 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13127 if(IS_BITFIELD(getSpec(restype))
13128 && IS_BITFIELD(getSpec(rtype))) {
13129 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13132 /* port from pic14 to cope with generic pointers */
13133 if (PIC_IS_TAGGED(restype))
13135 operand *result = IC_RESULT(ic);
13136 //operand *left = IC_LEFT(ic);
13137 operand *right = IC_RIGHT(ic);
13140 /* copy common part */
13141 int max, size = AOP_SIZE(result);
13142 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13143 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13148 pic16_mov2w (AOP(right), size);
13149 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13152 /* upcast into generic pointer type? */
13153 if (IS_GENPTR(restype)
13154 && !PIC_IS_TAGGED(rtype)
13155 && (AOP_SIZE(result) > max))
13157 /* determine appropriate tag for right */
13158 if (PIC_IS_DATA_PTR(rtype))
13159 tag = GPTR_TAG_DATA;
13160 else if (IS_CODEPTR(rtype))
13161 tag = GPTR_TAG_CODE;
13162 else if (PIC_IS_DATA_PTR(ctype)) {
13163 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13164 tag = GPTR_TAG_DATA;
13165 } else if (IS_CODEPTR(ctype)) {
13166 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13167 tag = GPTR_TAG_CODE;
13168 } else if (IS_PTR(rtype)) {
13169 PERFORM_ONCE(weirdcast,
13170 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13172 tag = GPTR_TAG_DATA;
13174 PERFORM_ONCE(weirdcast,
13175 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13177 tag = GPTR_TAG_DATA;
13180 assert (AOP_SIZE(result) == 3);
13181 /* zero-extend address... */
13182 for (size = max; size < AOP_SIZE(result)-1; size++)
13183 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13184 /* ...and add tag */
13185 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13186 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13187 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13188 for (size = max; size < AOP_SIZE(result)-1; size++)
13189 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13190 /* add __code tag */
13191 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13192 } else if (AOP_SIZE(result) > max) {
13193 /* extend non-pointers */
13194 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13195 pic16_addSign(result, max, 0);
13200 /* if they are the same size : or less */
13201 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13203 /* if they are in the same place */
13204 if (pic16_sameRegs(AOP(right),AOP(result)))
13207 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13209 if (IS_PTR_CONST(rtype))
13211 if (IS_CODEPTR(rtype))
13213 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13216 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13218 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13220 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13223 if(AOP_TYPE(right) == AOP_IMMD) {
13224 pCodeOp *pcop0, *pcop1, *pcop2;
13225 symbol *sym = OP_SYMBOL( right );
13227 size = AOP_SIZE(result);
13229 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13231 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13233 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13236 pic16_emitpcode(POC_MOVLW, pcop0);
13237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13238 pic16_emitpcode(POC_MOVLW, pcop1);
13239 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13240 pic16_emitpcode(POC_MOVLW, pcop2);
13241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13244 pic16_emitpcode(POC_MOVLW, pcop0);
13245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13246 pic16_emitpcode(POC_MOVLW, pcop1);
13247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13249 pic16_emitpcode(POC_MOVLW, pcop0);
13250 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13254 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13255 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13256 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13258 if(AOP_SIZE(result) < 2) {
13259 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13261 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13262 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13265 /* if they in different places then copy */
13266 size = AOP_SIZE(result);
13269 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13277 /* if the result is of type pointer */
13278 if (IS_PTR(ctype)) {
13280 sym_link *type = operandType(right);
13281 sym_link *etype = getSpec(type);
13283 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13285 /* pointer to generic pointer */
13286 if (IS_GENPTR(ctype)) {
13290 p_type = DCL_TYPE(type);
13292 /* we have to go by the storage class */
13293 p_type = PTR_TYPE(SPEC_OCLS(etype));
13295 /* if (SPEC_OCLS(etype)->codesp ) */
13296 /* p_type = CPOINTER ; */
13298 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13299 /* p_type = FPOINTER ; */
13301 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13302 /* p_type = PPOINTER; */
13304 /* if (SPEC_OCLS(etype) == idata ) */
13305 /* p_type = IPOINTER ; */
13307 /* p_type = POINTER ; */
13310 /* the first two bytes are known */
13311 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13312 size = GPTRSIZE - 1;
13315 if(offset < AOP_SIZE(right)) {
13316 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13317 pic16_mov2f(AOP(result), AOP(right), offset);
13319 if ((AOP_TYPE(right) == AOP_PCODE) &&
13320 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13321 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13322 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13325 pic16_aopPut(AOP(result),
13326 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13331 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13334 /* the last byte depending on type */
13339 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13343 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13347 pic16_emitcode(";BUG!? ","%d",__LINE__);
13352 if (GPTRSIZE > AOP_SIZE(right)) {
13353 // assume __data pointer... THIS MIGHT BE WRONG!
13354 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13356 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13361 /* this should never happen */
13362 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13363 "got unknown pointer type");
13366 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13372 /* just copy the pointers */
13373 size = AOP_SIZE(result);
13376 pic16_aopPut(AOP(result),
13377 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13386 /* so we now know that the size of destination is greater
13387 than the size of the source.
13388 Now, if the next iCode is an operator then we might be
13389 able to optimize the operation without performing a cast.
13391 if(genMixedOperation(ic))
13394 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13396 /* we move to result for the size of source */
13397 size = AOP_SIZE(right);
13402 pic16_mov2f(AOP(result), AOP(right), offset);
13406 /* now depending on the sign of the destination */
13407 size = AOP_SIZE(result) - AOP_SIZE(right);
13408 /* if unsigned or not an integral type */
13409 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13411 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13413 /* we need to extend the sign :( */
13416 /* Save one instruction of casting char to int */
13417 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13418 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13419 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13421 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13424 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13426 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13428 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13431 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13436 pic16_freeAsmop(right,NULL,ic,TRUE);
13437 pic16_freeAsmop(result,NULL,ic,TRUE);
13441 /*-----------------------------------------------------------------*/
13442 /* genDjnz - generate decrement & jump if not zero instrucion */
13443 /*-----------------------------------------------------------------*/
13444 static int genDjnz (iCode *ic, iCode *ifx)
13446 symbol *lbl, *lbl1;
13447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13452 /* if the if condition has a false label
13453 then we cannot save */
13457 /* if the minus is not of the form
13459 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13460 !IS_OP_LITERAL(IC_RIGHT(ic)))
13463 if (operandLitValue(IC_RIGHT(ic)) != 1)
13466 /* if the size of this greater than one then no
13468 if (getSize(operandType(IC_RESULT(ic))) > 1)
13471 /* otherwise we can save BIG */
13472 lbl = newiTempLabel(NULL);
13473 lbl1= newiTempLabel(NULL);
13475 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13477 if (IS_AOP_PREG(IC_RESULT(ic))) {
13478 pic16_emitcode("dec","%s",
13479 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13480 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13481 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13485 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13486 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13488 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13489 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13493 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13494 ifx->generated = 1;
13498 /*-----------------------------------------------------------------*/
13499 /* genReceive - generate code for a receive iCode */
13500 /*-----------------------------------------------------------------*/
13501 static void genReceive (iCode *ic)
13507 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13508 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13510 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13512 if (isOperandInFarSpace(IC_RESULT(ic))
13513 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13514 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13516 int size = getSize(operandType(IC_RESULT(ic)));
13517 int offset = pic16_fReturnSizePic - size;
13521 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13522 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13526 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13528 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13529 size = AOP_SIZE(IC_RESULT(ic));
13532 pic16_emitcode ("pop","acc");
13533 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13536 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13538 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13541 /* set pseudo stack pointer to where it should be - dw*/
13542 GpsuedoStkPtr = ic->parmBytes;
13544 /* setting GpsuedoStkPtr has side effects here: */
13545 /* FIXME: What's the correct size of the return(ed) value?
13546 * For now, assuming '4' as before... */
13547 assignResultValue(IC_RESULT(ic), 4, 0);
13550 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13553 /*-----------------------------------------------------------------*/
13554 /* genDummyRead - generate code for dummy read of volatiles */
13555 /*-----------------------------------------------------------------*/
13557 genDummyRead (iCode * ic)
13563 if (op && IS_SYMOP(op)) {
13564 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13565 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13568 pic16_aopOp (op, ic, FALSE);
13569 for (i=0; i < AOP_SIZE(op); i++) {
13570 // may need to protect this from the peepholer -- this is not nice but works...
13571 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13572 pic16_mov2w (AOP(op),i);
13573 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13575 pic16_freeAsmop (op, NULL, ic, TRUE);
13577 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13581 /*-----------------------------------------------------------------*/
13582 /* genpic16Code - generate code for pic16 based controllers */
13583 /*-----------------------------------------------------------------*/
13585 * At this point, ralloc.c has gone through the iCode and attempted
13586 * to optimize in a way suitable for a PIC. Now we've got to generate
13587 * PIC instructions that correspond to the iCode.
13589 * Once the instructions are generated, we'll pass through both the
13590 * peep hole optimizer and the pCode optimizer.
13591 *-----------------------------------------------------------------*/
13593 void genpic16Code (iCode *lic)
13598 lineHead = lineCurr = NULL;
13600 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13601 pic16_addpBlock(pb);
13604 /* if debug information required */
13605 if (options.debug && currFunc) {
13607 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13612 for (ic = lic ; ic ; ic = ic->next ) {
13614 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13615 if ( cln != ic->lineno ) {
13616 if ( options.debug ) {
13617 debugFile->writeCLine (ic);
13620 if(!options.noCcodeInAsm) {
13621 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13622 printCLine(ic->filename, ic->lineno)));
13628 if(options.iCodeInAsm) {
13631 /* insert here code to print iCode as comment */
13632 l = Safe_strdup(printILine(ic));
13633 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13636 /* if the result is marked as
13637 * spilt and rematerializable or code for
13638 * this has already been generated then
13640 if (resultRemat(ic) || ic->generated )
13643 /* depending on the operation */
13662 /* IPOP happens only when trying to restore a
13663 * spilt live range, if there is an ifx statement
13664 * following this pop then the if statement might
13665 * be using some of the registers being popped which
13666 * would destroy the contents of the register so
13667 * we need to check for this condition and handle it */
13669 && ic->next->op == IFX
13670 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13671 genIfx (ic->next,ic);
13689 genEndFunction (ic);
13705 pic16_genPlus (ic) ;
13709 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13710 pic16_genMinus (ic);
13726 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13730 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13736 /* note these two are xlated by algebraic equivalence
13737 * during parsing SDCC.y */
13738 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13739 "got '>=' or '<=' shouldn't have come here");
13743 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13755 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13759 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13763 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13787 genRightShift (ic);
13790 case GET_VALUE_AT_ADDRESS:
13795 if (POINTER_SET(ic))
13822 addSet(&_G.sendSet,ic);
13825 case DUMMY_READ_VOLATILE:
13835 /* now we are ready to call the
13836 peep hole optimizer */
13837 if (!options.nopeep)
13838 peepHole (&lineHead);
13840 /* now do the actual printing */
13841 printLine (lineHead, codeOutFile);
13844 DFPRINTF((stderr,"printing pBlock\n\n"));
13845 pic16_printpBlock(stdout,pb);