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 ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3764 // pic16_pBlockConvert2ISR(pb);
3767 /* emit code to setup stack frame if user enabled,
3768 * and function is not main() */
3770 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3771 if(strcmp(sym->name, "main")) {
3773 || !options.ommitFramePtr
3775 || IFFUNC_ARGS(sym->type)
3776 || FUNC_HASSTACKPARM(sym->etype)
3778 /* setup the stack frame */
3779 if(STACK_MODEL_LARGE)
3780 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3781 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3783 if(STACK_MODEL_LARGE)
3784 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3785 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3789 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3792 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3794 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3795 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3797 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3800 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3801 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3808 /* if callee-save to be used for this function
3809 * then save the registers being used in this function */
3810 // if (IFFUNC_CALLEESAVES(sym->type))
3811 if(strcmp(sym->name, "main")) {
3814 /* if any registers used */
3815 if (sym->regsUsed) {
3816 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3819 /* save the registers used */
3820 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3821 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3822 if (bitVectBitValue(sym->regsUsed,i)) {
3824 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3826 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3829 if(!pic16_regWithIdx(i)->wasUsed) {
3830 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3831 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3832 pic16_regWithIdx(i)->wasUsed = 1;
3839 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3840 for(i=0;i<sym->regsUsed->size;i++) {
3841 if(bitVectBitValue(sym->regsUsed, i)) {
3846 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3849 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3854 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3855 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3858 /*-----------------------------------------------------------------*/
3859 /* genEndFunction - generates epilogue for functions */
3860 /*-----------------------------------------------------------------*/
3861 static void genEndFunction (iCode *ic)
3863 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3867 if(IFFUNC_ISNAKED(sym->type)) {
3868 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3874 /* add code for ISCRITICAL */
3875 if(IFFUNC_ISCRITICAL(sym->type)) {
3876 /* if critical function, turn on interrupts */
3878 /* TODO: add code here -- VR */
3881 // sym->regsUsed = _G.fregsUsed;
3883 /* now we need to restore the registers */
3884 /* if any registers used */
3886 /* first restore registers that might be used for stack access */
3887 if(_G.sregsAllocSet) {
3890 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3891 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3892 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3896 if (strcmp(sym->name, "main") && sym->regsUsed) {
3899 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3900 /* restore registers used */
3901 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3902 for ( i = sym->regsUsed->size; i >= 0; i--) {
3903 if (bitVectBitValue(sym->regsUsed,i)) {
3904 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3908 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3913 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3915 if (sym->stack == 1) {
3916 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3917 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3919 // we have to add more than one...
3920 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3921 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3922 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3924 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3925 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3926 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3930 if(strcmp(sym->name, "main")) {
3932 || !options.ommitFramePtr
3934 || IFFUNC_ARGS(sym->type)
3935 || FUNC_HASSTACKPARM(sym->etype)
3937 /* restore stack frame */
3938 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3939 if(STACK_MODEL_LARGE)
3940 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3946 if (IFFUNC_ISISR(sym->type)) {
3947 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3948 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3949 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3950 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3951 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3952 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3954 if(!FUNC_ISSHADOWREGS(sym->type)) {
3955 /* do not restore interrupt vector for WREG,STATUS,BSR
3956 * for high priority interrupt, see genFunction */
3957 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3958 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3959 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3961 // _G.interruptvector = 0; /* sanity check */
3964 /* if debug then send end of function */
3965 /* if (options.debug && currFunc) */
3967 debugFile->writeEndFunction (currFunc, ic, 1);
3970 if(_G.usefastretfie)
3971 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3973 pic16_emitpcodeNULLop(POC_RETFIE);
3975 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3977 _G.usefastretfie = 0;
3981 if (IFFUNC_ISCRITICAL(sym->type)) {
3982 pic16_emitcode("setb","ea");
3985 /* if debug then send end of function */
3987 debugFile->writeEndFunction (currFunc, ic, 1);
3990 /* insert code to restore stack frame, if user enabled it
3991 * and function is not main() */
3994 pic16_emitpcodeNULLop(POC_RETURN);
3996 /* Mark the end of a function */
3997 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4001 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4003 unsigned long lit=1;
4008 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4009 if(AOP_TYPE(op) == AOP_LIT) {
4010 if(!IS_FLOAT(operandType( op ))) {
4011 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4014 unsigned long lit_int;
4018 /* take care if literal is a float */
4019 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4024 if (AOP_TYPE(op) == AOP_LIT) {
4025 /* FIXME: broken for
4026 * char __at(0x456) foo;
4028 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4029 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4030 } else if (AOP_TYPE(op) == AOP_PCODE
4031 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4032 /* char *s= "aaa"; return s; */
4033 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4034 * that the generic pointer is interpreted correctly
4035 * as referring to __code space, but this is fragile! */
4036 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4037 /* XXX: should check that dest != WREG */
4038 pic16_emitpcode(POC_MOVWF, dest);
4040 if(dest->type == PO_WREG && (offset == 0)) {
4041 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4048 /*-----------------------------------------------------------------*/
4049 /* genRet - generate code for return statement */
4050 /*-----------------------------------------------------------------*/
4051 static void genRet (iCode *ic)
4057 /* if we have no return value then
4058 * just generate the "ret" */
4063 /* we have something to return then
4064 * move the return value into place */
4065 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4066 size = AOP_SIZE(IC_LEFT(ic));
4070 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4073 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4076 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4078 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4081 /* >32-bits, setup stack and FSR0 */
4083 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4084 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4086 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4088 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4093 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4094 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4096 if(STACK_MODEL_LARGE) {
4097 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4098 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4100 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4105 /* old code, left here for reference -- VR */
4109 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4111 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4112 pic16_emitpcomment("push %s",l);
4115 DEBUGpic16_emitcode(";", "%d", __LINE__);
4116 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4117 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4119 if (strcmp(fReturn[offset],l)) {
4120 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4121 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4122 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4124 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4128 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4138 if (strcmp(fReturn[pushed],"a"))
4139 pic16_emitcode("pop",fReturn[pushed]);
4141 pic16_emitcode("pop","acc");
4147 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4150 /* generate a jump to the return label
4151 * if the next is not the return statement */
4152 if (!(ic->next && ic->next->op == LABEL
4153 && IC_LABEL(ic->next) == returnLabel)) {
4155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4156 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4160 /*-----------------------------------------------------------------*/
4161 /* genLabel - generates a label */
4162 /*-----------------------------------------------------------------*/
4163 static void genLabel (iCode *ic)
4167 /* special case never generate */
4168 if (IC_LABEL(ic) == entryLabel)
4171 pic16_emitpLabel(IC_LABEL(ic)->key);
4172 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4175 /*-----------------------------------------------------------------*/
4176 /* genGoto - generates a goto */
4177 /*-----------------------------------------------------------------*/
4179 static void genGoto (iCode *ic)
4182 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4183 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4187 /*-----------------------------------------------------------------*/
4188 /* genMultbits :- multiplication of bits */
4189 /*-----------------------------------------------------------------*/
4190 static void genMultbits (operand *left,
4196 if(!pic16_sameRegs(AOP(result),AOP(right)))
4197 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4199 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4200 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4201 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4206 /*-----------------------------------------------------------------*/
4207 /* genMultOneByte : 8 bit multiplication & division */
4208 /*-----------------------------------------------------------------*/
4209 static void genMultOneByte (operand *left,
4215 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4218 /* (if two literals, the value is computed before) */
4219 /* if one literal, literal on the right */
4220 if (AOP_TYPE(left) == AOP_LIT){
4226 /* size is already checked in genMult == 1 */
4227 // size = AOP_SIZE(result);
4229 if (AOP_TYPE(right) == AOP_LIT){
4230 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4231 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4232 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4233 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4235 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4236 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4237 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4238 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4241 pic16_genMult8X8_n (left, right,result);
4245 /*-----------------------------------------------------------------*/
4246 /* genMultOneWord : 16 bit multiplication */
4247 /*-----------------------------------------------------------------*/
4248 static void genMultOneWord (operand *left,
4253 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4254 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4256 /* (if two literals, the value is computed before)
4257 * if one literal, literal on the right */
4258 if (AOP_TYPE(left) == AOP_LIT){
4264 /* size is checked already == 2 */
4265 // size = AOP_SIZE(result);
4267 if (AOP_TYPE(right) == AOP_LIT) {
4268 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4269 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4270 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4271 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4273 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4274 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4275 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4276 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4279 pic16_genMult16X16_16(left, right,result);
4284 /*-----------------------------------------------------------------*/
4285 /* genMultOneLong : 32 bit multiplication */
4286 /*-----------------------------------------------------------------*/
4287 static void genMultOneLong (operand *left,
4292 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4293 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4295 /* (if two literals, the value is computed before)
4296 * if one literal, literal on the right */
4297 if (AOP_TYPE(left) == AOP_LIT){
4303 /* size is checked already == 4 */
4304 // size = AOP_SIZE(result);
4306 if (AOP_TYPE(right) == AOP_LIT) {
4307 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4308 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4309 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4310 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4312 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4313 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4314 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4315 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4318 pic16_genMult32X32_32(left, right,result);
4324 /*-----------------------------------------------------------------*/
4325 /* genMult - generates code for multiplication */
4326 /*-----------------------------------------------------------------*/
4327 static void genMult (iCode *ic)
4329 operand *left = IC_LEFT(ic);
4330 operand *right = IC_RIGHT(ic);
4331 operand *result= IC_RESULT(ic);
4334 /* assign the amsops */
4335 pic16_aopOp (left,ic,FALSE);
4336 pic16_aopOp (right,ic,FALSE);
4337 pic16_aopOp (result,ic,TRUE);
4339 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4341 /* special cases first *
4343 if (AOP_TYPE(left) == AOP_CRY
4344 && AOP_TYPE(right)== AOP_CRY) {
4345 genMultbits(left,right,result);
4349 /* if both are of size == 1 */
4350 if(AOP_SIZE(left) == 1
4351 && AOP_SIZE(right) == 1) {
4352 genMultOneByte(left,right,result);
4357 /* if both are of size == 2 */
4358 if(AOP_SIZE(left) == 2
4359 && AOP_SIZE(right) == 2) {
4360 genMultOneWord(left, right, result);
4364 /* if both are of size == 4 */
4365 if(AOP_SIZE(left) == 4
4366 && AOP_SIZE(right) == 4) {
4367 genMultOneLong(left, right, result);
4372 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4373 assert( !"Multiplication should have been transformed into function call!" );
4375 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4378 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4379 /* should have been converted to function call */
4383 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4385 pic16_freeAsmop(result,NULL,ic,TRUE);
4389 /*-----------------------------------------------------------------*/
4390 /* genDivbits :- division of bits */
4391 /*-----------------------------------------------------------------*/
4392 static void genDivbits (operand *left,
4399 /* the result must be bit */
4400 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4401 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4405 pic16_emitcode("div","ab");
4406 pic16_emitcode("rrc","a");
4407 pic16_aopPut(AOP(result),"c",0);
4410 /*-----------------------------------------------------------------*/
4411 /* genDivOneByte : 8 bit division */
4412 /*-----------------------------------------------------------------*/
4413 static void genDivOneByte (operand *left,
4417 sym_link *opetype = operandType(result);
4422 /* result = divident / divisor
4423 * - divident may be a register or a literal,
4424 * - divisor may be a register or a literal,
4425 * so there are 3 cases (literal / literal is optimized
4426 * by the front-end) to handle.
4427 * In addition we must handle signed and unsigned, which
4428 * result in 6 final different cases -- VR */
4432 size = AOP_SIZE(result) - 1;
4434 /* signed or unsigned */
4435 if (SPEC_USIGN(opetype)) {
4436 pCodeOp *pct1, /* count */
4439 symbol *label1, *label2, *label3;;
4442 /* unsigned is easy */
4444 pct1 = pic16_popGetTempReg(1);
4445 pct2 = pic16_popGetTempReg(1);
4446 pct3 = pic16_popGetTempReg(1);
4448 label1 = newiTempLabel(NULL);
4449 label2 = newiTempLabel(NULL);
4450 label3 = newiTempLabel(NULL);
4452 /* the following algorithm is extracted from divuint.c */
4454 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4455 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4457 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4459 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4461 pic16_emitpLabel(label1->key);
4464 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4468 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4472 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4474 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4477 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4478 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4479 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4481 pic16_emitpLabel( label3->key );
4482 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4483 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4487 pic16_emitpLabel(label2->key);
4488 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4489 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4490 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4492 /* result is in wreg */
4493 if(AOP_TYPE(result) != AOP_ACC)
4494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4496 pic16_popReleaseTempReg( pct3, 1);
4497 pic16_popReleaseTempReg( pct2, 1);
4498 pic16_popReleaseTempReg( pct1, 1);
4503 /* signed is a little bit more difficult */
4505 /* save the signs of the operands */
4506 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4508 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4509 pic16_emitcode("push","acc"); /* save it on the stack */
4511 /* now sign adjust for both left & right */
4512 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4514 lbl = newiTempLabel(NULL);
4515 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4516 pic16_emitcode("cpl","a");
4517 pic16_emitcode("inc","a");
4518 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4519 pic16_emitcode("mov","b,a");
4521 /* sign adjust left side */
4522 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4525 lbl = newiTempLabel(NULL);
4526 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4527 pic16_emitcode("cpl","a");
4528 pic16_emitcode("inc","a");
4529 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4531 /* now the division */
4532 pic16_emitcode("div","ab");
4533 /* we are interested in the lower order
4535 pic16_emitcode("mov","b,a");
4536 lbl = newiTempLabel(NULL);
4537 pic16_emitcode("pop","acc");
4538 /* if there was an over flow we don't
4539 adjust the sign of the result */
4540 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4541 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4543 pic16_emitcode("clr","a");
4544 pic16_emitcode("subb","a,b");
4545 pic16_emitcode("mov","b,a");
4546 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4548 /* now we are done */
4549 pic16_aopPut(AOP(result),"b",0);
4551 pic16_emitcode("mov","c,b.7");
4552 pic16_emitcode("subb","a,acc");
4555 pic16_aopPut(AOP(result),"a",offset++);
4560 /*-----------------------------------------------------------------*/
4561 /* genDiv - generates code for division */
4562 /*-----------------------------------------------------------------*/
4563 static void genDiv (iCode *ic)
4565 operand *left = IC_LEFT(ic);
4566 operand *right = IC_RIGHT(ic);
4567 operand *result= IC_RESULT(ic);
4569 int leftVal = 0, rightVal = 0;
4571 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4574 /* Division is a very lengthy algorithm, so it is better
4575 * to call support routines than inlining algorithm.
4576 * Division functions written here just in case someone
4577 * wants to inline and not use the support libraries -- VR */
4581 /* assign the amsops */
4582 pic16_aopOp (left,ic,FALSE);
4583 pic16_aopOp (right,ic,FALSE);
4584 pic16_aopOp (result,ic,TRUE);
4588 else if (ic->op == '%')
4591 assert( !"invalid operation requested in genDivMod" );
4593 /* get literal values */
4594 if (IS_VALOP(left)) {
4595 leftVal = (int)floatFromVal( OP_VALUE(left) );
4596 assert( leftVal >= -128 && leftVal < 256 );
4597 if (leftVal < 0) { signedLits++; }
4599 if (IS_VALOP(right)) {
4600 rightVal = (int)floatFromVal( OP_VALUE(right) );
4601 assert( rightVal >= -128 && rightVal < 256 );
4602 if (rightVal < 0) { signedLits++; }
4605 /* We should only come here to convert all
4606 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4607 * with exactly one operand being s8_t into
4608 * u8_t x u8_t -> u8_t. All other cases should have been
4609 * turned into calls to support routines beforehand... */
4610 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4611 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4613 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4614 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4616 /* Both operands are signed or negative, use _divschar
4617 * instead of _divuchar */
4618 pushaop(AOP(right), 0);
4619 pushaop(AOP(left), 0);
4621 /* call _divschar */
4622 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4626 sym = newSymbol( functions[op][0], 0 );
4628 strcpy(sym->rname, functions[op][0]);
4629 checkAddSym(&externs, sym);
4633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4634 if (AOP_SIZE(result) > 1)
4636 pic16_emitpcode(POC_MOVFF,
4637 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4638 pic16_popGet(AOP(result), 1)));
4640 pic16_addSign(result, 2, 1);
4643 /* clean up stack */
4644 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4645 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4650 /* push right operand */
4651 if (IS_VALOP(right)) {
4653 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4656 pushaop(AOP(right), 0);
4658 } else if (!IS_UNSIGNED(operandType(right))) {
4659 pic16_mov2w(AOP(right), 0);
4660 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4661 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4662 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4665 pushaop(AOP(right), 0);
4668 /* push left operand */
4669 if (IS_VALOP(left)) {
4671 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4674 pushaop(AOP(left), 0);
4676 } else if (!IS_UNSIGNED(operandType(left))) {
4677 pic16_mov2w(AOP(left),0);
4678 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4679 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4680 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4683 pushaop(AOP(left), 0);
4686 /* call _divuchar */
4687 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4691 sym = newSymbol( functions[op][1], 0 );
4693 strcpy(sym->rname, functions[op][1]);
4694 checkAddSym(&externs, sym);
4697 /* Revert negation(s) from above.
4698 * This is inefficient: if both operands are negative, this
4699 * should not touch WREG. However, determining that exactly
4700 * one operand was negated costs at least 3 instructions,
4701 * so there is nothing to be gained here, is there?
4703 * I negate WREG because either operand might share registers with
4704 * result, so assigning first might destroy an operand. */
4706 /* For the modulus operator, (a/b)*b == a shall hold.
4707 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4708 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4709 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4710 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4711 * Only invert the result if the left operand is negative (sigh).
4713 if (AOP_SIZE(result) <= 1 || !negated)
4717 if (IS_VALOP(right)) {
4719 /* we negated this operand above */
4720 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4722 } else if (!IS_UNSIGNED(operandType(right))) {
4723 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4724 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4728 if (IS_VALOP(left)) {
4730 /* we negated this operand above */
4731 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4733 } else if (!IS_UNSIGNED(operandType(left))) {
4734 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4735 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4738 /* Move result to destination. */
4739 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4741 /* Zero-extend: no operand was signed (or result is just a byte). */
4742 pic16_addSign(result, 1, 0);
4744 assert( AOP_SIZE(result) > 1 );
4745 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4748 if (IS_VALOP(right)) {
4750 /* we negated this operand above */
4751 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4753 } else if (!IS_UNSIGNED(operandType(right))) {
4754 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4755 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4759 if (IS_VALOP(left)) {
4761 /* we negated this operand above */
4762 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4764 } else if (!IS_UNSIGNED(operandType(left))) {
4765 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4766 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4769 /* Move result to destination. */
4770 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4772 /* Negate result if required. */
4773 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4774 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4777 pic16_addSign(result, 2, 1);
4780 /* clean up stack */
4781 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4782 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4787 /* special cases first */
4789 if (AOP_TYPE(left) == AOP_CRY &&
4790 AOP_TYPE(right)== AOP_CRY) {
4791 genDivbits(left,right,result);
4795 /* if both are of size == 1 */
4796 if (AOP_SIZE(left) == 1 &&
4797 AOP_SIZE(right) == 1 ) {
4798 genDivOneByte(left,right,result);
4803 /* should have been converted to function call */
4806 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4808 pic16_freeAsmop(result,NULL,ic,TRUE);
4812 /*-----------------------------------------------------------------*/
4813 /* genModbits :- modulus of bits */
4814 /*-----------------------------------------------------------------*/
4815 static void genModbits (operand *left,
4823 werror(W_POSSBUG2, __FILE__, __LINE__);
4824 /* the result must be bit */
4825 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4826 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4830 pic16_emitcode("div","ab");
4831 pic16_emitcode("mov","a,b");
4832 pic16_emitcode("rrc","a");
4833 pic16_aopPut(AOP(result),"c",0);
4836 /*-----------------------------------------------------------------*/
4837 /* genModOneByte : 8 bit modulus */
4838 /*-----------------------------------------------------------------*/
4839 static void genModOneByte (operand *left,
4843 sym_link *opetype = operandType(result);
4848 werror(W_POSSBUG2, __FILE__, __LINE__);
4850 /* signed or unsigned */
4851 if (SPEC_USIGN(opetype)) {
4852 /* unsigned is easy */
4853 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4854 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4856 pic16_emitcode("div","ab");
4857 pic16_aopPut(AOP(result),"b",0);
4861 /* signed is a little bit more difficult */
4863 /* save the signs of the operands */
4864 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4867 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4868 pic16_emitcode("push","acc"); /* save it on the stack */
4870 /* now sign adjust for both left & right */
4871 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4874 lbl = newiTempLabel(NULL);
4875 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4876 pic16_emitcode("cpl","a");
4877 pic16_emitcode("inc","a");
4878 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4879 pic16_emitcode("mov","b,a");
4881 /* sign adjust left side */
4882 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4885 lbl = newiTempLabel(NULL);
4886 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4887 pic16_emitcode("cpl","a");
4888 pic16_emitcode("inc","a");
4889 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4891 /* now the multiplication */
4892 pic16_emitcode("div","ab");
4893 /* we are interested in the lower order
4895 lbl = newiTempLabel(NULL);
4896 pic16_emitcode("pop","acc");
4897 /* if there was an over flow we don't
4898 adjust the sign of the result */
4899 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4900 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4902 pic16_emitcode("clr","a");
4903 pic16_emitcode("subb","a,b");
4904 pic16_emitcode("mov","b,a");
4905 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4907 /* now we are done */
4908 pic16_aopPut(AOP(result),"b",0);
4913 /*-----------------------------------------------------------------*/
4914 /* genMod - generates code for division */
4915 /*-----------------------------------------------------------------*/
4916 static void genMod (iCode *ic)
4918 /* Task deferred to genDiv */
4921 operand *left = IC_LEFT(ic);
4922 operand *right = IC_RIGHT(ic);
4923 operand *result= IC_RESULT(ic);
4927 /* assign the amsops */
4928 pic16_aopOp (left,ic,FALSE);
4929 pic16_aopOp (right,ic,FALSE);
4930 pic16_aopOp (result,ic,TRUE);
4932 /* special cases first */
4934 if (AOP_TYPE(left) == AOP_CRY &&
4935 AOP_TYPE(right)== AOP_CRY) {
4936 genModbits(left,right,result);
4940 /* if both are of size == 1 */
4941 if (AOP_SIZE(left) == 1 &&
4942 AOP_SIZE(right) == 1 ) {
4943 genModOneByte(left,right,result);
4947 /* should have been converted to function call */
4951 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4953 pic16_freeAsmop(result,NULL,ic,TRUE);
4957 /*-----------------------------------------------------------------*/
4958 /* genIfxJump :- will create a jump depending on the ifx */
4959 /*-----------------------------------------------------------------*/
4961 note: May need to add parameter to indicate when a variable is in bit space.
4963 static void genIfxJump (iCode *ic, char *jval)
4967 /* if true label then we jump if condition
4969 if ( IC_TRUE(ic) ) {
4971 if(strcmp(jval,"a") == 0)
4973 else if (strcmp(jval,"c") == 0)
4976 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4977 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4981 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4985 /* false label is present */
4986 if(strcmp(jval,"a") == 0)
4988 else if (strcmp(jval,"c") == 0)
4991 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4992 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4995 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4996 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5001 /* mark the icode as generated */
5005 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5009 /* if true label then we jump if condition
5011 if ( IC_TRUE(ic) ) {
5012 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5013 pic16_emitpcode(POC_BTFSC, jop);
5015 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5016 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5019 /* false label is present */
5020 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5021 pic16_emitpcode(POC_BTFSS, jop);
5023 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5024 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5028 /* mark the icode as generated */
5035 /*-----------------------------------------------------------------*/
5037 /*-----------------------------------------------------------------*/
5038 static void genSkip(iCode *ifx,int status_bit)
5040 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5044 if ( IC_TRUE(ifx) ) {
5045 switch(status_bit) {
5060 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5061 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5065 switch(status_bit) {
5079 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5080 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5087 /*-----------------------------------------------------------------*/
5089 /*-----------------------------------------------------------------*/
5090 static void genSkipc(resolvedIfx *rifx)
5092 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5102 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5103 rifx->generated = 1;
5106 #if !(USE_SIMPLE_GENCMP)
5107 /*-----------------------------------------------------------------*/
5109 /*-----------------------------------------------------------------*/
5110 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5112 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5117 if( (rifx->condition ^ invert_condition) & 1)
5122 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5123 rifx->generated = 1;
5128 /*-----------------------------------------------------------------*/
5130 /*-----------------------------------------------------------------*/
5131 static void genSkipz(iCode *ifx, int condition)
5142 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5144 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5147 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5149 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5154 #if !(USE_SIMPLE_GENCMP)
5155 /*-----------------------------------------------------------------*/
5157 /*-----------------------------------------------------------------*/
5158 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5164 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5166 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5169 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5170 rifx->generated = 1;
5175 /*-----------------------------------------------------------------*/
5176 /* genChkZeroes :- greater or less than comparison */
5177 /* For each byte in a literal that is zero, inclusive or the */
5178 /* the corresponding byte in the operand with W */
5179 /* returns true if any of the bytes are zero */
5180 /*-----------------------------------------------------------------*/
5181 static int genChkZeroes(operand *op, int lit, int size)
5188 i = (lit >> (size*8)) & 0xff;
5192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5194 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5204 /*-----------------------------------------------------------------*/
5205 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5206 /* aop (if it's NOT a literal) or from lit (if */
5207 /* aop is a literal) */
5208 /*-----------------------------------------------------------------*/
5209 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5210 if (aop->type == AOP_LIT) {
5211 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5213 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5217 /*-----------------------------------------------------------------*/
5218 /* genCmp :- greater or less than comparison */
5219 /*-----------------------------------------------------------------*/
5221 #if USE_SIMPLE_GENCMP /* { */
5223 /* genCmp performs a left < right comparison, stores
5224 * the outcome in result (if != NULL) and generates
5225 * control flow code for the ifx (if != NULL).
5227 * This version leaves in sequences like
5228 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5229 * which should be optmized by the peephole
5230 * optimizer - RN 2005-01-01 */
5231 static void genCmp (operand *left,operand *right,
5232 operand *result, iCode *ifx, int sign)
5245 assert (left && right);
5246 assert (AOP_SIZE(left) == AOP_SIZE(right));
5248 size = AOP_SIZE(right) - 1;
5249 mask = (0x100UL << (size*8)) - 1;
5250 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5255 resolveIfx (&rIfx, ifx);
5257 /* handle for special cases */
5258 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5261 /**********************************************************************
5262 * handle bits - bit compares are promoted to int compares seemingly! *
5263 **********************************************************************/
5265 // THIS IS COMPLETELY UNTESTED!
5266 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5267 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5268 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5269 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5272 // 1 < {0,1} is false --> clear C by skipping the next instruction
5273 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5274 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5275 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5276 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5277 emitCLRC; // only skipped for left=0 && right=1
5279 goto correct_result_in_carry;
5283 /*************************************************
5284 * make sure that left is register (or the like) *
5285 *************************************************/
5286 if (!isAOP_REGlike(left)) {
5287 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5288 assert (isAOP_LIT(left));
5289 assert (isAOP_REGlike(right));
5290 // swap left and right
5291 // left < right <==> right > left <==> (right >= left + 1)
5292 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5294 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5295 // MAXVALUE < right? always false
5296 if (performedLt) emitCLRC; else emitSETC;
5297 goto correct_result_in_carry;
5300 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5301 // that's why we handled it above.
5308 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5309 } else if (isAOP_LIT(right)) {
5310 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5313 assert (isAOP_REGlike(left)); // left must be register or the like
5314 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5316 /*************************************************
5317 * special cases go here *
5318 *************************************************/
5320 if (isAOP_LIT(right)) {
5322 // unsigned comparison to a literal
5323 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5325 // unsigned left < 0? always false
5326 if (performedLt) emitCLRC; else emitSETC;
5327 goto correct_result_in_carry;
5330 // signed comparison to a literal
5331 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5332 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5333 // signed left < 0x80000000? always false
5334 if (performedLt) emitCLRC; else emitSETC;
5335 goto correct_result_in_carry;
5336 } else if (lit == 0) {
5337 // compare left < 0; set CARRY if SIGNBIT(left) is set
5338 if (performedLt) emitSETC; else emitCLRC;
5339 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5340 if (performedLt) emitCLRC; else emitSETC;
5341 goto correct_result_in_carry;
5344 } // right is literal
5346 /*************************************************
5347 * perform a general case comparison *
5348 * make sure we get CARRY==1 <==> left >= right *
5349 *************************************************/
5350 // compare most significant bytes
5351 //DEBUGpc ("comparing bytes at offset %d", size);
5353 // unsigned comparison
5354 mov2w_regOrLit (AOP(right), lit, size);
5355 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5357 // signed comparison
5358 // (add 2^n to both operands then perform an unsigned comparison)
5359 if (isAOP_LIT(right)) {
5360 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5361 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5363 if (litbyte == 0x80) {
5364 // left >= 0x80 -- always true, but more bytes to come
5365 pic16_mov2w (AOP(left), size);
5366 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5369 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5370 pic16_mov2w (AOP(left), size);
5371 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5372 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5375 /* using PRODL as a temporary register here */
5376 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5377 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5378 pic16_mov2w (AOP(left), size);
5379 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5380 pic16_emitpcode (POC_MOVWF, pctemp);
5381 pic16_mov2w (AOP(right), size);
5382 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5383 pic16_emitpcode (POC_SUBFW, pctemp);
5384 //pic16_popReleaseTempReg(pctemp, 1);
5388 // compare remaining bytes (treat as unsigned case from above)
5389 templbl = newiTempLabel ( NULL );
5392 //DEBUGpc ("comparing bytes at offset %d", offs);
5393 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5394 mov2w_regOrLit (AOP(right), lit, offs);
5395 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5397 pic16_emitpLabel (templbl->key);
5398 goto result_in_carry;
5402 /****************************************************
5403 * now CARRY contains the result of the comparison: *
5404 * SUBWF sets CARRY iff *
5405 * F-W >= 0 <==> F >= W <==> !(F < W) *
5406 * (F=left, W=right) *
5407 ****************************************************/
5410 if (result && AOP_TYPE(result) != AOP_CRY) {
5411 // value will be stored
5414 // value wil only be used in the following genSkipc()
5415 rIfx.condition ^= 1;
5419 correct_result_in_carry:
5421 // assign result to variable (if neccessary)
5422 if (result && AOP_TYPE(result) != AOP_CRY) {
5423 //DEBUGpc ("assign result");
5424 size = AOP_SIZE(result);
5426 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5428 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5431 // perform conditional jump
5433 //DEBUGpc ("generate control flow");
5442 static void genCmp (operand *left,operand *right,
5443 operand *result, iCode *ifx, int sign)
5445 int size; //, offset = 0 ;
5446 unsigned long lit = 0L,i = 0;
5447 resolvedIfx rFalseIfx;
5448 // resolvedIfx rTrueIfx;
5450 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5453 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5454 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5460 resolveIfx(&rFalseIfx,ifx);
5461 truelbl = newiTempLabel(NULL);
5462 size = max(AOP_SIZE(left),AOP_SIZE(right));
5464 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5468 /* if literal is on the right then swap with left */
5469 if ((AOP_TYPE(right) == AOP_LIT)) {
5470 operand *tmp = right ;
5471 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5472 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5475 lit = (lit - 1) & mask;
5478 rFalseIfx.condition ^= 1;
5481 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5482 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5486 //if(IC_TRUE(ifx) == NULL)
5487 /* if left & right are bit variables */
5488 if (AOP_TYPE(left) == AOP_CRY &&
5489 AOP_TYPE(right) == AOP_CRY ) {
5490 assert (0 && "bit variables used in genCmp");
5491 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5492 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5494 /* subtract right from left if at the
5495 end the carry flag is set then we know that
5496 left is greater than right */
5498 symbol *lbl = newiTempLabel(NULL);
5501 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5502 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5506 if(AOP_TYPE(right) == AOP_LIT) {
5508 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5510 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5517 genSkipCond(&rFalseIfx,left,size-1,7);
5519 /* no need to compare to 0...*/
5520 /* NOTE: this is a de-generate compare that most certainly
5521 * creates some dead code. */
5522 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5524 if(ifx) ifx->generated = 1;
5531 //i = (lit >> (size*8)) & 0xff;
5532 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5534 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5536 i = ((0-lit) & 0xff);
5539 /* lit is 0x7f, all signed chars are less than
5540 * this except for 0x7f itself */
5541 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5542 genSkipz2(&rFalseIfx,0);
5544 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5545 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5546 genSkipc(&rFalseIfx);
5551 genSkipz2(&rFalseIfx,1);
5553 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5554 genSkipc(&rFalseIfx);
5558 if(ifx) ifx->generated = 1;
5562 /* chars are out of the way. now do ints and longs */
5565 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5572 genSkipCond(&rFalseIfx,left,size,7);
5573 if(ifx) ifx->generated = 1;
5578 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5580 //rFalseIfx.condition ^= 1;
5581 //genSkipCond(&rFalseIfx,left,size,7);
5582 //rFalseIfx.condition ^= 1;
5584 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5585 if(rFalseIfx.condition)
5586 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5588 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5590 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5591 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5592 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5595 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5597 if(rFalseIfx.condition) {
5599 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5605 genSkipc(&rFalseIfx);
5606 pic16_emitpLabel(truelbl->key);
5607 if(ifx) ifx->generated = 1;
5614 if( (lit & 0xff) == 0) {
5615 /* lower byte is zero */
5616 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5617 i = ((lit >> 8) & 0xff) ^0x80;
5618 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5619 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5620 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5621 genSkipc(&rFalseIfx);
5624 if(ifx) ifx->generated = 1;
5629 /* Special cases for signed longs */
5630 if( (lit & 0xffffff) == 0) {
5631 /* lower byte is zero */
5632 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5633 i = ((lit >> 8*3) & 0xff) ^0x80;
5634 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5635 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5636 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5637 genSkipc(&rFalseIfx);
5640 if(ifx) ifx->generated = 1;
5648 if(lit & (0x80 << (size*8))) {
5649 /* lit is negative */
5650 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5652 //genSkipCond(&rFalseIfx,left,size,7);
5654 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5656 if(rFalseIfx.condition)
5657 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5659 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5663 /* lit is positive */
5664 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5665 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5666 if(rFalseIfx.condition)
5667 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5669 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5674 This works, but is only good for ints.
5675 It also requires a "known zero" register.
5676 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5677 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5678 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5679 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5680 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5681 genSkipc(&rFalseIfx);
5683 pic16_emitpLabel(truelbl->key);
5684 if(ifx) ifx->generated = 1;
5688 /* There are no more special cases, so perform a general compare */
5690 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5691 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5695 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5697 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5699 //rFalseIfx.condition ^= 1;
5700 genSkipc(&rFalseIfx);
5702 pic16_emitpLabel(truelbl->key);
5704 if(ifx) ifx->generated = 1;
5711 /* sign is out of the way. So now do an unsigned compare */
5712 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5715 /* General case - compare to an unsigned literal on the right.*/
5717 i = (lit >> (size*8)) & 0xff;
5718 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5719 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5721 i = (lit >> (size*8)) & 0xff;
5724 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5726 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5728 /* this byte of the lit is zero,
5729 *if it's not the last then OR in the variable */
5731 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5736 pic16_emitpLabel(lbl->key);
5737 // pic16_emitpLabel(truelbl->key);
5738 //if(emitFinalCheck)
5739 genSkipc(&rFalseIfx);
5741 pic16_emitpLabel(truelbl->key);
5743 if(ifx) ifx->generated = 1;
5750 if(AOP_TYPE(left) == AOP_LIT) {
5751 //symbol *lbl = newiTempLabel(NULL);
5753 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5756 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5759 if((lit == 0) && (sign == 0)){
5762 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5764 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5766 genSkipz2(&rFalseIfx,0);
5767 if(ifx) ifx->generated = 1;
5774 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5775 /* degenerate compare can never be true */
5776 if(rFalseIfx.condition == 0)
5777 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5779 if(ifx) ifx->generated = 1;
5784 /* signed comparisons to a literal byte */
5786 int lp1 = (lit+1) & 0xff;
5788 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5791 rFalseIfx.condition ^= 1;
5792 genSkipCond(&rFalseIfx,right,0,7);
5795 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5796 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5797 genSkipz2(&rFalseIfx,1);
5800 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5801 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5802 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5803 rFalseIfx.condition ^= 1;
5804 genSkipc(&rFalseIfx);
5808 /* unsigned comparisons to a literal byte */
5810 switch(lit & 0xff ) {
5812 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5813 genSkipz2(&rFalseIfx,0);
5816 rFalseIfx.condition ^= 1;
5817 genSkipCond(&rFalseIfx,right,0,7);
5821 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5822 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5824 rFalseIfx.condition ^= 1;
5825 if (AOP_TYPE(result) == AOP_CRY)
5826 genSkipc(&rFalseIfx);
5828 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5829 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5835 if(ifx) ifx->generated = 1;
5836 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5842 /* Size is greater than 1 */
5850 /* this means lit = 0xffffffff, or -1 */
5853 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5854 rFalseIfx.condition ^= 1;
5855 genSkipCond(&rFalseIfx,right,size,7);
5856 if(ifx) ifx->generated = 1;
5858 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5867 if(rFalseIfx.condition) {
5868 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5869 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5872 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5874 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5878 if(rFalseIfx.condition) {
5879 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5880 pic16_emitpLabel(truelbl->key);
5882 rFalseIfx.condition ^= 1;
5883 genSkipCond(&rFalseIfx,right,s,7);
5886 if(ifx) ifx->generated = 1;
5888 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5894 if((size == 1) && (0 == (lp1&0xff))) {
5895 /* lower byte of signed word is zero */
5896 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5897 i = ((lp1 >> 8) & 0xff) ^0x80;
5898 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5899 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5900 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5902 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5904 if(ifx) ifx->generated = 1;
5907 rFalseIfx.condition ^= 1;
5908 genSkipc(&rFalseIfx);
5909 if(ifx) ifx->generated = 1;
5915 if(lit & (0x80 << (size*8))) {
5916 /* Lit is less than zero */
5917 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5918 //rFalseIfx.condition ^= 1;
5919 //genSkipCond(&rFalseIfx,left,size,7);
5920 //rFalseIfx.condition ^= 1;
5921 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5922 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5924 if(rFalseIfx.condition)
5925 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5927 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5931 /* Lit is greater than or equal to zero */
5932 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5933 //rFalseIfx.condition ^= 1;
5934 //genSkipCond(&rFalseIfx,right,size,7);
5935 //rFalseIfx.condition ^= 1;
5937 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5938 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5940 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5941 if(rFalseIfx.condition)
5942 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5948 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5949 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5955 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5957 rFalseIfx.condition ^= 1;
5958 //rFalseIfx.condition = 1;
5959 genSkipc(&rFalseIfx);
5961 pic16_emitpLabel(truelbl->key);
5963 if(ifx) ifx->generated = 1;
5966 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5973 /* compare word or long to an unsigned literal on the right.*/
5978 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5981 break; /* handled above */
5984 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5986 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5987 genSkipz2(&rFalseIfx,0);
5991 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5993 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5996 if(rFalseIfx.condition)
5997 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5999 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6002 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6003 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6005 rFalseIfx.condition ^= 1;
6006 genSkipc(&rFalseIfx);
6009 pic16_emitpLabel(truelbl->key);
6011 if(ifx) ifx->generated = 1;
6013 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6021 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6022 i = (lit >> (size*8)) & 0xff;
6024 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6025 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6028 i = (lit >> (size*8)) & 0xff;
6031 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6033 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6035 /* this byte of the lit is zero,
6036 * if it's not the last then OR in the variable */
6038 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6043 pic16_emitpLabel(lbl->key);
6045 rFalseIfx.condition ^= 1;
6047 genSkipc(&rFalseIfx);
6051 pic16_emitpLabel(truelbl->key);
6052 if(ifx) ifx->generated = 1;
6054 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6060 /* Compare two variables */
6062 DEBUGpic16_emitcode(";sign","%d",sign);
6066 /* Sigh. thus sucks... */
6070 pctemp = pic16_popGetTempReg(1);
6071 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6072 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6073 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6074 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6075 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6076 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6077 pic16_popReleaseTempReg(pctemp, 1);
6079 /* Signed char comparison */
6080 /* Special thanks to Nikolai Golovchenko for this snippet */
6081 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6082 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6083 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6084 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6085 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6086 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6088 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6089 genSkipc(&rFalseIfx);
6091 if(ifx) ifx->generated = 1;
6093 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6101 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6102 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6106 /* The rest of the bytes of a multi-byte compare */
6110 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6113 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6114 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6119 pic16_emitpLabel(lbl->key);
6121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6122 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6123 (AOP_TYPE(result) == AOP_REG)) {
6124 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6125 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6127 genSkipc(&rFalseIfx);
6129 //genSkipc(&rFalseIfx);
6130 if(ifx) ifx->generated = 1;
6133 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6141 if ((AOP_TYPE(result) != AOP_CRY)
6142 && AOP_SIZE(result)) {
6143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6145 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6147 pic16_outBitC(result);
6149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6150 /* if the result is used in the next
6151 ifx conditional branch then generate
6152 code a little differently */
6154 genIfxJump (ifx,"c");
6156 pic16_outBitC(result);
6157 /* leave the result in acc */
6162 #elif 0 /* VR version of genCmp() */ /* } else { */
6164 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6165 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6166 operand *result, int offset, int invert_op)
6170 /* check condition, > or < ?? */
6171 if(rIfx->condition != 0)invert_op ^= 1;
6173 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6175 if(!ifx)invert_op ^= 1;
6177 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6178 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6181 if(!invert_op)return POC_CPFSGT;
6182 else return POC_CPFSLT;
6185 static int compareAopfirstpass=1;
6187 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6188 operand *oper, int offset, operand *result,
6189 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6195 /* invert if there is a result to be loaded, in order to fit,
6196 * SETC/CLRC sequence */
6197 if(AOP_SIZE(result))invert_op ^= 1;
6199 // if(sign && !offset)invert_op ^= 1;
6201 // if(sign)invert_op ^= 1;
6203 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6205 if(AOP_SIZE(result) && compareAopfirstpass) {
6208 pic16_emitpcode(POC_SETF, pcop2);
6213 pic16_emitpcode(POC_CLRF, pcop2);
6219 compareAopfirstpass = 0;
6221 /* there is a bug when comparing operands with size > 1,
6222 * because higher bytes can be equal and test should be performed
6223 * to the next lower byte, current algorithm, considers operands
6224 * inequal in these cases! -- VR 20041107 */
6228 pic16_emitpcode(op, pcop);
6230 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6233 if((!sign || !offset) && AOP_SIZE(result)) {
6236 pic16_emitpcode(POC_CLRF, pcop2);
6241 pic16_emitpcode(POC_SETF, pcop2);
6246 /* don't emit final branch (offset == 0) */
6250 pic16_emitpcode(POC_RRCF, pcop2);
6252 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6255 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6256 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6257 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6259 truelbl = newiTempLabel( NULL );
6260 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6261 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6262 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6264 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6265 pic16_emitpLabel(truelbl->key);
6267 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6272 static void genCmp (operand *left, operand *right,
6273 operand *result, iCode *ifx, int sign)
6277 resolvedIfx rFalseIfx;
6278 symbol *falselbl, *tlbl;
6282 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6284 resolveIfx(&rFalseIfx, ifx);
6285 size = max(AOP_SIZE(left), AOP_SIZE(right));
6287 /* if left & right are bit variables */
6288 if(AOP_TYPE(left) == AOP_CRY
6289 && AOP_TYPE(right) == AOP_CRY ) {
6291 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6292 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6294 werror(W_POSSBUG2, __FILE__, __LINE__);
6298 /* if literal is on the right then swap with left */
6299 if((AOP_TYPE(right) == AOP_LIT)) {
6300 operand *tmp = right ;
6301 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6303 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6305 // lit = (lit - 1) & mask;
6308 rFalseIfx.condition ^= 1; /* reverse compare */
6310 if ((AOP_TYPE(left) == AOP_LIT)) {
6311 /* float compares are handled by support functions */
6312 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6315 /* actual comparing algorithm */
6316 // size = AOP_SIZE( right );
6318 falselbl = newiTempLabel( NULL );
6319 if(AOP_TYPE(left) == AOP_LIT) {
6320 /* compare to literal */
6321 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6324 pCodeOp *pct, *pct2;
6327 /* signed compare */
6328 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6330 /* using PRODL:PRODH as a temporary register here */
6331 pct = pic16_popCopyReg(&pic16_pc_prodl);
6332 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6333 tlbl = newiTempLabel( NULL );
6335 /* first compare signs:
6336 * a. if both are positive, compare just like unsigned
6337 * b. if both are negative, invert cmpop, compare just like unsigned
6338 * c. if different signs, determine the result directly */
6344 tlbl1 = newiTempLabel( NULL );
6345 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6349 /* literal is zero or positive:
6350 * a. if carry is zero, too, continue compare,
6351 * b. if carry is set, then continue depending on cmpop ^ condition:
6352 * 1. '<' return false (literal < variable),
6353 * 2. '>' return true (literal > variable) */
6354 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6355 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6358 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6359 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6363 /* literal is negative:
6364 * a. if carry is set, too, continue compare,
6365 * b. if carry is zero, then continue depending on cmpop ^ condition:
6366 * 1. '<' return true (literal < variable),
6367 * 2. '>' return false (literal > variable) */
6368 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6369 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6371 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6372 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6377 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6379 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6380 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6385 pic16_emitpLabel( tlbl1->key );
6388 compareAopfirstpass=1;
6389 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6390 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6391 // pic16_emitpcode(POC_MOVWF, pct);
6393 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6394 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6395 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6396 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6400 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6401 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6402 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6403 // pic16_emitpcode(POC_MOVWF, pct);
6405 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6406 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6407 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6408 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6409 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6412 if(ifx)ifx->generated = 1;
6414 if(AOP_SIZE(result)) {
6415 pic16_emitpLabel(tlbl->key);
6416 pic16_emitpLabel(falselbl->key);
6417 pic16_outBitOp( result, pct2 );
6419 pic16_emitpLabel(tlbl->key);
6423 /* unsigned compare */
6424 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6426 compareAopfirstpass=1;
6429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6430 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6433 if(ifx)ifx->generated = 1;
6435 if(AOP_SIZE(result)) {
6436 pic16_emitpLabel(falselbl->key);
6437 pic16_outBitC( result );
6442 /* compare registers */
6443 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6447 pCodeOp *pct, *pct2;
6449 /* signed compare */
6450 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6452 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6453 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6454 tlbl = newiTempLabel( NULL );
6456 compareAopfirstpass=1;
6459 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6460 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6461 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6462 pic16_emitpcode(POC_MOVWF, pct);
6464 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6465 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6468 /* WREG already holds left + 0x80 */
6469 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6472 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6473 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6474 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6475 pic16_emitpcode(POC_MOVWF, pct);
6477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6478 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6479 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6481 /* WREG already holds left + 0x80 */
6482 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6483 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6486 if(ifx)ifx->generated = 1;
6488 if(AOP_SIZE(result)) {
6489 pic16_emitpLabel(tlbl->key);
6490 pic16_emitpLabel(falselbl->key);
6491 pic16_outBitOp( result, pct2 );
6493 pic16_emitpLabel(tlbl->key);
6497 /* unsigned compare */
6498 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6500 compareAopfirstpass=1;
6503 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6504 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6508 if(ifx)ifx->generated = 1;
6509 if(AOP_SIZE(result)) {
6511 pic16_emitpLabel(falselbl->key);
6512 pic16_outBitC( result );
6523 /*-----------------------------------------------------------------*/
6524 /* genCmpGt :- greater than comparison */
6525 /*-----------------------------------------------------------------*/
6526 static void genCmpGt (iCode *ic, iCode *ifx)
6528 operand *left, *right, *result;
6529 sym_link *letype , *retype;
6535 right= IC_RIGHT(ic);
6536 result = IC_RESULT(ic);
6538 letype = getSpec(operandType(left));
6539 retype =getSpec(operandType(right));
6540 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6541 /* assign the amsops */
6542 pic16_aopOp (left,ic,FALSE);
6543 pic16_aopOp (right,ic,FALSE);
6544 pic16_aopOp (result,ic,TRUE);
6546 genCmp(right, left, result, ifx, sign);
6548 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6550 pic16_freeAsmop(result,NULL,ic,TRUE);
6553 /*-----------------------------------------------------------------*/
6554 /* genCmpLt - less than comparisons */
6555 /*-----------------------------------------------------------------*/
6556 static void genCmpLt (iCode *ic, iCode *ifx)
6558 operand *left, *right, *result;
6559 sym_link *letype , *retype;
6565 right= IC_RIGHT(ic);
6566 result = IC_RESULT(ic);
6568 letype = getSpec(operandType(left));
6569 retype =getSpec(operandType(right));
6570 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6572 /* assign the amsops */
6573 pic16_aopOp (left,ic,FALSE);
6574 pic16_aopOp (right,ic,FALSE);
6575 pic16_aopOp (result,ic,TRUE);
6577 genCmp(left, right, result, ifx, sign);
6579 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6581 pic16_freeAsmop(result,NULL,ic,TRUE);
6586 // FIXME reenable literal optimisation when the pic16 port is stable
6588 /*-----------------------------------------------------------------*/
6589 /* genc16bit2lit - compare a 16 bit value to a literal */
6590 /*-----------------------------------------------------------------*/
6591 static void genc16bit2lit(operand *op, int lit, int offset)
6595 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6596 if( (lit&0xff) == 0)
6601 switch( BYTEofLONG(lit,i)) {
6603 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6606 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6609 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6612 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6613 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6618 switch( BYTEofLONG(lit,i)) {
6620 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6624 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6628 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6631 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6633 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6642 /*-----------------------------------------------------------------*/
6643 /* gencjneshort - compare and jump if not equal */
6644 /*-----------------------------------------------------------------*/
6645 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6647 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6649 int res_offset = 0; /* the result may be a different size then left or right */
6650 int res_size = AOP_SIZE(result);
6652 symbol *lbl, *lbl_done;
6654 unsigned long lit = 0L;
6655 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6657 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6658 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6660 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6661 resolveIfx(&rIfx,ifx);
6662 lbl = newiTempLabel(NULL);
6663 lbl_done = newiTempLabel(NULL);
6666 /* if the left side is a literal or
6667 if the right is in a pointer register and left
6669 if ((AOP_TYPE(left) == AOP_LIT) ||
6670 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6675 if(AOP_TYPE(right) == AOP_LIT)
6676 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6678 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6679 preserve_result = 1;
6681 if(result && !preserve_result)
6684 for(i = 0; i < AOP_SIZE(result); i++)
6685 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6689 /* if the right side is a literal then anything goes */
6690 if (AOP_TYPE(right) == AOP_LIT &&
6691 AOP_TYPE(left) != AOP_DIR ) {
6694 genc16bit2lit(left, lit, 0);
6696 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6702 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6703 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6705 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6709 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6711 if(res_offset < res_size-1)
6719 /* if the right side is in a register or in direct space or
6720 if the left is a pointer register & right is not */
6721 else if (AOP_TYPE(right) == AOP_REG ||
6722 AOP_TYPE(right) == AOP_DIR ||
6723 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6724 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6725 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6726 int lbl_key = lbl->key;
6729 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6730 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6732 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6733 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6734 __FUNCTION__,__LINE__);
6738 /* switch(size) { */
6740 /* genc16bit2lit(left, lit, 0); */
6742 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6747 if((AOP_TYPE(left) == AOP_DIR) &&
6748 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6750 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6751 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6753 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6755 switch (lit & 0xff) {
6757 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6760 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6761 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6766 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6767 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6768 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6769 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6773 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6774 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6779 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6782 if(AOP_TYPE(result) == AOP_CRY) {
6783 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6788 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6790 /* fix me. probably need to check result size too */
6791 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6796 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6797 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6804 if(res_offset < res_size-1)
6809 } else if(AOP_TYPE(right) == AOP_REG &&
6810 AOP_TYPE(left) != AOP_DIR){
6813 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6814 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6815 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6820 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6822 if(res_offset < res_size-1)
6827 /* right is a pointer reg need both a & b */
6829 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6831 pic16_emitcode("mov","b,%s",l);
6832 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6833 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6838 if(result && preserve_result)
6841 for(i = 0; i < AOP_SIZE(result); i++)
6842 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6845 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6847 if(result && preserve_result)
6848 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6851 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6853 pic16_emitpLabel(lbl->key);
6855 if(result && preserve_result)
6858 for(i = 0; i < AOP_SIZE(result); i++)
6859 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6861 pic16_emitpLabel(lbl_done->key);
6864 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6872 /*-----------------------------------------------------------------*/
6873 /* gencjne - compare and jump if not equal */
6874 /*-----------------------------------------------------------------*/
6875 static void gencjne(operand *left, operand *right, iCode *ifx)
6877 symbol *tlbl = newiTempLabel(NULL);
6879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6880 gencjneshort(left, right, lbl);
6882 pic16_emitcode("mov","a,%s",one);
6883 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6884 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6885 pic16_emitcode("clr","a");
6886 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6888 pic16_emitpLabel(lbl->key);
6889 pic16_emitpLabel(tlbl->key);
6895 /*-----------------------------------------------------------------*/
6896 /* is_LitOp - check if operand has to be treated as literal */
6897 /*-----------------------------------------------------------------*/
6898 static bool is_LitOp(operand *op)
6900 return ((AOP_TYPE(op) == AOP_LIT)
6901 || ( (AOP_TYPE(op) == AOP_PCODE)
6902 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6903 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6906 /*-----------------------------------------------------------------*/
6907 /* is_LitAOp - check if operand has to be treated as literal */
6908 /*-----------------------------------------------------------------*/
6909 static bool is_LitAOp(asmop *aop)
6911 return ((aop->type == AOP_LIT)
6912 || ( (aop->type == AOP_PCODE)
6913 && ( (aop->aopu.pcop->type == PO_LITERAL)
6914 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6919 /*-----------------------------------------------------------------*/
6920 /* genCmpEq - generates code for equal to */
6921 /*-----------------------------------------------------------------*/
6922 static void genCmpEq (iCode *ic, iCode *ifx)
6924 operand *left, *right, *result;
6925 symbol *falselbl = newiTempLabel(NULL);
6926 symbol *donelbl = newiTempLabel(NULL);
6928 int preserve_result = 0;
6929 int generate_result = 0;
6931 unsigned long lit = -1;
6935 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6936 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6937 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6939 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6941 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6943 werror(W_POSSBUG2, __FILE__, __LINE__);
6944 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6945 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6949 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6951 operand *tmp = right ;
6956 if (AOP_TYPE(right) == AOP_LIT) {
6957 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6960 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6961 preserve_result = 1;
6963 if(result && AOP_SIZE(result))
6964 generate_result = 1;
6966 if(generate_result && !preserve_result)
6968 for(i = 0; i < AOP_SIZE(result); i++)
6969 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6972 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6973 for(i=0; i < AOP_SIZE(left); i++)
6975 if(AOP_TYPE(left) != AOP_ACC)
6978 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6980 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6982 if(is_LitOp(right)) {
6983 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6984 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6987 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6989 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6994 if(generate_result && preserve_result)
6996 for(i = 0; i < AOP_SIZE(result); i++)
6997 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7001 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7003 if(generate_result && preserve_result)
7004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7006 if(ifx && IC_TRUE(ifx))
7007 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7009 if(ifx && IC_FALSE(ifx))
7010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7012 pic16_emitpLabel(falselbl->key);
7016 if(ifx && IC_FALSE(ifx))
7017 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7019 if(generate_result && preserve_result)
7021 for(i = 0; i < AOP_SIZE(result); i++)
7022 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7025 pic16_emitpLabel(donelbl->key);
7031 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7033 pic16_freeAsmop(result,NULL,ic,TRUE);
7039 // old version kept for reference
7041 /*-----------------------------------------------------------------*/
7042 /* genCmpEq - generates code for equal to */
7043 /*-----------------------------------------------------------------*/
7044 static void genCmpEq (iCode *ic, iCode *ifx)
7046 operand *left, *right, *result;
7047 unsigned long lit = 0L;
7049 symbol *falselbl = newiTempLabel(NULL);
7052 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7055 DEBUGpic16_emitcode ("; ifx is non-null","");
7057 DEBUGpic16_emitcode ("; ifx is null","");
7059 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7060 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7061 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7063 size = max(AOP_SIZE(left),AOP_SIZE(right));
7065 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7067 /* if literal, literal on the right or
7068 if the right is in a pointer register and left
7070 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7071 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7072 operand *tmp = right ;
7078 if(ifx && !AOP_SIZE(result)){
7080 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7081 /* if they are both bit variables */
7082 if (AOP_TYPE(left) == AOP_CRY &&
7083 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7084 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7085 if(AOP_TYPE(right) == AOP_LIT){
7086 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7088 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7089 pic16_emitcode("cpl","c");
7090 } else if(lit == 1L) {
7091 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7093 pic16_emitcode("clr","c");
7095 /* AOP_TYPE(right) == AOP_CRY */
7097 symbol *lbl = newiTempLabel(NULL);
7098 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7099 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7100 pic16_emitcode("cpl","c");
7101 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7103 /* if true label then we jump if condition
7105 tlbl = newiTempLabel(NULL);
7106 if ( IC_TRUE(ifx) ) {
7107 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7108 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7110 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7111 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7113 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7116 /* left and right are both bit variables, result is carry */
7119 resolveIfx(&rIfx,ifx);
7121 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7122 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7123 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7124 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7129 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7131 /* They're not both bit variables. Is the right a literal? */
7132 if(AOP_TYPE(right) == AOP_LIT) {
7133 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7138 switch(lit & 0xff) {
7140 if ( IC_TRUE(ifx) ) {
7141 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7143 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7145 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7146 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7150 if ( IC_TRUE(ifx) ) {
7151 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7153 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7155 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7156 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7160 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7162 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7167 /* end of size == 1 */
7171 genc16bit2lit(left,lit,offset);
7174 /* end of size == 2 */
7179 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7180 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7181 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7182 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7185 /* search for patterns that can be optimized */
7187 genc16bit2lit(left,lit,0);
7191 emitSKPZ; // if hi word unequal
7193 emitSKPNZ; // if hi word equal
7195 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7196 genc16bit2lit(left,lit,2);
7199 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7200 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7204 pic16_emitpLabel(falselbl->key);
7213 } else if(AOP_TYPE(right) == AOP_CRY ) {
7214 /* we know the left is not a bit, but that the right is */
7215 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7216 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7217 pic16_popGet(AOP(right),offset));
7218 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7220 /* if the two are equal, then W will be 0 and the Z bit is set
7221 * we could test Z now, or go ahead and check the high order bytes if
7222 * the variable we're comparing is larger than a byte. */
7225 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7227 if ( IC_TRUE(ifx) ) {
7229 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7230 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7233 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7234 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7238 /* They're both variables that are larger than bits */
7241 tlbl = newiTempLabel(NULL);
7244 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7245 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7247 if ( IC_TRUE(ifx) ) {
7251 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7253 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7254 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7258 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7261 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7262 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7267 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7269 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7270 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7274 if(s>1 && IC_TRUE(ifx)) {
7275 pic16_emitpLabel(tlbl->key);
7276 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7280 /* mark the icode as generated */
7285 /* if they are both bit variables */
7286 if (AOP_TYPE(left) == AOP_CRY &&
7287 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7288 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7289 if(AOP_TYPE(right) == AOP_LIT){
7290 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7292 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7293 pic16_emitcode("cpl","c");
7294 } else if(lit == 1L) {
7295 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7297 pic16_emitcode("clr","c");
7299 /* AOP_TYPE(right) == AOP_CRY */
7301 symbol *lbl = newiTempLabel(NULL);
7302 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7303 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7304 pic16_emitcode("cpl","c");
7305 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7308 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7309 pic16_outBitC(result);
7313 genIfxJump (ifx,"c");
7316 /* if the result is used in an arithmetic operation
7317 then put the result in place */
7318 pic16_outBitC(result);
7321 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7322 gencjne(left,right,result,ifx);
7325 gencjne(left,right,newiTempLabel(NULL));
7327 if(IC_TRUE(ifx)->key)
7328 gencjne(left,right,IC_TRUE(ifx)->key);
7330 gencjne(left,right,IC_FALSE(ifx)->key);
7334 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7335 pic16_aopPut(AOP(result),"a",0);
7340 genIfxJump (ifx,"a");
7344 /* if the result is used in an arithmetic operation
7345 then put the result in place */
7347 if (AOP_TYPE(result) != AOP_CRY)
7348 pic16_outAcc(result);
7350 /* leave the result in acc */
7354 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7356 pic16_freeAsmop(result,NULL,ic,TRUE);
7360 /*-----------------------------------------------------------------*/
7361 /* ifxForOp - returns the icode containing the ifx for operand */
7362 /*-----------------------------------------------------------------*/
7363 static iCode *ifxForOp ( operand *op, iCode *ic )
7367 /* if true symbol then needs to be assigned */
7368 if (IS_TRUE_SYMOP(op))
7371 /* if this has register type condition and
7372 the next instruction is ifx with the same operand
7373 and live to of the operand is upto the ifx only then */
7375 && ic->next->op == IFX
7376 && IC_COND(ic->next)->key == op->key
7377 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7379 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7385 ic->next->op == IFX &&
7386 IC_COND(ic->next)->key == op->key) {
7387 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7392 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7394 ic->next->op == IFX)
7395 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7398 ic->next->op == IFX &&
7399 IC_COND(ic->next)->key == op->key) {
7400 DEBUGpic16_emitcode ("; "," key is okay");
7401 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7402 OP_SYMBOL(op)->liveTo,
7407 /* the code below is completely untested
7408 * it just allows ulong2fs.c compile -- VR */
7411 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7412 __FILE__, __FUNCTION__, __LINE__);
7414 /* if this has register type condition and
7415 the next instruction is ifx with the same operand
7416 and live to of the operand is upto the ifx only then */
7418 ic->next->op == IFX &&
7419 IC_COND(ic->next)->key == op->key &&
7420 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7424 ic->next->op == IFX &&
7425 IC_COND(ic->next)->key == op->key) {
7426 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7430 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7431 __FILE__, __FUNCTION__, __LINE__);
7433 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7438 /*-----------------------------------------------------------------*/
7439 /* genAndOp - for && operation */
7440 /*-----------------------------------------------------------------*/
7441 static void genAndOp (iCode *ic)
7443 operand *left,*right, *result;
7448 /* note here that && operations that are in an
7449 if statement are taken away by backPatchLabels
7450 only those used in arthmetic operations remain */
7451 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7452 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7453 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7455 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7457 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7458 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7459 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7461 /* if both are bit variables */
7462 /* if (AOP_TYPE(left) == AOP_CRY && */
7463 /* AOP_TYPE(right) == AOP_CRY ) { */
7464 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7465 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7466 /* pic16_outBitC(result); */
7468 /* tlbl = newiTempLabel(NULL); */
7469 /* pic16_toBoolean(left); */
7470 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7471 /* pic16_toBoolean(right); */
7472 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7473 /* pic16_outBitAcc(result); */
7476 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7478 pic16_freeAsmop(result,NULL,ic,TRUE);
7482 /*-----------------------------------------------------------------*/
7483 /* genOrOp - for || operation */
7484 /*-----------------------------------------------------------------*/
7487 modified this code, but it doesn't appear to ever get called
7490 static void genOrOp (iCode *ic)
7492 operand *left,*right, *result;
7497 /* note here that || operations that are in an
7498 if statement are taken away by backPatchLabels
7499 only those used in arthmetic operations remain */
7500 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7501 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7502 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7504 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7506 /* if both are bit variables */
7507 if (AOP_TYPE(left) == AOP_CRY &&
7508 AOP_TYPE(right) == AOP_CRY ) {
7509 pic16_emitcode("clrc","");
7510 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7511 AOP(left)->aopu.aop_dir,
7512 AOP(left)->aopu.aop_dir);
7513 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7514 AOP(right)->aopu.aop_dir,
7515 AOP(right)->aopu.aop_dir);
7516 pic16_emitcode("setc","");
7519 tlbl = newiTempLabel(NULL);
7520 pic16_toBoolean(left);
7522 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7523 pic16_toBoolean(right);
7524 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7526 pic16_outBitAcc(result);
7529 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7531 pic16_freeAsmop(result,NULL,ic,TRUE);
7534 /*-----------------------------------------------------------------*/
7535 /* isLiteralBit - test if lit == 2^n */
7536 /*-----------------------------------------------------------------*/
7537 static int isLiteralBit(unsigned long lit)
7539 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7540 0x100L,0x200L,0x400L,0x800L,
7541 0x1000L,0x2000L,0x4000L,0x8000L,
7542 0x10000L,0x20000L,0x40000L,0x80000L,
7543 0x100000L,0x200000L,0x400000L,0x800000L,
7544 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7545 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7549 for(idx = 0; idx < 32; idx++)
7555 /*-----------------------------------------------------------------*/
7556 /* continueIfTrue - */
7557 /*-----------------------------------------------------------------*/
7558 static void continueIfTrue (iCode *ic)
7562 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7566 /*-----------------------------------------------------------------*/
7568 /*-----------------------------------------------------------------*/
7569 static void jumpIfTrue (iCode *ic)
7573 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7577 /*-----------------------------------------------------------------*/
7578 /* jmpTrueOrFalse - */
7579 /*-----------------------------------------------------------------*/
7580 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7582 // ugly but optimized by peephole
7585 symbol *nlbl = newiTempLabel(NULL);
7586 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7587 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7588 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7589 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7591 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7592 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7597 /*-----------------------------------------------------------------*/
7598 /* genAnd - code for and */
7599 /*-----------------------------------------------------------------*/
7600 static void genAnd (iCode *ic, iCode *ifx)
7602 operand *left, *right, *result;
7604 unsigned long lit = 0L;
7610 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7611 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7612 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7614 resolveIfx(&rIfx,ifx);
7616 /* if left is a literal & right is not then exchange them */
7617 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7618 AOP_NEEDSACC(left)) {
7619 operand *tmp = right ;
7624 /* if result = right then exchange them */
7625 if(pic16_sameRegs(AOP(result),AOP(right))){
7626 operand *tmp = right ;
7631 /* if right is bit then exchange them */
7632 if (AOP_TYPE(right) == AOP_CRY &&
7633 AOP_TYPE(left) != AOP_CRY){
7634 operand *tmp = right ;
7638 if(AOP_TYPE(right) == AOP_LIT)
7639 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7641 size = AOP_SIZE(result);
7643 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7646 // result = bit & yy;
7647 if (AOP_TYPE(left) == AOP_CRY){
7648 // c = bit & literal;
7649 if(AOP_TYPE(right) == AOP_LIT){
7651 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7654 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7657 if(size && (AOP_TYPE(result) == AOP_CRY)){
7658 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7661 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7665 pic16_emitcode("clr","c");
7668 if (AOP_TYPE(right) == AOP_CRY){
7670 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7671 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7674 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7676 pic16_emitcode("rrc","a");
7677 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7683 pic16_outBitC(result);
7685 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7686 genIfxJump(ifx, "c");
7690 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7691 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7692 if((AOP_TYPE(right) == AOP_LIT) &&
7693 (AOP_TYPE(result) == AOP_CRY) &&
7694 (AOP_TYPE(left) != AOP_CRY)){
7695 int posbit = isLiteralBit(lit);
7699 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7702 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7708 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7709 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7711 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7712 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7715 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7716 size = AOP_SIZE(left);
7719 int bp = posbit, ofs=0;
7726 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7727 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7731 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7732 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7734 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7741 symbol *tlbl = newiTempLabel(NULL);
7742 int sizel = AOP_SIZE(left);
7748 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7750 /* patch provided by Aaron Colwell */
7751 if((posbit = isLiteralBit(bytelit)) != 0) {
7752 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7753 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7754 (posbit-1),0, PO_GPR_REGISTER));
7756 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7757 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7759 if (bytelit == 0xff) {
7760 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7761 * a peephole could optimize it out -- VR */
7762 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7764 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7765 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7768 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7769 pic16_popGetLabel(tlbl->key));
7773 /* old code, left here for reference -- VR 09/2004 */
7774 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7776 if((posbit = isLiteralBit(bytelit)) != 0)
7777 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7779 if(bytelit != 0x0FFL)
7780 pic16_emitcode("anl","a,%s",
7781 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7782 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7788 // bit = left & literal
7791 pic16_emitpLabel(tlbl->key);
7793 // if(left & literal)
7796 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7799 pic16_emitpLabel(tlbl->key);
7804 pic16_outBitC(result);
7808 /* if left is same as result */
7809 if(pic16_sameRegs(AOP(result),AOP(left))){
7811 for(;size--; offset++,lit>>=8) {
7812 if(AOP_TYPE(right) == AOP_LIT){
7813 switch(lit & 0xff) {
7815 /* and'ing with 0 has clears the result */
7816 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7817 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7820 /* and'ing with 0xff is a nop when the result and left are the same */
7825 int p = pic16_my_powof2( (~lit) & 0xff );
7827 /* only one bit is set in the literal, so use a bcf instruction */
7828 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7829 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7832 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7833 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7834 if(know_W != (lit&0xff))
7835 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7837 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7842 if (AOP_TYPE(left) == AOP_ACC) {
7843 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7845 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7846 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7853 // left & result in different registers
7854 if(AOP_TYPE(result) == AOP_CRY){
7856 // if(size), result in bit
7857 // if(!size && ifx), conditional oper: if(left & right)
7858 symbol *tlbl = newiTempLabel(NULL);
7859 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7861 pic16_emitcode("setb","c");
7863 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7864 pic16_emitcode("anl","a,%s",
7865 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7866 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7871 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7872 pic16_outBitC(result);
7874 jmpTrueOrFalse(ifx, tlbl);
7876 for(;(size--);offset++) {
7878 // result = left & right
7879 if(AOP_TYPE(right) == AOP_LIT){
7880 int t = (lit >> (offset*8)) & 0x0FFL;
7883 pic16_emitcode("clrf","%s",
7884 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7885 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7888 pic16_emitcode("movf","%s,w",
7889 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890 pic16_emitcode("movwf","%s",
7891 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7892 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7893 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7896 pic16_emitcode("movlw","0x%x",t);
7897 pic16_emitcode("andwf","%s,w",
7898 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7899 pic16_emitcode("movwf","%s",
7900 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7902 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7903 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7904 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7909 if (AOP_TYPE(left) == AOP_ACC) {
7910 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7911 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7913 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914 pic16_emitcode("andwf","%s,w",
7915 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7916 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7917 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7919 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7920 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7926 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7927 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7928 pic16_freeAsmop(result,NULL,ic,TRUE);
7931 /*-----------------------------------------------------------------*/
7932 /* genOr - code for or */
7933 /*-----------------------------------------------------------------*/
7934 static void genOr (iCode *ic, iCode *ifx)
7936 operand *left, *right, *result;
7938 unsigned long lit = 0L;
7940 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7943 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7944 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7945 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7947 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7949 /* if left is a literal & right is not then exchange them */
7950 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7951 AOP_NEEDSACC(left)) {
7952 operand *tmp = right ;
7957 /* if result = right then exchange them */
7958 if(pic16_sameRegs(AOP(result),AOP(right))){
7959 operand *tmp = right ;
7964 /* if right is bit then exchange them */
7965 if (AOP_TYPE(right) == AOP_CRY &&
7966 AOP_TYPE(left) != AOP_CRY){
7967 operand *tmp = right ;
7972 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7974 if(AOP_TYPE(right) == AOP_LIT)
7975 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7977 size = AOP_SIZE(result);
7981 if (AOP_TYPE(left) == AOP_CRY){
7982 if(AOP_TYPE(right) == AOP_LIT){
7983 // c = bit & literal;
7985 // lit != 0 => result = 1
7986 if(AOP_TYPE(result) == AOP_CRY){
7988 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7989 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7990 // AOP(result)->aopu.aop_dir,
7991 // AOP(result)->aopu.aop_dir);
7993 continueIfTrue(ifx);
7997 // lit == 0 => result = left
7998 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8000 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8003 if (AOP_TYPE(right) == AOP_CRY){
8004 if(pic16_sameRegs(AOP(result),AOP(left))){
8006 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8007 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8008 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8010 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8011 AOP(result)->aopu.aop_dir,
8012 AOP(result)->aopu.aop_dir);
8013 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8014 AOP(right)->aopu.aop_dir,
8015 AOP(right)->aopu.aop_dir);
8016 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8017 AOP(result)->aopu.aop_dir,
8018 AOP(result)->aopu.aop_dir);
8020 if( AOP_TYPE(result) == AOP_ACC) {
8021 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8022 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8023 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8024 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8028 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8029 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8030 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8031 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8033 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8034 AOP(result)->aopu.aop_dir,
8035 AOP(result)->aopu.aop_dir);
8036 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8037 AOP(right)->aopu.aop_dir,
8038 AOP(right)->aopu.aop_dir);
8039 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8040 AOP(left)->aopu.aop_dir,
8041 AOP(left)->aopu.aop_dir);
8042 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8043 AOP(result)->aopu.aop_dir,
8044 AOP(result)->aopu.aop_dir);
8049 symbol *tlbl = newiTempLabel(NULL);
8050 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8053 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8054 if( AOP_TYPE(right) == AOP_ACC) {
8055 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8057 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8058 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8063 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8064 pic16_emitcode(";XXX setb","c");
8065 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8066 AOP(left)->aopu.aop_dir,tlbl->key+100);
8067 pic16_toBoolean(right);
8068 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8069 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8070 jmpTrueOrFalse(ifx, tlbl);
8074 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8081 pic16_outBitC(result);
8083 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8084 genIfxJump(ifx, "c");
8088 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8089 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8090 if((AOP_TYPE(right) == AOP_LIT) &&
8091 (AOP_TYPE(result) == AOP_CRY) &&
8092 (AOP_TYPE(left) != AOP_CRY)){
8094 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8097 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8099 continueIfTrue(ifx);
8102 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8103 // lit = 0, result = boolean(left)
8105 pic16_emitcode(";XXX setb","c");
8106 pic16_toBoolean(right);
8108 symbol *tlbl = newiTempLabel(NULL);
8109 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8111 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8113 genIfxJump (ifx,"a");
8117 pic16_outBitC(result);
8121 /* if left is same as result */
8122 if(pic16_sameRegs(AOP(result),AOP(left))){
8124 for(;size--; offset++,lit>>=8) {
8125 if(AOP_TYPE(right) == AOP_LIT){
8126 if((lit & 0xff) == 0)
8127 /* or'ing with 0 has no effect */
8130 int p = pic16_my_powof2(lit & 0xff);
8132 /* only one bit is set in the literal, so use a bsf instruction */
8133 pic16_emitpcode(POC_BSF,
8134 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8136 if(know_W != (lit & 0xff))
8137 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8138 know_W = lit & 0xff;
8139 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8144 if (AOP_TYPE(left) == AOP_ACC) {
8145 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8146 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8149 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8151 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8152 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158 // left & result in different registers
8159 if(AOP_TYPE(result) == AOP_CRY){
8161 // if(size), result in bit
8162 // if(!size && ifx), conditional oper: if(left | right)
8163 symbol *tlbl = newiTempLabel(NULL);
8164 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8165 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8169 pic16_emitcode(";XXX setb","c");
8171 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8172 pic16_emitcode(";XXX orl","a,%s",
8173 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8179 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8180 pic16_outBitC(result);
8182 jmpTrueOrFalse(ifx, tlbl);
8183 } else for(;(size--);offset++){
8185 // result = left & right
8186 if(AOP_TYPE(right) == AOP_LIT){
8187 int t = (lit >> (offset*8)) & 0x0FFL;
8190 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8191 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8193 // pic16_emitcode("movf","%s,w",
8194 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8195 // pic16_emitcode("movwf","%s",
8196 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8199 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8200 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8201 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8203 // pic16_emitcode("movlw","0x%x",t);
8204 // pic16_emitcode("iorwf","%s,w",
8205 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8206 // pic16_emitcode("movwf","%s",
8207 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8213 // faster than result <- left, anl result,right
8214 // and better if result is SFR
8215 if (AOP_TYPE(left) == AOP_ACC) {
8216 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8217 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8219 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8220 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8222 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8223 // pic16_emitcode("iorwf","%s,w",
8224 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8226 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8227 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8232 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8233 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8234 pic16_freeAsmop(result,NULL,ic,TRUE);
8237 /*-----------------------------------------------------------------*/
8238 /* genXor - code for xclusive or */
8239 /*-----------------------------------------------------------------*/
8240 static void genXor (iCode *ic, iCode *ifx)
8242 operand *left, *right, *result;
8244 unsigned long lit = 0L;
8246 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8249 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8250 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8251 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8253 /* if left is a literal & right is not ||
8254 if left needs acc & right does not */
8255 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8256 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8257 operand *tmp = right ;
8262 /* if result = right then exchange them */
8263 if(pic16_sameRegs(AOP(result),AOP(right))){
8264 operand *tmp = right ;
8269 /* if right is bit then exchange them */
8270 if (AOP_TYPE(right) == AOP_CRY &&
8271 AOP_TYPE(left) != AOP_CRY){
8272 operand *tmp = right ;
8276 if(AOP_TYPE(right) == AOP_LIT)
8277 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8279 size = AOP_SIZE(result);
8283 if (AOP_TYPE(left) == AOP_CRY){
8284 if(AOP_TYPE(right) == AOP_LIT){
8285 // c = bit & literal;
8287 // lit>>1 != 0 => result = 1
8288 if(AOP_TYPE(result) == AOP_CRY){
8290 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8291 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8293 continueIfTrue(ifx);
8296 pic16_emitcode("setb","c");
8300 // lit == 0, result = left
8301 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8303 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8305 // lit == 1, result = not(left)
8306 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8307 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8308 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8309 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8312 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8313 pic16_emitcode("cpl","c");
8320 symbol *tlbl = newiTempLabel(NULL);
8321 if (AOP_TYPE(right) == AOP_CRY){
8323 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8326 int sizer = AOP_SIZE(right);
8328 // if val>>1 != 0, result = 1
8329 pic16_emitcode("setb","c");
8331 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8333 // test the msb of the lsb
8334 pic16_emitcode("anl","a,#0xfe");
8335 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8339 pic16_emitcode("rrc","a");
8341 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8342 pic16_emitcode("cpl","c");
8343 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8348 pic16_outBitC(result);
8350 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8351 genIfxJump(ifx, "c");
8355 if(pic16_sameRegs(AOP(result),AOP(left))){
8356 /* if left is same as result */
8357 for(;size--; offset++) {
8358 if(AOP_TYPE(right) == AOP_LIT){
8359 int t = (lit >> (offset*8)) & 0x0FFL;
8363 if (IS_AOP_PREG(left)) {
8364 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8365 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8366 pic16_aopPut(AOP(result),"a",offset);
8368 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8369 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8370 pic16_emitcode("xrl","%s,%s",
8371 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8372 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8375 if (AOP_TYPE(left) == AOP_ACC)
8376 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8378 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8379 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8381 if (IS_AOP_PREG(left)) {
8382 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8383 pic16_aopPut(AOP(result),"a",offset);
8385 pic16_emitcode("xrl","%s,a",
8386 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8392 // left & result in different registers
8393 if(AOP_TYPE(result) == AOP_CRY){
8395 // if(size), result in bit
8396 // if(!size && ifx), conditional oper: if(left ^ right)
8397 symbol *tlbl = newiTempLabel(NULL);
8398 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8400 pic16_emitcode("setb","c");
8402 if((AOP_TYPE(right) == AOP_LIT) &&
8403 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8404 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8406 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8407 pic16_emitcode("xrl","a,%s",
8408 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8410 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8415 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8416 pic16_outBitC(result);
8418 jmpTrueOrFalse(ifx, tlbl);
8419 } else for(;(size--);offset++){
8421 // result = left & right
8422 if(AOP_TYPE(right) == AOP_LIT){
8423 int t = (lit >> (offset*8)) & 0x0FFL;
8426 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8427 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8428 pic16_emitcode("movf","%s,w",
8429 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8430 pic16_emitcode("movwf","%s",
8431 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8434 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8435 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8436 pic16_emitcode("comf","%s,w",
8437 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8438 pic16_emitcode("movwf","%s",
8439 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8442 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8443 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8444 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8445 pic16_emitcode("movlw","0x%x",t);
8446 pic16_emitcode("xorwf","%s,w",
8447 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8448 pic16_emitcode("movwf","%s",
8449 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8455 // faster than result <- left, anl result,right
8456 // and better if result is SFR
8457 if (AOP_TYPE(left) == AOP_ACC) {
8458 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8459 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8461 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8462 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8463 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8464 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8466 if ( AOP_TYPE(result) != AOP_ACC){
8467 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8468 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8474 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8475 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8476 pic16_freeAsmop(result,NULL,ic,TRUE);
8479 /*-----------------------------------------------------------------*/
8480 /* genInline - write the inline code out */
8481 /*-----------------------------------------------------------------*/
8482 static void genInline (iCode *ic)
8484 char *buffer, *bp, *bp1;
8486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8488 _G.inLine += (!options.asmpeep);
8490 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8491 strcpy(buffer,IC_INLINE(ic));
8493 while((bp1=strstr(bp, "\\n"))) {
8501 /* This is an experimental code for #pragma inline
8502 and is temporarily disabled for 2.5.0 release */
8510 cbuf = Safe_strdup(buffer);
8511 cblen = strlen(buffer)+1;
8512 memset(cbuf, 0, cblen);
8517 if(*bp != '%')*bp1++ = *bp++;
8523 if(i>elementsInSet(asmInlineMap))break;
8526 s = indexSet(asmInlineMap, i);
8527 DEBUGpc("searching symbol s = `%s'", s);
8528 sym = findSym(SymbolTab, NULL, s);
8531 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8533 strcat(bp1, sym->rname);
8539 if(strlen(bp1) > cblen - 16) {
8540 int i = strlen(cbuf);
8542 cbuf = realloc(cbuf, cblen);
8543 memset(cbuf+i, 0, 50);
8549 buffer = Safe_strdup( cbuf );
8556 /* emit each line as a code */
8562 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8570 /* print label, use this special format with NULL directive
8571 * to denote that the argument should not be indented with tab */
8572 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8575 /* advance to end of line (prevent splitting of comments at ':' */
8576 while (*bp && *bp != '\n') {
8584 if ((bp1 != bp) && *bp1)
8585 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8590 _G.inLine -= (!options.asmpeep);
8593 /*-----------------------------------------------------------------*/
8594 /* genRRC - rotate right with carry */
8595 /*-----------------------------------------------------------------*/
8596 static void genRRC (iCode *ic)
8598 operand *left , *result ;
8599 int size, offset = 0, same;
8601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8603 /* rotate right with carry */
8605 result=IC_RESULT(ic);
8606 pic16_aopOp (left,ic,FALSE);
8607 pic16_aopOp (result,ic,TRUE);
8609 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8611 same = pic16_sameRegs(AOP(result),AOP(left));
8613 size = AOP_SIZE(result);
8615 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8617 /* get the lsb and put it into the carry */
8618 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8625 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8627 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8634 pic16_freeAsmop(left,NULL,ic,TRUE);
8635 pic16_freeAsmop(result,NULL,ic,TRUE);
8638 /*-----------------------------------------------------------------*/
8639 /* genRLC - generate code for rotate left with carry */
8640 /*-----------------------------------------------------------------*/
8641 static void genRLC (iCode *ic)
8643 operand *left , *result ;
8644 int size, offset = 0;
8647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8648 /* rotate right with carry */
8650 result=IC_RESULT(ic);
8651 pic16_aopOp (left,ic,FALSE);
8652 pic16_aopOp (result,ic,TRUE);
8654 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8656 same = pic16_sameRegs(AOP(result),AOP(left));
8658 /* move it to the result */
8659 size = AOP_SIZE(result);
8661 /* get the msb and put it into the carry */
8662 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8669 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8671 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8679 pic16_freeAsmop(left,NULL,ic,TRUE);
8680 pic16_freeAsmop(result,NULL,ic,TRUE);
8684 /* gpasm can get the highest order bit with HIGH/UPPER
8685 * so the following probably is not needed -- VR */
8687 /*-----------------------------------------------------------------*/
8688 /* genGetHbit - generates code get highest order bit */
8689 /*-----------------------------------------------------------------*/
8690 static void genGetHbit (iCode *ic)
8692 operand *left, *result;
8694 result=IC_RESULT(ic);
8695 pic16_aopOp (left,ic,FALSE);
8696 pic16_aopOp (result,ic,FALSE);
8698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8699 /* get the highest order byte into a */
8700 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8701 if(AOP_TYPE(result) == AOP_CRY){
8702 pic16_emitcode("rlc","a");
8703 pic16_outBitC(result);
8706 pic16_emitcode("rl","a");
8707 pic16_emitcode("anl","a,#0x01");
8708 pic16_outAcc(result);
8712 pic16_freeAsmop(left,NULL,ic,TRUE);
8713 pic16_freeAsmop(result,NULL,ic,TRUE);
8717 /*-----------------------------------------------------------------*/
8718 /* AccRol - rotate left accumulator by known count */
8719 /*-----------------------------------------------------------------*/
8720 static void AccRol (int shCount)
8722 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8723 shCount &= 0x0007; // shCount : 0..7
8728 pic16_emitcode("rl","a");
8731 pic16_emitcode("rl","a");
8732 pic16_emitcode("rl","a");
8735 pic16_emitcode("swap","a");
8736 pic16_emitcode("rr","a");
8739 pic16_emitcode("swap","a");
8742 pic16_emitcode("swap","a");
8743 pic16_emitcode("rl","a");
8746 pic16_emitcode("rr","a");
8747 pic16_emitcode("rr","a");
8750 pic16_emitcode("rr","a");
8756 /*-----------------------------------------------------------------*/
8757 /* AccLsh - left shift accumulator by known count */
8758 /*-----------------------------------------------------------------*/
8759 static void AccLsh (int shCount, int doMask)
8761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8767 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8770 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8771 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8774 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8775 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8778 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8781 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8782 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8785 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8793 /* no masking is required in genPackBits */
8794 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8798 /*-----------------------------------------------------------------*/
8799 /* AccRsh - right shift accumulator by known count */
8800 /*-----------------------------------------------------------------*/
8801 static void AccRsh (int shCount, int andmask)
8803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8808 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8811 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8816 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8819 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8822 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8823 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8826 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8835 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8837 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8841 /*-----------------------------------------------------------------*/
8842 /* AccSRsh - signed right shift accumulator by known count */
8843 /*-----------------------------------------------------------------*/
8844 static void AccSRsh (int shCount)
8847 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8850 pic16_emitcode("mov","c,acc.7");
8851 pic16_emitcode("rrc","a");
8852 } else if(shCount == 2){
8853 pic16_emitcode("mov","c,acc.7");
8854 pic16_emitcode("rrc","a");
8855 pic16_emitcode("mov","c,acc.7");
8856 pic16_emitcode("rrc","a");
8858 tlbl = newiTempLabel(NULL);
8859 /* rotate right accumulator */
8860 AccRol(8 - shCount);
8861 /* and kill the higher order bits */
8862 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8863 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8864 pic16_emitcode("orl","a,#0x%02x",
8865 (unsigned char)~SRMask[shCount]);
8866 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8872 /*-----------------------------------------------------------------*/
8873 /* shiftR1Left2Result - shift right one byte from left to result */
8874 /*-----------------------------------------------------------------*/
8875 static void shiftR1Left2ResultSigned (operand *left, int offl,
8876 operand *result, int offr,
8881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8883 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8887 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8889 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8898 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8900 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8902 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8903 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8905 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8912 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8914 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8915 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8918 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8919 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8920 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8922 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8923 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8925 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8929 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8930 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8931 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8932 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8937 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8940 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8943 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8944 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8945 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8952 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8954 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8955 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8960 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8962 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8968 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8969 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8970 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8975 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8983 /*-----------------------------------------------------------------*/
8984 /* shiftR1Left2Result - shift right one byte from left to result */
8985 /*-----------------------------------------------------------------*/
8986 static void shiftR1Left2Result (operand *left, int offl,
8987 operand *result, int offr,
8988 int shCount, int sign)
8992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8994 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8996 /* Copy the msb into the carry if signed. */
8998 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9008 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9017 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9031 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9035 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9042 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9043 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9048 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9056 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9057 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9058 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9059 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9060 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9065 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9066 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9067 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9076 /*-----------------------------------------------------------------*/
9077 /* shiftL1Left2Result - shift left one byte from left to result */
9078 /*-----------------------------------------------------------------*/
9079 static void shiftL1Left2Result (operand *left, int offl,
9080 operand *result, int offr, int shCount)
9085 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9087 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9088 DEBUGpic16_emitcode ("; ***","same = %d",same);
9089 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9091 /* shift left accumulator */
9092 //AccLsh(shCount, 1); // don't comment out just yet...
9093 // pic16_aopPut(AOP(result),"a",offr);
9097 /* Shift left 1 bit position */
9098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9100 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9102 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9103 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9108 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9109 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9110 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9114 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9117 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9121 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9122 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9126 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9127 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9132 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9133 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9138 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9139 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9144 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9149 /*-----------------------------------------------------------------*/
9150 /* movLeft2Result - move byte from left to result */
9151 /*-----------------------------------------------------------------*/
9152 static void movLeft2Result (operand *left, int offl,
9153 operand *result, int offr)
9156 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9157 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9158 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9160 if (*l == '@' && (IS_AOP_PREG(result))) {
9161 pic16_emitcode("mov","a,%s",l);
9162 pic16_aopPut(AOP(result),"a",offr);
9164 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9165 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9170 /*-----------------------------------------------------------------*/
9171 /* shiftL2Left2Result - shift left two bytes from left to result */
9172 /*-----------------------------------------------------------------*/
9173 static void shiftL2Left2Result (operand *left, int offl,
9174 operand *result, int offr, int shCount)
9176 int same = pic16_sameRegs(AOP(result), AOP(left));
9179 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9181 if (same && (offl != offr)) { // shift bytes
9184 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9185 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9187 } else { // just treat as different later on
9200 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9201 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9202 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9206 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9207 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9213 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9214 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9215 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9216 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9217 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9218 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9219 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9221 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9222 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9226 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9227 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9228 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9229 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9230 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9231 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9232 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9234 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9235 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9238 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9239 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9240 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9241 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9242 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9252 /* note, use a mov/add for the shift since the mov has a
9253 chance of getting optimized out */
9254 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9256 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9257 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9262 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9263 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9269 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9270 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9271 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9272 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9274 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9275 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9276 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9280 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9281 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9285 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9286 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9287 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9288 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9290 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9291 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9292 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9293 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9294 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9295 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9296 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9297 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9300 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9301 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9302 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9303 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9304 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9309 /*-----------------------------------------------------------------*/
9310 /* shiftR2Left2Result - shift right two bytes from left to result */
9311 /*-----------------------------------------------------------------*/
9312 static void shiftR2Left2Result (operand *left, int offl,
9313 operand *result, int offr,
9314 int shCount, int sign)
9316 int same = pic16_sameRegs(AOP(result), AOP(left));
9318 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9320 if (same && (offl != offr)) { // shift right bytes
9323 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9324 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9326 } else { // just treat as different later on
9337 /* obtain sign from left operand */
9339 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9344 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9345 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9347 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9348 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9349 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9350 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9355 /* now get sign from already assigned result (avoid BANKSEL) */
9356 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9359 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9360 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9367 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9368 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9369 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9371 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9372 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9373 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9374 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9376 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9377 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9378 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9380 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9382 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9383 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9384 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9388 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9389 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9393 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9394 pic16_emitpcode(POC_BTFSC,
9395 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9396 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9404 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9405 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9407 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9408 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9409 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9410 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9412 pic16_emitpcode(POC_BTFSC,
9413 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9414 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9416 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9417 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9418 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9419 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9421 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9422 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9424 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9425 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9426 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9427 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9428 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9430 pic16_emitpcode(POC_BTFSC,
9431 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9432 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9434 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9435 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9442 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9443 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9444 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9445 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9448 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9450 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9455 /*-----------------------------------------------------------------*/
9456 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9457 /*-----------------------------------------------------------------*/
9458 static void shiftLLeftOrResult (operand *left, int offl,
9459 operand *result, int offr, int shCount)
9461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9463 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9464 /* shift left accumulator */
9466 /* or with result */
9467 /* back to result */
9468 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9471 /*-----------------------------------------------------------------*/
9472 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9473 /*-----------------------------------------------------------------*/
9474 static void shiftRLeftOrResult (operand *left, int offl,
9475 operand *result, int offr, int shCount)
9477 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9479 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9480 /* shift right accumulator */
9482 /* or with result */
9483 /* back to result */
9484 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9487 /*-----------------------------------------------------------------*/
9488 /* genlshOne - left shift a one byte quantity by known count */
9489 /*-----------------------------------------------------------------*/
9490 static void genlshOne (operand *result, operand *left, int shCount)
9492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9493 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9496 /*-----------------------------------------------------------------*/
9497 /* genlshTwo - left shift two bytes by known amount != 0 */
9498 /*-----------------------------------------------------------------*/
9499 static void genlshTwo (operand *result,operand *left, int shCount)
9503 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9504 size = pic16_getDataSize(result);
9506 /* if shCount >= 8 */
9512 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9514 movLeft2Result(left, LSB, result, MSB16);
9516 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9519 /* 1 <= shCount <= 7 */
9522 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9524 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9528 /*-----------------------------------------------------------------*/
9529 /* shiftLLong - shift left one long from left to result */
9530 /* offr = LSB or MSB16 */
9531 /*-----------------------------------------------------------------*/
9532 static void shiftLLong (operand *left, operand *result, int offr )
9534 int size = AOP_SIZE(result);
9535 int same = pic16_sameRegs(AOP(left),AOP(result));
9538 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9540 if (same && (offr == MSB16)) { //shift one byte
9541 for(i=size-1;i>=MSB16;i--) {
9542 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9543 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9546 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9549 if (size > LSB+offr ){
9551 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9553 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9554 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9558 if(size > MSB16+offr){
9560 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9562 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9563 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9567 if(size > MSB24+offr){
9569 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9571 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9572 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9576 if(size > MSB32+offr){
9578 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9580 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9581 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9585 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9589 /*-----------------------------------------------------------------*/
9590 /* genlshFour - shift four byte by a known amount != 0 */
9591 /*-----------------------------------------------------------------*/
9592 static void genlshFour (operand *result, operand *left, int shCount)
9596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9597 size = AOP_SIZE(result);
9599 /* if shifting more that 3 bytes */
9600 if (shCount >= 24 ) {
9603 /* lowest order of left goes to the highest
9604 order of the destination */
9605 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9607 movLeft2Result(left, LSB, result, MSB32);
9609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9610 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9611 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9616 /* more than two bytes */
9617 else if ( shCount >= 16 ) {
9618 /* lower order two bytes goes to higher order two bytes */
9620 /* if some more remaining */
9622 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9624 movLeft2Result(left, MSB16, result, MSB32);
9625 movLeft2Result(left, LSB, result, MSB24);
9627 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9628 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9632 /* if more than 1 byte */
9633 else if ( shCount >= 8 ) {
9634 /* lower order three bytes goes to higher order three bytes */
9638 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9640 movLeft2Result(left, LSB, result, MSB16);
9642 else{ /* size = 4 */
9644 movLeft2Result(left, MSB24, result, MSB32);
9645 movLeft2Result(left, MSB16, result, MSB24);
9646 movLeft2Result(left, LSB, result, MSB16);
9647 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9649 else if(shCount == 1)
9650 shiftLLong(left, result, MSB16);
9652 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9653 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9654 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9655 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9660 /* 1 <= shCount <= 7 */
9661 else if(shCount <= 3)
9663 shiftLLong(left, result, LSB);
9664 while(--shCount >= 1)
9665 shiftLLong(result, result, LSB);
9667 /* 3 <= shCount <= 7, optimize */
9669 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9670 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9671 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9675 /*-----------------------------------------------------------------*/
9676 /* genLeftShiftLiteral - left shifting by known count */
9677 /*-----------------------------------------------------------------*/
9678 void pic16_genLeftShiftLiteral (operand *left,
9683 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9687 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9688 pic16_freeAsmop(right,NULL,ic,TRUE);
9690 pic16_aopOp(left,ic,FALSE);
9691 pic16_aopOp(result,ic,TRUE);
9693 size = getSize(operandType(result));
9696 pic16_emitcode("; shift left ","result %d, left %d",size,
9700 /* I suppose that the left size >= result size */
9703 movLeft2Result(left, size, result, size);
9707 else if(shCount >= (size * 8))
9709 pic16_aopPut(AOP(result),zero,size);
9713 genlshOne (result,left,shCount);
9718 genlshTwo (result,left,shCount);
9722 genlshFour (result,left,shCount);
9726 pic16_freeAsmop(left,NULL,ic,TRUE);
9727 pic16_freeAsmop(result,NULL,ic,TRUE);
9730 /*-----------------------------------------------------------------*
9731 * genMultiAsm - repeat assembly instruction for size of register.
9732 * if endian == 1, then the high byte (i.e base address + size of
9733 * register) is used first else the low byte is used first;
9734 *-----------------------------------------------------------------*/
9735 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9753 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9759 #if !(USE_GENERIC_SIGNED_SHIFT)
9760 /*-----------------------------------------------------------------*/
9761 /* genLeftShift - generates code for left shifting */
9762 /*-----------------------------------------------------------------*/
9763 static void genLeftShift (iCode *ic)
9765 operand *left,*right, *result;
9768 symbol *tlbl , *tlbl1;
9771 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9773 right = IC_RIGHT(ic);
9775 result = IC_RESULT(ic);
9777 pic16_aopOp(right,ic,FALSE);
9779 /* if the shift count is known then do it
9780 as efficiently as possible */
9781 if (AOP_TYPE(right) == AOP_LIT) {
9782 pic16_genLeftShiftLiteral (left,right,result,ic);
9786 /* shift count is unknown then we have to form
9787 * a loop. Get the loop count in WREG : Note: we take
9788 * only the lower order byte since shifting
9789 * more than 32 bits make no sense anyway, ( the
9790 * largest size of an object can be only 32 bits ) */
9792 pic16_aopOp(left,ic,FALSE);
9793 pic16_aopOp(result,ic,FALSE);
9795 /* now move the left to the result if they are not the
9796 * same, and if size > 1,
9797 * and if right is not same to result (!!!) -- VR */
9798 if (!pic16_sameRegs(AOP(left),AOP(result))
9799 && (AOP_SIZE(result) > 1)) {
9801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9803 size = AOP_SIZE(result);
9808 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9809 if (*l == '@' && (IS_AOP_PREG(result))) {
9811 pic16_emitcode("mov","a,%s",l);
9812 pic16_aopPut(AOP(result),"a",offset);
9816 /* we don't know if left is a literal or a register, take care -- VR */
9817 pic16_mov2f(AOP(result), AOP(left), offset);
9823 size = AOP_SIZE(result);
9825 /* if it is only one byte then */
9827 if(optimized_for_speed) {
9828 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9829 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9830 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9831 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9832 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9833 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9834 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9835 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9836 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9837 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9838 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9839 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9844 tlbl = newiTempLabel(NULL);
9847 /* this is already done, why change it? */
9848 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9849 pic16_mov2f(AOP(result), AOP(left), 0);
9853 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9854 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9855 pic16_emitpLabel(tlbl->key);
9856 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9857 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9859 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9864 if (pic16_sameRegs(AOP(left),AOP(result))) {
9866 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9868 tlbl = newiTempLabel(NULL);
9869 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9870 genMultiAsm(POC_RRCF, result, size,1);
9871 pic16_emitpLabel(tlbl->key);
9872 genMultiAsm(POC_RLCF, result, size,0);
9873 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9879 //tlbl = newiTempLabel(NULL);
9881 //tlbl1 = newiTempLabel(NULL);
9883 //reAdjustPreg(AOP(result));
9885 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9886 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9887 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9889 //pic16_emitcode("add","a,acc");
9890 //pic16_aopPut(AOP(result),"a",offset++);
9892 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9894 // pic16_emitcode("rlc","a");
9895 // pic16_aopPut(AOP(result),"a",offset++);
9897 //reAdjustPreg(AOP(result));
9899 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9900 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9903 tlbl = newiTempLabel(NULL);
9904 tlbl1= newiTempLabel(NULL);
9906 size = AOP_SIZE(result);
9909 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9911 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9913 /* offset should be 0, 1 or 3 */
9915 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9917 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9919 pic16_emitpcode(POC_MOVWF, pctemp);
9922 pic16_emitpLabel(tlbl->key);
9925 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9927 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9929 pic16_emitpcode(POC_DECFSZ, pctemp);
9930 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9931 pic16_emitpLabel(tlbl1->key);
9933 pic16_popReleaseTempReg(pctemp,1);
9937 pic16_freeAsmop (right,NULL,ic,TRUE);
9938 pic16_freeAsmop(left,NULL,ic,TRUE);
9939 pic16_freeAsmop(result,NULL,ic,TRUE);
9945 #error old code (left here for reference)
9946 /*-----------------------------------------------------------------*/
9947 /* genLeftShift - generates code for left shifting */
9948 /*-----------------------------------------------------------------*/
9949 static void genLeftShift (iCode *ic)
9951 operand *left,*right, *result;
9954 symbol *tlbl , *tlbl1;
9957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9959 right = IC_RIGHT(ic);
9961 result = IC_RESULT(ic);
9963 pic16_aopOp(right,ic,FALSE);
9965 /* if the shift count is known then do it
9966 as efficiently as possible */
9967 if (AOP_TYPE(right) == AOP_LIT) {
9968 pic16_genLeftShiftLiteral (left,right,result,ic);
9972 /* shift count is unknown then we have to form
9973 a loop get the loop count in B : Note: we take
9974 only the lower order byte since shifting
9975 more that 32 bits make no sense anyway, ( the
9976 largest size of an object can be only 32 bits ) */
9979 pic16_aopOp(left,ic,FALSE);
9980 pic16_aopOp(result,ic,FALSE);
9982 /* now move the left to the result if they are not the
9984 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9985 AOP_SIZE(result) > 1) {
9987 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9989 size = AOP_SIZE(result);
9992 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9993 if (*l == '@' && (IS_AOP_PREG(result))) {
9995 pic16_emitcode("mov","a,%s",l);
9996 pic16_aopPut(AOP(result),"a",offset);
9999 /* we don't know if left is a literal or a register, take care -- VR */
10000 pic16_mov2f(AOP(result), AOP(left), offset);
10006 size = AOP_SIZE(result);
10008 /* if it is only one byte then */
10010 if(optimized_for_speed) {
10011 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10012 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10013 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10014 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10016 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10017 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10018 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10019 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10020 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10021 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10022 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10027 tlbl = newiTempLabel(NULL);
10028 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10029 pic16_mov2f(AOP(result), AOP(left), 0);
10031 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10032 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10035 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10036 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10037 pic16_emitpLabel(tlbl->key);
10038 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10039 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10041 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10046 if (pic16_sameRegs(AOP(left),AOP(result))) {
10048 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10050 tlbl = newiTempLabel(NULL);
10051 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10052 genMultiAsm(POC_RRCF, result, size,1);
10053 pic16_emitpLabel(tlbl->key);
10054 genMultiAsm(POC_RLCF, result, size,0);
10055 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10057 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10061 //tlbl = newiTempLabel(NULL);
10063 //tlbl1 = newiTempLabel(NULL);
10065 //reAdjustPreg(AOP(result));
10067 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10068 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10069 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10071 //pic16_emitcode("add","a,acc");
10072 //pic16_aopPut(AOP(result),"a",offset++);
10074 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10076 // pic16_emitcode("rlc","a");
10077 // pic16_aopPut(AOP(result),"a",offset++);
10079 //reAdjustPreg(AOP(result));
10081 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10082 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10085 tlbl = newiTempLabel(NULL);
10086 tlbl1= newiTempLabel(NULL);
10088 size = AOP_SIZE(result);
10091 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10093 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10095 /* offset should be 0, 1 or 3 */
10097 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10099 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10101 pic16_emitpcode(POC_MOVWF, pctemp);
10104 pic16_emitpLabel(tlbl->key);
10107 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10109 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10111 pic16_emitpcode(POC_DECFSZ, pctemp);
10112 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10113 pic16_emitpLabel(tlbl1->key);
10115 pic16_popReleaseTempReg(pctemp,1);
10119 pic16_freeAsmop (right,NULL,ic,TRUE);
10120 pic16_freeAsmop(left,NULL,ic,TRUE);
10121 pic16_freeAsmop(result,NULL,ic,TRUE);
10125 /*-----------------------------------------------------------------*/
10126 /* genrshOne - right shift a one byte quantity by known count */
10127 /*-----------------------------------------------------------------*/
10128 static void genrshOne (operand *result, operand *left,
10129 int shCount, int sign)
10131 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10132 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10135 /*-----------------------------------------------------------------*/
10136 /* genrshTwo - right shift two bytes by known amount != 0 */
10137 /*-----------------------------------------------------------------*/
10138 static void genrshTwo (operand *result,operand *left,
10139 int shCount, int sign)
10141 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10142 /* if shCount >= 8 */
10143 if (shCount >= 8) {
10146 shiftR1Left2Result(left, MSB16, result, LSB,
10149 movLeft2Result(left, MSB16, result, LSB);
10151 pic16_addSign (result, 1, sign);
10154 /* 1 <= shCount <= 7 */
10156 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10159 /*-----------------------------------------------------------------*/
10160 /* shiftRLong - shift right one long from left to result */
10161 /* offl = LSB or MSB16 */
10162 /*-----------------------------------------------------------------*/
10163 static void shiftRLong (operand *left, int offl,
10164 operand *result, int sign)
10166 int size = AOP_SIZE(result);
10167 int same = pic16_sameRegs(AOP(left),AOP(result));
10169 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10171 if (same && (offl == MSB16)) { //shift one byte right
10172 for(i=MSB16;i<size;i++) {
10173 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10174 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10179 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10185 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10187 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10188 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10191 if(offl == MSB16) {
10192 /* add sign of "a" */
10193 pic16_addSign(result, MSB32, sign);
10197 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10199 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10200 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10204 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10206 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10211 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10214 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10215 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10220 /*-----------------------------------------------------------------*/
10221 /* genrshFour - shift four byte by a known amount != 0 */
10222 /*-----------------------------------------------------------------*/
10223 static void genrshFour (operand *result, operand *left,
10224 int shCount, int sign)
10226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10227 /* if shifting more that 3 bytes */
10228 if(shCount >= 24 ) {
10231 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10233 movLeft2Result(left, MSB32, result, LSB);
10235 pic16_addSign(result, MSB16, sign);
10237 else if(shCount >= 16){
10240 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10242 movLeft2Result(left, MSB24, result, LSB);
10243 movLeft2Result(left, MSB32, result, MSB16);
10245 pic16_addSign(result, MSB24, sign);
10247 else if(shCount >= 8){
10250 shiftRLong(left, MSB16, result, sign);
10251 else if(shCount == 0){
10252 movLeft2Result(left, MSB16, result, LSB);
10253 movLeft2Result(left, MSB24, result, MSB16);
10254 movLeft2Result(left, MSB32, result, MSB24);
10255 pic16_addSign(result, MSB32, sign);
10257 else{ //shcount >= 2
10258 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10259 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10260 /* the last shift is signed */
10261 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10262 pic16_addSign(result, MSB32, sign);
10265 else{ /* 1 <= shCount <= 7 */
10267 shiftRLong(left, LSB, result, sign);
10269 shiftRLong(result, LSB, result, sign);
10272 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10273 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10274 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10279 /*-----------------------------------------------------------------*/
10280 /* genRightShiftLiteral - right shifting by known count */
10281 /*-----------------------------------------------------------------*/
10282 static void genRightShiftLiteral (operand *left,
10288 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10289 int lsize,res_size;
10291 pic16_freeAsmop(right,NULL,ic,TRUE);
10293 pic16_aopOp(left,ic,FALSE);
10294 pic16_aopOp(result,ic,TRUE);
10296 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10299 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10303 lsize = pic16_getDataSize(left);
10304 res_size = pic16_getDataSize(result);
10305 /* test the LEFT size !!! */
10307 /* I suppose that the left size >= result size */
10309 assert (res_size <= lsize);
10310 while (res_size--) {
10311 pic16_mov2f (AOP(result), AOP(left), res_size);
10315 else if(shCount >= (lsize * 8)){
10317 if(res_size == 1) {
10318 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10320 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10321 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10326 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10327 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10328 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10335 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10340 switch (res_size) {
10342 genrshOne (result,left,shCount,sign);
10346 genrshTwo (result,left,shCount,sign);
10350 genrshFour (result,left,shCount,sign);
10358 pic16_freeAsmop(left,NULL,ic,TRUE);
10359 pic16_freeAsmop(result,NULL,ic,TRUE);
10362 #if !(USE_GENERIC_SIGNED_SHIFT)
10363 /*-----------------------------------------------------------------*/
10364 /* genSignedRightShift - right shift of signed number */
10365 /*-----------------------------------------------------------------*/
10366 static void genSignedRightShift (iCode *ic)
10368 operand *right, *left, *result;
10371 symbol *tlbl, *tlbl1 ;
10374 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10376 /* we do it the hard way put the shift count in b
10377 and loop thru preserving the sign */
10378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10380 right = IC_RIGHT(ic);
10381 left = IC_LEFT(ic);
10382 result = IC_RESULT(ic);
10384 pic16_aopOp(right,ic,FALSE);
10385 pic16_aopOp(left,ic,FALSE);
10386 pic16_aopOp(result,ic,FALSE);
10389 if ( AOP_TYPE(right) == AOP_LIT) {
10390 genRightShiftLiteral (left,right,result,ic,1);
10393 /* shift count is unknown then we have to form
10394 a loop get the loop count in B : Note: we take
10395 only the lower order byte since shifting
10396 more that 32 bits make no sense anyway, ( the
10397 largest size of an object can be only 32 bits ) */
10399 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10400 //pic16_emitcode("inc","b");
10401 //pic16_freeAsmop (right,NULL,ic,TRUE);
10402 //pic16_aopOp(left,ic,FALSE);
10403 //pic16_aopOp(result,ic,FALSE);
10405 /* now move the left to the result if they are not the
10407 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10408 AOP_SIZE(result) > 1) {
10410 size = AOP_SIZE(result);
10414 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10415 if (*l == '@' && IS_AOP_PREG(result)) {
10417 pic16_emitcode("mov","a,%s",l);
10418 pic16_aopPut(AOP(result),"a",offset);
10420 pic16_aopPut(AOP(result),l,offset);
10422 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10423 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10429 /* mov the highest order bit to OVR */
10430 tlbl = newiTempLabel(NULL);
10431 tlbl1= newiTempLabel(NULL);
10433 size = AOP_SIZE(result);
10436 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10438 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10440 /* offset should be 0, 1 or 3 */
10441 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10443 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10445 pic16_emitpcode(POC_MOVWF, pctemp);
10448 pic16_emitpLabel(tlbl->key);
10450 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10451 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10454 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10457 pic16_emitpcode(POC_DECFSZ, pctemp);
10458 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10459 pic16_emitpLabel(tlbl1->key);
10461 pic16_popReleaseTempReg(pctemp,1);
10463 size = AOP_SIZE(result);
10465 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10466 pic16_emitcode("rlc","a");
10467 pic16_emitcode("mov","ov,c");
10468 /* if it is only one byte then */
10470 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10472 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10473 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10474 pic16_emitcode("mov","c,ov");
10475 pic16_emitcode("rrc","a");
10476 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10477 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10478 pic16_aopPut(AOP(result),"a",0);
10482 reAdjustPreg(AOP(result));
10483 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10484 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10485 pic16_emitcode("mov","c,ov");
10487 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10489 pic16_emitcode("rrc","a");
10490 pic16_aopPut(AOP(result),"a",offset--);
10492 reAdjustPreg(AOP(result));
10493 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10494 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10499 pic16_freeAsmop(left,NULL,ic,TRUE);
10500 pic16_freeAsmop(result,NULL,ic,TRUE);
10501 pic16_freeAsmop(right,NULL,ic,TRUE);
10505 #if !(USE_GENERIC_SIGNED_SHIFT)
10506 #warning This implementation of genRightShift() is incomplete!
10507 /*-----------------------------------------------------------------*/
10508 /* genRightShift - generate code for right shifting */
10509 /*-----------------------------------------------------------------*/
10510 static void genRightShift (iCode *ic)
10512 operand *right, *left, *result;
10516 symbol *tlbl, *tlbl1 ;
10518 /* if signed then we do it the hard way preserve the
10519 sign bit moving it inwards */
10520 letype = getSpec(operandType(IC_LEFT(ic)));
10521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10523 if (!SPEC_USIGN(letype)) {
10524 genSignedRightShift (ic);
10528 /* signed & unsigned types are treated the same : i.e. the
10529 signed is NOT propagated inwards : quoting from the
10530 ANSI - standard : "for E1 >> E2, is equivalent to division
10531 by 2**E2 if unsigned or if it has a non-negative value,
10532 otherwise the result is implementation defined ", MY definition
10533 is that the sign does not get propagated */
10535 right = IC_RIGHT(ic);
10536 left = IC_LEFT(ic);
10537 result = IC_RESULT(ic);
10539 pic16_aopOp(right,ic,FALSE);
10541 /* if the shift count is known then do it
10542 as efficiently as possible */
10543 if (AOP_TYPE(right) == AOP_LIT) {
10544 genRightShiftLiteral (left,right,result,ic, 0);
10548 /* shift count is unknown then we have to form
10549 a loop get the loop count in B : Note: we take
10550 only the lower order byte since shifting
10551 more that 32 bits make no sense anyway, ( the
10552 largest size of an object can be only 32 bits ) */
10554 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10555 pic16_emitcode("inc","b");
10556 pic16_aopOp(left,ic,FALSE);
10557 pic16_aopOp(result,ic,FALSE);
10559 /* now move the left to the result if they are not the
10561 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10562 AOP_SIZE(result) > 1) {
10564 size = AOP_SIZE(result);
10567 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10568 if (*l == '@' && IS_AOP_PREG(result)) {
10570 pic16_emitcode("mov","a,%s",l);
10571 pic16_aopPut(AOP(result),"a",offset);
10573 pic16_aopPut(AOP(result),l,offset);
10578 tlbl = newiTempLabel(NULL);
10579 tlbl1= newiTempLabel(NULL);
10580 size = AOP_SIZE(result);
10583 /* if it is only one byte then */
10586 tlbl = newiTempLabel(NULL);
10587 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10588 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10592 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10593 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10594 pic16_emitpLabel(tlbl->key);
10595 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10596 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10598 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10603 reAdjustPreg(AOP(result));
10604 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10605 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10608 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10610 pic16_emitcode("rrc","a");
10611 pic16_aopPut(AOP(result),"a",offset--);
10613 reAdjustPreg(AOP(result));
10615 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10616 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10619 pic16_freeAsmop(left,NULL,ic,TRUE);
10620 pic16_freeAsmop (right,NULL,ic,TRUE);
10621 pic16_freeAsmop(result,NULL,ic,TRUE);
10625 #if (USE_GENERIC_SIGNED_SHIFT)
10626 /*-----------------------------------------------------------------*/
10627 /* genGenericShift - generates code for left or right shifting */
10628 /*-----------------------------------------------------------------*/
10629 static void genGenericShift (iCode *ic, int isShiftLeft) {
10630 operand *left,*right, *result;
10632 int sign, signedCount;
10633 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10634 PIC_OPCODE pos_shift, neg_shift;
10638 right = IC_RIGHT(ic);
10639 left = IC_LEFT(ic);
10640 result = IC_RESULT(ic);
10642 pic16_aopOp(right,ic,FALSE);
10643 pic16_aopOp(left,ic,FALSE);
10644 pic16_aopOp(result,ic,TRUE);
10646 sign = !SPEC_USIGN(operandType (left));
10647 signedCount = !SPEC_USIGN(operandType (right));
10649 /* if the shift count is known then do it
10650 as efficiently as possible */
10651 if (AOP_TYPE(right) == AOP_LIT) {
10652 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10653 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10654 // we should modify right->aopu.aop_lit here!
10655 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10656 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10658 pic16_genLeftShiftLiteral (left,right,result,ic);
10660 genRightShiftLiteral (left,right,result,ic, sign);
10663 } // if (right is literal)
10665 /* shift count is unknown then we have to form a loop.
10666 * Note: we take only the lower order byte since shifting
10667 * more than 32 bits make no sense anyway, ( the
10668 * largest size of an object can be only 32 bits )
10669 * Note: we perform arithmetic shifts if the left operand is
10670 * signed and we do an (effective) right shift, i. e. we
10671 * shift in the sign bit from the left. */
10673 label_complete = newiTempLabel ( NULL );
10674 label_loop_pos = newiTempLabel ( NULL );
10675 label_loop_neg = NULL;
10676 label_negative = NULL;
10677 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10678 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10681 // additional labels needed
10682 label_loop_neg = newiTempLabel ( NULL );
10683 label_negative = newiTempLabel ( NULL );
10686 // copy source to result -- this will effectively truncate the left operand to the size of result!
10687 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10688 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10689 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10690 pic16_mov2f (AOP(result),AOP(left), offset);
10693 // if result is longer than left, fill with zeros (or sign)
10694 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10695 if (sign && AOP_SIZE(left) > 0) {
10696 // shift signed operand -- fill with sign
10697 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10698 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10699 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10700 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10701 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10704 // shift unsigned operand -- fill result with zeros
10705 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10706 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10709 } // if (size mismatch)
10711 pic16_mov2w (AOP(right), 0);
10712 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10713 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10716 // perform a shift by one (shift count is positive)
10717 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10718 // 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])
10719 pic16_emitpLabel (label_loop_pos->key);
10721 if (sign && (pos_shift == POC_RRCF)) {
10722 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10725 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10726 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10727 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10729 // perform a shift by one (shift count is positive)
10730 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10731 // 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])
10732 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10733 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10735 pic16_emitpLabel (label_loop_pos->key);
10736 if (sign && (pos_shift == POC_RRCF)) {
10737 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10740 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10741 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10742 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10743 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10747 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10749 pic16_emitpLabel (label_negative->key);
10750 // perform a shift by -1 (shift count is negative)
10751 // 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)
10753 pic16_emitpLabel (label_loop_neg->key);
10754 if (sign && (neg_shift == POC_RRCF)) {
10755 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10758 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10759 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10760 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10761 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10762 } // if (signedCount)
10764 pic16_emitpLabel (label_complete->key);
10767 pic16_freeAsmop (right,NULL,ic,TRUE);
10768 pic16_freeAsmop(left,NULL,ic,TRUE);
10769 pic16_freeAsmop(result,NULL,ic,TRUE);
10772 static void genLeftShift (iCode *ic) {
10773 genGenericShift (ic, 1);
10776 static void genRightShift (iCode *ic) {
10777 genGenericShift (ic, 0);
10782 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10783 void pic16_loadFSR0(operand *op, int lit)
10785 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10786 if (AOP_TYPE(op) == AOP_LIT) {
10787 /* handle 12 bit integers correctly */
10788 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10789 if ((val & 0x0fff) != val) {
10790 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10791 val, (val & 0x0fff) );
10794 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10796 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10799 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10800 // set up FSR0 with address of result
10801 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10802 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10806 /*----------------------------------------------------------------*/
10807 /* pic16_derefPtr - move one byte from the location ptr points to */
10808 /* to WREG (doWrite == 0) or one byte from WREG */
10809 /* to the location ptr points to (doWrite != 0) */
10810 /*----------------------------------------------------------------*/
10811 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10813 if (!IS_PTR(operandType(ptr)))
10815 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10816 else pic16_mov2w (AOP(ptr), 0);
10820 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10821 /* We might determine pointer type right here: */
10822 p_type = DCL_TYPE(operandType(ptr));
10827 if (!fsr0_setup || !*fsr0_setup)
10829 pic16_loadFSR0( ptr, 0 );
10830 if (fsr0_setup) *fsr0_setup = 1;
10833 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10835 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10839 if (AOP(ptr)->aopu.aop_reg[2]) {
10840 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10841 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10842 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10843 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10844 pic16_mov2w(AOP(ptr), 2);
10845 pic16_callGenericPointerRW(doWrite, 1);
10847 // data pointer (just 2 byte given)
10848 if (!fsr0_setup || !*fsr0_setup)
10850 pic16_loadFSR0( ptr, 0 );
10851 if (fsr0_setup) *fsr0_setup = 1;
10854 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10856 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10861 assert (0 && "invalid pointer type specified");
10866 /*-----------------------------------------------------------------*/
10867 /* genUnpackBits - generates code for unpacking bits */
10868 /*-----------------------------------------------------------------*/
10869 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10872 sym_link *etype, *letype;
10873 int blen=0, bstr=0;
10878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10879 etype = getSpec(operandType(result));
10880 letype = getSpec(operandType(left));
10882 // if(IS_BITFIELD(etype)) {
10883 blen = SPEC_BLEN(etype);
10884 bstr = SPEC_BSTR(etype);
10887 lbstr = SPEC_BSTR( letype );
10889 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10890 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10893 if((blen == 1) && (bstr < 8)
10894 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10895 /* it is a single bit, so use the appropriate bit instructions */
10896 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10898 same = pic16_sameRegs(AOP(left),AOP(result));
10899 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10900 pic16_emitpcode(POC_CLRF, op);
10902 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10903 /* workaround to reduce the extra lfsr instruction */
10904 pic16_emitpcode(POC_BTFSC,
10905 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10907 assert (PIC_IS_DATA_PTR (operandType(left)));
10908 pic16_loadFSR0 (left, 0);
10909 pic16_emitpcode(POC_BTFSC,
10910 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10913 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10914 /* unsigned bitfields result in either 0 or 1 */
10915 pic16_emitpcode(POC_INCF, op);
10917 /* signed bitfields result in either 0 or -1 */
10918 pic16_emitpcode(POC_DECF, op);
10921 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10924 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10930 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10931 // access symbol directly
10932 pic16_mov2w (AOP(left), 0);
10934 pic16_derefPtr (left, ptype, 0, NULL);
10937 /* if we have bitdisplacement then it fits */
10938 /* into this byte completely or if length is */
10939 /* less than a byte */
10940 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10942 /* shift right acc */
10945 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10946 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10948 /* VR -- normally I would use the following, but since we use the hack,
10949 * to avoid the masking from AccRsh, why not mask it right now? */
10952 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10955 /* extend signed bitfields to 8 bits */
10956 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10958 assert (blen + bstr > 0);
10959 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10960 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10965 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10969 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10970 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10971 exit(EXIT_FAILURE);
10977 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10979 int size, offset = 0, leoffset=0 ;
10981 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10982 pic16_aopOp(result, ic, TRUE);
10986 size = AOP_SIZE(result);
10987 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10991 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10992 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10993 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10998 if(AOP(left)->aopu.pcop->type == PO_DIR)
10999 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11001 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11004 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11006 // pic16_DumpOp("(result)",result);
11007 if(is_LitAOp(AOP(result))) {
11008 pic16_mov2w(AOP(left), offset); // patch 8
11009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11011 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11012 pic16_popGet(AOP(left), offset), //patch 8
11013 pic16_popGet(AOP(result), offset)));
11021 pic16_freeAsmop(result,NULL,ic,TRUE);
11026 /*-----------------------------------------------------------------*/
11027 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11028 /*-----------------------------------------------------------------*/
11029 static void genNearPointerGet (operand *left,
11033 // asmop *aop = NULL;
11034 //regs *preg = NULL ;
11035 sym_link *rtype, *retype;
11036 sym_link *ltype, *letype;
11040 rtype = operandType(result);
11041 retype= getSpec(rtype);
11042 ltype = operandType(left);
11043 letype= getSpec(ltype);
11045 pic16_aopOp(left,ic,FALSE);
11047 // pic16_DumpOp("(left)",left);
11048 // pic16_DumpOp("(result)",result);
11050 /* if left is rematerialisable and
11051 * result is not bit variable type and
11052 * the left is pointer to data space i.e
11053 * lower 128 bytes of space */
11055 if (AOP_TYPE(left) == AOP_PCODE
11056 && !IS_BITFIELD(retype)
11057 && DCL_TYPE(ltype) == POINTER) {
11059 genDataPointerGet (left,result,ic);
11060 pic16_freeAsmop(left, NULL, ic, TRUE);
11064 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11065 pic16_aopOp (result,ic,TRUE);
11067 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11070 if(IS_BITFIELD( retype )
11071 && (SPEC_BLEN(operandType(result))==1)
11075 int bitstrt, bytestrt;
11077 /* if this is bitfield of size 1, see if we are checking the value
11078 * of a single bit in an if-statement,
11079 * if yes, then don't generate usual code, but execute the
11080 * genIfx directly -- VR */
11084 /* CHECK: if next iCode is IFX
11085 * and current result operand is nextic's conditional operand
11086 * and current result operand live ranges ends at nextic's key number
11088 if((nextic->op == IFX)
11089 && (result == IC_COND(nextic))
11090 && (OP_LIVETO(result) == nextic->seq)
11091 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11093 /* everything is ok then */
11094 /* find a way to optimize the genIfx iCode */
11096 bytestrt = SPEC_BSTR(operandType(result))/8;
11097 bitstrt = SPEC_BSTR(operandType(result))%8;
11099 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11101 genIfxpCOpJump(nextic, jop);
11103 pic16_freeAsmop(left, NULL, ic, TRUE);
11104 pic16_freeAsmop(result, NULL, ic, TRUE);
11110 /* if bitfield then unpack the bits */
11111 if (IS_BITFIELD(letype))
11112 genUnpackBits (result, left, NULL, POINTER);
11114 /* we have can just get the values */
11115 int size = AOP_SIZE(result);
11118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11120 pic16_loadFSR0( left, 0 );
11124 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11125 pic16_popGet(AOP(result), offset++)));
11127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11128 pic16_popGet(AOP(result), offset++)));
11134 /* now some housekeeping stuff */
11136 /* we had to allocate for this iCode */
11137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11138 pic16_freeAsmop(NULL,aop,ic,TRUE);
11140 /* we did not allocate which means left
11141 * already in a pointer register, then
11142 * if size > 0 && this could be used again
11143 * we have to point it back to where it
11145 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11146 if (AOP_SIZE(result) > 1
11147 && !OP_SYMBOL(left)->remat
11148 && ( OP_SYMBOL(left)->liveTo > ic->seq
11150 // int size = AOP_SIZE(result) - 1;
11152 // pic16_emitcode("dec","%s",rname);
11158 pic16_freeAsmop(left,NULL,ic,TRUE);
11159 pic16_freeAsmop(result,NULL,ic,TRUE);
11162 /*-----------------------------------------------------------------*/
11163 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11164 /*-----------------------------------------------------------------*/
11165 static void genPagedPointerGet (operand *left,
11170 regs *preg = NULL ;
11172 sym_link *rtype, *retype;
11174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11176 rtype = operandType(result);
11177 retype= getSpec(rtype);
11179 pic16_aopOp(left,ic,FALSE);
11181 /* if the value is already in a pointer register
11182 then don't need anything more */
11183 if (!AOP_INPREG(AOP(left))) {
11184 /* otherwise get a free pointer register */
11186 preg = getFreePtr(ic,&aop,FALSE);
11187 pic16_emitcode("mov","%s,%s",
11189 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11190 rname = preg->name ;
11192 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11194 pic16_freeAsmop(left,NULL,ic,TRUE);
11195 pic16_aopOp (result,ic,TRUE);
11197 /* if bitfield then unpack the bits */
11198 if (IS_BITFIELD(retype))
11199 genUnpackBits (result,left,rname,PPOINTER);
11201 /* we have can just get the values */
11202 int size = AOP_SIZE(result);
11207 pic16_emitcode("movx","a,@%s",rname);
11208 pic16_aopPut(AOP(result),"a",offset);
11213 pic16_emitcode("inc","%s",rname);
11217 /* now some housekeeping stuff */
11219 /* we had to allocate for this iCode */
11220 pic16_freeAsmop(NULL,aop,ic,TRUE);
11222 /* we did not allocate which means left
11223 already in a pointer register, then
11224 if size > 0 && this could be used again
11225 we have to point it back to where it
11227 if (AOP_SIZE(result) > 1 &&
11228 !OP_SYMBOL(left)->remat &&
11229 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11231 int size = AOP_SIZE(result) - 1;
11233 pic16_emitcode("dec","%s",rname);
11238 pic16_freeAsmop(result,NULL,ic,TRUE);
11244 /* This code is not adjusted to PIC16 and fails utterly.
11245 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11247 /*-----------------------------------------------------------------*/
11248 /* genFarPointerGet - gget value from far space */
11249 /*-----------------------------------------------------------------*/
11250 static void genFarPointerGet (operand *left,
11251 operand *result, iCode *ic)
11254 sym_link *retype = getSpec(operandType(result));
11256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11258 pic16_aopOp(left,ic,FALSE);
11260 /* if the operand is already in dptr
11261 then we do nothing else we move the value to dptr */
11262 if (AOP_TYPE(left) != AOP_STR) {
11263 /* if this is remateriazable */
11264 if (AOP_TYPE(left) == AOP_IMMD)
11265 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11266 else { /* we need to get it byte by byte */
11267 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11268 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11269 if (options.model == MODEL_FLAT24)
11271 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11275 /* so dptr know contains the address */
11276 pic16_freeAsmop(left,NULL,ic,TRUE);
11277 pic16_aopOp(result,ic,TRUE);
11279 /* if bit then unpack */
11280 if (IS_BITFIELD(retype))
11281 genUnpackBits(result,left,"dptr",FPOINTER);
11283 size = AOP_SIZE(result);
11287 pic16_emitcode("movx","a,@dptr");
11288 pic16_aopPut(AOP(result),"a",offset++);
11290 pic16_emitcode("inc","dptr");
11294 pic16_freeAsmop(result,NULL,ic,TRUE);
11299 /*-----------------------------------------------------------------*/
11300 /* genCodePointerGet - get value from code space */
11301 /*-----------------------------------------------------------------*/
11302 static void genCodePointerGet (operand *left,
11303 operand *result, iCode *ic)
11306 sym_link *retype = getSpec(operandType(result));
11308 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11310 pic16_aopOp(left,ic,FALSE);
11312 /* if the operand is already in dptr
11313 then we do nothing else we move the value to dptr */
11314 if (AOP_TYPE(left) != AOP_STR) {
11315 /* if this is remateriazable */
11316 if (AOP_TYPE(left) == AOP_IMMD)
11317 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11318 else { /* we need to get it byte by byte */
11319 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11320 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11321 if (options.model == MODEL_FLAT24)
11323 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11327 /* so dptr know contains the address */
11328 pic16_freeAsmop(left,NULL,ic,TRUE);
11329 pic16_aopOp(result,ic,FALSE);
11331 /* if bit then unpack */
11332 if (IS_BITFIELD(retype))
11333 genUnpackBits(result,left,"dptr",CPOINTER);
11335 size = AOP_SIZE(result);
11339 pic16_emitcode("clr","a");
11340 pic16_emitcode("movc","a,@a+dptr");
11341 pic16_aopPut(AOP(result),"a",offset++);
11343 pic16_emitcode("inc","dptr");
11347 pic16_freeAsmop(result,NULL,ic,TRUE);
11352 /*-----------------------------------------------------------------*/
11353 /* genGenPointerGet - gget value from generic pointer space */
11354 /*-----------------------------------------------------------------*/
11355 static void genGenPointerGet (operand *left,
11356 operand *result, iCode *ic)
11358 int size, offset, lit;
11359 sym_link *retype = getSpec(operandType(result));
11361 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11362 pic16_aopOp(left,ic,FALSE);
11363 pic16_aopOp(result,ic,FALSE);
11364 size = AOP_SIZE(result);
11366 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11368 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11370 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11371 // load FSR0 from immediate
11372 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11374 // pic16_loadFSR0( left );
11379 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11381 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11388 else { /* we need to get it byte by byte */
11389 // set up FSR0 with address from left
11390 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11391 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11397 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11399 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11406 /* if bit then unpack */
11407 if (IS_BITFIELD(retype))
11408 genUnpackBits(result,left,"BAD",GPOINTER);
11411 pic16_freeAsmop(left,NULL,ic,TRUE);
11412 pic16_freeAsmop(result,NULL,ic,TRUE);
11418 /*-----------------------------------------------------------------*/
11419 /* genGenPointerGet - gget value from generic pointer space */
11420 /*-----------------------------------------------------------------*/
11421 static void genGenPointerGet (operand *left,
11422 operand *result, iCode *ic)
11424 int size, offset, lit;
11425 sym_link *letype = getSpec(operandType(left));
11427 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11428 pic16_aopOp(left,ic,FALSE);
11429 pic16_aopOp(result,ic,TRUE);
11430 size = AOP_SIZE(result);
11432 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11434 /* if bit then unpack */
11435 if (IS_BITFIELD(letype)) {
11436 genUnpackBits(result,left,"BAD",GPOINTER);
11440 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11442 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11443 // load FSR0 from immediate
11444 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11446 werror(W_POSSBUG2, __FILE__, __LINE__);
11451 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11453 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11460 } else { /* we need to get it byte by byte */
11462 /* set up WREG:PRODL:FSR0L with address from left */
11463 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11464 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11465 pic16_mov2w(AOP(left), 2);
11466 pic16_callGenericPointerRW(0, size);
11468 assignResultValue(result, size, 1);
11474 pic16_freeAsmop(left,NULL,ic,TRUE);
11475 pic16_freeAsmop(result,NULL,ic,TRUE);
11478 /*-----------------------------------------------------------------*/
11479 /* genConstPointerGet - get value from const generic pointer space */
11480 /*-----------------------------------------------------------------*/
11481 static void genConstPointerGet (operand *left,
11482 operand *result, iCode *ic)
11484 //sym_link *retype = getSpec(operandType(result));
11485 // symbol *albl = newiTempLabel(NULL); // patch 15
11486 // symbol *blbl = newiTempLabel(NULL); //
11487 // PIC_OPCODE poc; // patch 15
11491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11492 pic16_aopOp(left,ic,FALSE);
11493 pic16_aopOp(result,ic,TRUE);
11494 size = AOP_SIZE(result);
11496 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11498 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11500 // set up table pointer
11501 if( (AOP_TYPE(left) == AOP_PCODE)
11502 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11503 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11505 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11506 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11507 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11508 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11509 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11510 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11512 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11513 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11514 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11518 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11519 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11523 pic16_freeAsmop(left,NULL,ic,TRUE);
11524 pic16_freeAsmop(result,NULL,ic,TRUE);
11528 /*-----------------------------------------------------------------*/
11529 /* genPointerGet - generate code for pointer get */
11530 /*-----------------------------------------------------------------*/
11531 static void genPointerGet (iCode *ic)
11533 operand *left, *result ;
11534 sym_link *type, *etype;
11539 left = IC_LEFT(ic);
11540 result = IC_RESULT(ic) ;
11542 /* depending on the type of pointer we need to
11543 move it to the correct pointer register */
11544 type = operandType(left);
11545 etype = getSpec(type);
11548 if (IS_PTR_CONST(type))
11550 if (IS_CODEPTR(type))
11552 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11554 /* if left is of type of pointer then it is simple */
11555 if (IS_PTR(type) && !IS_FUNC(type->next))
11556 p_type = DCL_TYPE(type);
11558 /* we have to go by the storage class */
11559 p_type = PTR_TYPE(SPEC_OCLS(etype));
11561 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11563 if (SPEC_OCLS(etype)->codesp ) {
11564 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11565 //p_type = CPOINTER ;
11567 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11568 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11569 /*p_type = FPOINTER ;*/
11571 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11572 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11573 /* p_type = PPOINTER; */
11575 if (SPEC_OCLS(etype) == idata ) {
11576 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11577 /* p_type = IPOINTER; */
11579 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11580 /* p_type = POINTER ; */
11584 /* now that we have the pointer type we assign
11585 the pointer values */
11590 genNearPointerGet (left,result,ic);
11594 genPagedPointerGet(left,result,ic);
11598 /* PICs do not support FAR pointers... */
11599 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11601 genFarPointerGet (left,result,ic);
11606 genConstPointerGet (left,result,ic);
11607 //pic16_emitcodePointerGet (left,result,ic);
11612 if (IS_PTR_CONST(type))
11613 genConstPointerGet (left,result,ic);
11616 genGenPointerGet (left,result,ic);
11620 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11621 "genPointerGet: illegal pointer type");
11626 /*-----------------------------------------------------------------*/
11627 /* genPackBits - generates code for packed bit storage */
11628 /*-----------------------------------------------------------------*/
11629 static void genPackBits (sym_link *etype , operand *result,
11631 char *rname, int p_type)
11637 int shifted_and_masked = 0;
11638 unsigned long lit = (unsigned long)-1;
11641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11642 blen = SPEC_BLEN(etype);
11643 bstr = SPEC_BSTR(etype);
11645 retype = getSpec(operandType(right));
11647 if(AOP_TYPE(right) == AOP_LIT) {
11648 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11650 if((blen == 1) && (bstr < 8)) {
11651 /* it is a single bit, so use the appropriate bit instructions */
11653 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11655 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11656 /* workaround to reduce the extra lfsr instruction */
11658 pic16_emitpcode(POC_BSF,
11659 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11661 pic16_emitpcode(POC_BCF,
11662 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11665 if (PIC_IS_DATA_PTR(operandType(result))) {
11666 pic16_loadFSR0(result, 0);
11667 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11668 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11670 /* get old value */
11671 pic16_derefPtr (result, p_type, 0, NULL);
11672 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11673 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11674 /* write back new value */
11675 pic16_derefPtr (result, p_type, 1, NULL);
11681 /* IORLW below is more efficient */
11682 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11683 lit = (lit & ((1UL << blen) - 1)) << bstr;
11684 shifted_and_masked = 1;
11687 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11688 && IS_BITFIELD(retype)
11689 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11693 rblen = SPEC_BLEN( retype );
11694 rbstr = SPEC_BSTR( retype );
11696 if(IS_BITFIELD(etype)) {
11697 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11698 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11700 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11703 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11705 if(IS_BITFIELD(etype)) {
11706 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11708 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11711 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11715 /* move right to W */
11716 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11719 /* if the bit length is less than or */
11720 /* it exactly fits a byte then */
11721 if((shCnt=SPEC_BSTR(etype))
11722 || SPEC_BLEN(etype) <= 8 ) {
11723 int fsr0_setup = 0;
11725 if (blen != 8 || bstr != 0) {
11726 // we need to combine the value with the old value
11727 if(!shifted_and_masked)
11729 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11731 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11732 SPEC_BSTR(etype), SPEC_BLEN(etype));
11734 /* shift left acc, do NOT mask the result again */
11737 /* using PRODH as a temporary register here */
11738 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11741 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11742 || IS_DIRECT(result)) {
11743 /* access symbol directly */
11744 pic16_mov2w (AOP(result), 0);
11746 /* get old value */
11747 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11750 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11751 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11752 (unsigned char)(0xff >> (8-bstr))) ));
11753 if (!shifted_and_masked) {
11754 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11756 /* We have the shifted and masked (literal) right value in `lit' */
11758 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11760 } // if (blen != 8 || bstr != 0)
11762 /* write new value back */
11763 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11764 || IS_DIRECT(result)) {
11765 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11767 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11776 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11777 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11778 exit(EXIT_FAILURE);
11782 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11783 rLen = SPEC_BLEN(etype)-8;
11785 /* now generate for lengths greater than one byte */
11789 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11795 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11801 pic16_emitcode("movx","@dptr,a");
11806 DEBUGpic16_emitcode(";lcall","__gptrput");
11814 pic16_mov2w(AOP(right), offset++);
11817 /* last last was not complete */
11819 /* save the byte & read byte */
11822 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11823 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11828 pic16_emitcode ("mov","b,a");
11829 pic16_emitcode("movx","a,@dptr");
11833 pic16_emitcode ("push","b");
11834 pic16_emitcode ("push","acc");
11835 pic16_emitcode ("lcall","__gptrget");
11836 pic16_emitcode ("pop","b");
11842 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11843 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11844 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11845 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11846 // pic16_emitcode ("orl","a,b");
11849 // if (p_type == GPOINTER)
11850 // pic16_emitcode("pop","b");
11855 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11856 // pic16_emitcode("mov","@%s,a",rname);
11860 pic16_emitcode("movx","@dptr,a");
11864 DEBUGpic16_emitcode(";lcall","__gptrput");
11871 // pic16_freeAsmop(right, NULL, ic, TRUE);
11874 /*-----------------------------------------------------------------*/
11875 /* genDataPointerSet - remat pointer to data space */
11876 /*-----------------------------------------------------------------*/
11877 static void genDataPointerSet(operand *right,
11881 int size, offset = 0, resoffset=0 ;
11883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11884 pic16_aopOp(right,ic,FALSE);
11886 size = AOP_SIZE(right);
11888 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11891 if ( AOP_TYPE(result) == AOP_PCODE) {
11892 fprintf(stderr,"genDataPointerSet %s, %d\n",
11893 AOP(result)->aopu.pcop->name,
11894 (AOP(result)->aopu.pcop->type == PO_DIR)?
11895 PCOR(AOP(result)->aopu.pcop)->instance:
11896 PCOI(AOP(result)->aopu.pcop)->offset);
11900 if(AOP(result)->aopu.pcop->type == PO_DIR)
11901 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11904 if (AOP_TYPE(right) == AOP_LIT) {
11905 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11906 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11908 pic16_mov2w(AOP(right), offset);
11909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11915 pic16_freeAsmop(right,NULL,ic,TRUE);
11920 /*-----------------------------------------------------------------*/
11921 /* genNearPointerSet - pic16_emitcode for near pointer put */
11922 /*-----------------------------------------------------------------*/
11923 static void genNearPointerSet (operand *right,
11929 sym_link *ptype = operandType(result);
11930 sym_link *resetype;
11932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11933 retype= getSpec(operandType(right));
11934 resetype = getSpec(operandType(result));
11936 pic16_aopOp(result,ic,FALSE);
11938 /* if the result is rematerializable &
11939 * in data space & not a bit variable */
11941 /* and result is not a bit variable */
11942 if (AOP_TYPE(result) == AOP_PCODE
11943 // && AOP_TYPE(result) == AOP_IMMD
11944 && DCL_TYPE(ptype) == POINTER
11945 && !IS_BITFIELD(retype)
11946 && !IS_BITFIELD(resetype)) {
11948 genDataPointerSet (right,result,ic);
11949 pic16_freeAsmop(result,NULL,ic,TRUE);
11953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11954 pic16_aopOp(right,ic,FALSE);
11955 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11957 /* if bitfield then unpack the bits */
11958 if (IS_BITFIELD(resetype)) {
11959 genPackBits (resetype, result, right, NULL, POINTER);
11961 /* we have can just get the values */
11962 int size = AOP_SIZE(right);
11965 pic16_loadFSR0(result, 0);
11967 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11969 if (AOP_TYPE(right) == AOP_LIT) {
11970 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11972 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11974 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11976 } else { // no literal
11978 pic16_emitpcode(POC_MOVFF,
11979 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11980 pic16_popCopyReg(&pic16_pc_postinc0)));
11982 pic16_emitpcode(POC_MOVFF,
11983 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11984 pic16_popCopyReg(&pic16_pc_indf0)));
11992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11993 /* now some housekeeping stuff */
11995 /* we had to allocate for this iCode */
11996 pic16_freeAsmop(NULL,aop,ic,TRUE);
11998 /* we did not allocate which means left
11999 * already in a pointer register, then
12000 * if size > 0 && this could be used again
12001 * we have to point it back to where it
12003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12004 if (AOP_SIZE(right) > 1
12005 && !OP_SYMBOL(result)->remat
12006 && ( OP_SYMBOL(result)->liveTo > ic->seq
12009 int size = AOP_SIZE(right) - 1;
12012 pic16_emitcode("decf","fsr0,f");
12013 //pic16_emitcode("dec","%s",rname);
12017 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12020 pic16_freeAsmop(right,NULL,ic,TRUE);
12021 pic16_freeAsmop(result,NULL,ic,TRUE);
12024 /*-----------------------------------------------------------------*/
12025 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12026 /*-----------------------------------------------------------------*/
12027 static void genPagedPointerSet (operand *right,
12032 regs *preg = NULL ;
12036 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12038 retype= getSpec(operandType(right));
12040 pic16_aopOp(result,ic,FALSE);
12042 /* if the value is already in a pointer register
12043 then don't need anything more */
12044 if (!AOP_INPREG(AOP(result))) {
12045 /* otherwise get a free pointer register */
12047 preg = getFreePtr(ic,&aop,FALSE);
12048 pic16_emitcode("mov","%s,%s",
12050 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12051 rname = preg->name ;
12053 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12055 pic16_freeAsmop(result,NULL,ic,TRUE);
12056 pic16_aopOp (right,ic,FALSE);
12058 /* if bitfield then unpack the bits */
12059 if (IS_BITFIELD(retype))
12060 genPackBits (retype,result,right,rname,PPOINTER);
12062 /* we have can just get the values */
12063 int size = AOP_SIZE(right);
12067 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12070 pic16_emitcode("movx","@%s,a",rname);
12073 pic16_emitcode("inc","%s",rname);
12079 /* now some housekeeping stuff */
12081 /* we had to allocate for this iCode */
12082 pic16_freeAsmop(NULL,aop,ic,TRUE);
12084 /* we did not allocate which means left
12085 already in a pointer register, then
12086 if size > 0 && this could be used again
12087 we have to point it back to where it
12089 if (AOP_SIZE(right) > 1 &&
12090 !OP_SYMBOL(result)->remat &&
12091 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12093 int size = AOP_SIZE(right) - 1;
12095 pic16_emitcode("dec","%s",rname);
12100 pic16_freeAsmop(right,NULL,ic,TRUE);
12106 /* This code is not adjusted to PIC16 and fails utterly...
12107 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12109 /*-----------------------------------------------------------------*/
12110 /* genFarPointerSet - set value from far space */
12111 /*-----------------------------------------------------------------*/
12112 static void genFarPointerSet (operand *right,
12113 operand *result, iCode *ic)
12116 sym_link *retype = getSpec(operandType(right));
12118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12119 pic16_aopOp(result,ic,FALSE);
12121 /* if the operand is already in dptr
12122 then we do nothing else we move the value to dptr */
12123 if (AOP_TYPE(result) != AOP_STR) {
12124 /* if this is remateriazable */
12125 if (AOP_TYPE(result) == AOP_IMMD)
12126 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12127 else { /* we need to get it byte by byte */
12128 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12129 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12130 if (options.model == MODEL_FLAT24)
12132 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12136 /* so dptr know contains the address */
12137 pic16_freeAsmop(result,NULL,ic,TRUE);
12138 pic16_aopOp(right,ic,FALSE);
12140 /* if bit then unpack */
12141 if (IS_BITFIELD(retype))
12142 genPackBits(retype,result,right,"dptr",FPOINTER);
12144 size = AOP_SIZE(right);
12148 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12150 pic16_emitcode("movx","@dptr,a");
12152 pic16_emitcode("inc","dptr");
12156 pic16_freeAsmop(right,NULL,ic,TRUE);
12160 /*-----------------------------------------------------------------*/
12161 /* genGenPointerSet - set value from generic pointer space */
12162 /*-----------------------------------------------------------------*/
12164 static void genGenPointerSet (operand *right,
12165 operand *result, iCode *ic)
12167 int i, size, offset, lit;
12168 sym_link *retype = getSpec(operandType(right));
12170 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12172 pic16_aopOp(result,ic,FALSE);
12173 pic16_aopOp(right,ic,FALSE);
12174 size = AOP_SIZE(right);
12177 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12179 /* if the operand is already in dptr
12180 then we do nothing else we move the value to dptr */
12181 if (AOP_TYPE(result) != AOP_STR) {
12182 /* if this is remateriazable */
12183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12184 // WARNING: anythig until "else" is untested!
12185 if (AOP_TYPE(result) == AOP_IMMD) {
12186 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12187 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12188 // load FSR0 from immediate
12189 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12193 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12195 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12201 else { /* we need to get it byte by byte */
12202 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12203 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12205 // set up FSR0 with address of result
12206 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12209 /* hack hack! see if this the FSR. If so don't load W */
12210 if(AOP_TYPE(right) != AOP_ACC) {
12212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12214 if(AOP_TYPE(right) == AOP_LIT)
12217 // note: pic16_popGet handles sign extension
12218 for(i=0;i<size;i++) {
12219 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12221 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12223 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12228 for(i=0;i<size;i++) {
12230 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12231 pic16_popCopyReg(&pic16_pc_postinc0)));
12233 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12234 pic16_popCopyReg(&pic16_pc_indf0)));
12240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12241 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12243 } // if (AOP_TYPE(result) != AOP_IMMD)
12245 } // if (AOP_TYPE(result) != AOP_STR)
12246 /* so dptr know contains the address */
12249 /* if bit then unpack */
12250 if (IS_BITFIELD(retype))
12251 genPackBits(retype,result,right,"dptr",GPOINTER);
12253 size = AOP_SIZE(right);
12256 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12258 // set up FSR0 with address of result
12259 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12260 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12263 if (AOP_TYPE(right) == AOP_LIT) {
12264 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12266 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12268 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12270 } else { // no literal
12272 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12274 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12282 pic16_freeAsmop(right,NULL,ic,TRUE);
12283 pic16_freeAsmop(result,NULL,ic,TRUE);
12287 static void genGenPointerSet (operand *right,
12288 operand *result, iCode *ic)
12291 sym_link *retype = getSpec(operandType(result));
12293 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12295 pic16_aopOp(result,ic,FALSE);
12296 pic16_aopOp(right,ic,FALSE);
12297 size = AOP_SIZE(right);
12299 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12302 /* if bit then unpack */
12303 if (IS_BITFIELD(retype)) {
12304 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12305 genPackBits(retype,result,right,"dptr",GPOINTER);
12309 size = AOP_SIZE(right);
12311 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12314 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12316 /* value of right+0 is placed on stack, which will be retrieved
12317 * by the support function thus restoring the stack. The important
12318 * thing is that there is no need to manually restore stack pointer
12320 pushaop(AOP(right), 0);
12321 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12322 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12323 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12324 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12326 /* load address to write to in WREG:FSR0H:FSR0L */
12327 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12328 pic16_popCopyReg(&pic16_pc_fsr0l)));
12329 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12330 pic16_popCopyReg(&pic16_pc_prodl)));
12331 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12333 pic16_callGenericPointerRW(1, size);
12336 pic16_freeAsmop(right,NULL,ic,TRUE);
12337 pic16_freeAsmop(result,NULL,ic,TRUE);
12340 /*-----------------------------------------------------------------*/
12341 /* genPointerSet - stores the value into a pointer location */
12342 /*-----------------------------------------------------------------*/
12343 static void genPointerSet (iCode *ic)
12345 operand *right, *result ;
12346 sym_link *type, *etype;
12351 right = IC_RIGHT(ic);
12352 result = IC_RESULT(ic) ;
12354 /* depending on the type of pointer we need to
12355 move it to the correct pointer register */
12356 type = operandType(result);
12357 etype = getSpec(type);
12359 /* if left is of type of pointer then it is simple */
12360 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12361 p_type = DCL_TYPE(type);
12364 /* we have to go by the storage class */
12365 p_type = PTR_TYPE(SPEC_OCLS(etype));
12367 /* if (SPEC_OCLS(etype)->codesp ) { */
12368 /* p_type = CPOINTER ; */
12371 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12372 /* p_type = FPOINTER ; */
12374 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12375 /* p_type = PPOINTER ; */
12377 /* if (SPEC_OCLS(etype) == idata ) */
12378 /* p_type = IPOINTER ; */
12380 /* p_type = POINTER ; */
12383 /* now that we have the pointer type we assign
12384 the pointer values */
12389 genNearPointerSet (right,result,ic);
12393 genPagedPointerSet (right,result,ic);
12397 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12399 genFarPointerSet (right,result,ic);
12404 genGenPointerSet (right,result,ic);
12408 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12409 "genPointerSet: illegal pointer type");
12413 /*-----------------------------------------------------------------*/
12414 /* genIfx - generate code for Ifx statement */
12415 /*-----------------------------------------------------------------*/
12416 static void genIfx (iCode *ic, iCode *popIc)
12418 operand *cond = IC_COND(ic);
12423 pic16_aopOp(cond,ic,FALSE);
12425 /* get the value into acc */
12426 if (AOP_TYPE(cond) != AOP_CRY)
12427 pic16_toBoolean(cond);
12430 /* the result is now in the accumulator */
12431 pic16_freeAsmop(cond,NULL,ic,TRUE);
12433 /* if there was something to be popped then do it */
12437 /* if the condition is a bit variable */
12438 if (isbit && IS_ITEMP(cond) &&
12440 genIfxJump(ic,"c");
12441 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12443 if (isbit && !IS_ITEMP(cond))
12444 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12446 genIfxJump(ic,"a");
12451 /*-----------------------------------------------------------------*/
12452 /* genAddrOf - generates code for address of */
12453 /*-----------------------------------------------------------------*/
12454 static void genAddrOf (iCode *ic)
12456 operand *result, *left;
12458 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12459 pCodeOp *pcop0, *pcop1, *pcop2;
12463 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12465 sym = OP_SYMBOL( IC_LEFT(ic) );
12468 /* get address of symbol on stack */
12469 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12471 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12472 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12475 // operands on stack are accessible via "FSR2 + index" with index
12476 // starting at 2 for arguments and growing from 0 downwards for
12477 // local variables (index == 0 is not assigned so we add one here)
12479 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12482 assert (soffs < 0);
12486 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12487 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12488 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12489 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12490 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12491 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12492 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12498 // if(pic16_debug_verbose) {
12499 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12500 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12503 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12504 size = AOP_SIZE(IC_RESULT(ic));
12506 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12507 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12508 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12511 pic16_emitpcode(POC_MOVLW, pcop0);
12512 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12513 pic16_emitpcode(POC_MOVLW, pcop1);
12514 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12515 pic16_emitpcode(POC_MOVLW, pcop2);
12516 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12519 pic16_emitpcode(POC_MOVLW, pcop0);
12520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12521 pic16_emitpcode(POC_MOVLW, pcop1);
12522 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12524 pic16_emitpcode(POC_MOVLW, pcop0);
12525 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12528 pic16_freeAsmop(left, NULL, ic, FALSE);
12530 pic16_freeAsmop(result,NULL,ic,TRUE);
12535 /*-----------------------------------------------------------------*/
12536 /* genFarFarAssign - assignment when both are in far space */
12537 /*-----------------------------------------------------------------*/
12538 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12540 int size = AOP_SIZE(right);
12543 /* first push the right side on to the stack */
12545 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12547 pic16_emitcode ("push","acc");
12550 pic16_freeAsmop(right,NULL,ic,FALSE);
12551 /* now assign DPTR to result */
12552 pic16_aopOp(result,ic,FALSE);
12553 size = AOP_SIZE(result);
12555 pic16_emitcode ("pop","acc");
12556 pic16_aopPut(AOP(result),"a",--offset);
12558 pic16_freeAsmop(result,NULL,ic,FALSE);
12563 /*-----------------------------------------------------------------*/
12564 /* genAssign - generate code for assignment */
12565 /*-----------------------------------------------------------------*/
12566 static void genAssign (iCode *ic)
12568 operand *result, *right;
12569 sym_link *restype, *rtype;
12570 int size, offset,know_W;
12571 unsigned long lit = 0L;
12573 result = IC_RESULT(ic);
12574 right = IC_RIGHT(ic) ;
12578 /* if they are the same */
12579 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12582 /* reversed order operands are aopOp'ed so that result operand
12583 * is effective in case right is a stack symbol. This maneauver
12584 * allows to use the _G.resDirect flag later */
12585 pic16_aopOp(result,ic,TRUE);
12586 pic16_aopOp(right,ic,FALSE);
12588 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12590 /* if they are the same registers */
12591 if (pic16_sameRegs(AOP(right),AOP(result)))
12594 /* if the result is a bit */
12595 if (AOP_TYPE(result) == AOP_CRY) {
12596 /* if the right size is a literal then
12597 we know what the value is */
12598 if (AOP_TYPE(right) == AOP_LIT) {
12600 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12601 pic16_popGet(AOP(result),0));
12603 if (((int) operandLitValue(right)))
12604 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12605 AOP(result)->aopu.aop_dir,
12606 AOP(result)->aopu.aop_dir);
12608 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12609 AOP(result)->aopu.aop_dir,
12610 AOP(result)->aopu.aop_dir);
12615 /* the right is also a bit variable */
12616 if (AOP_TYPE(right) == AOP_CRY) {
12617 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12618 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12619 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12624 /* we need to or */
12625 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12626 pic16_toBoolean(right);
12628 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12629 //pic16_aopPut(AOP(result),"a",0);
12633 /* bit variables done */
12635 size = AOP_SIZE(result);
12638 /* bit variables done */
12640 size = AOP_SIZE(result);
12641 restype = operandType(result);
12642 rtype = operandType(right);
12645 if(AOP_TYPE(right) == AOP_LIT) {
12646 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12648 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12650 /* patch tag for literals that are cast to pointers */
12651 if (IS_CODEPTR(restype)) {
12652 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12653 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12655 if (IS_GENPTR(restype))
12657 if (IS_CODEPTR(rtype)) {
12658 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12659 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12660 } else if (PIC_IS_DATA_PTR(rtype)) {
12661 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12662 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12663 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12664 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12665 } else if (IS_PTR(rtype)) {
12666 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12667 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12673 unsigned long lit_int;
12678 if(IS_FIXED16X16(operandType(right))) {
12679 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12681 /* take care if literal is a float */
12682 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12683 lit = info.lit_int;
12688 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12689 // sizeof(unsigned long int), sizeof(float));
12692 if (AOP_TYPE(right) == AOP_REG) {
12693 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12695 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12700 /* when do we have to read the program memory?
12701 * - if right itself is a symbol in code space
12702 * (we don't care what it points to if it's a pointer)
12703 * - AND right is not a function (we would want its address)
12705 if(AOP_TYPE(right) != AOP_LIT
12706 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12707 && !IS_FUNC(OP_SYM_TYPE(right))
12708 && !IS_ITEMP(right)) {
12710 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12711 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12713 // set up table pointer
12714 if(is_LitOp(right)) {
12715 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12716 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12717 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12718 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12719 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12720 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12721 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12723 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12724 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12725 pic16_popCopyReg(&pic16_pc_tblptrl)));
12726 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12727 pic16_popCopyReg(&pic16_pc_tblptrh)));
12728 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12729 pic16_popCopyReg(&pic16_pc_tblptru)));
12732 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12733 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12735 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12736 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12737 pic16_popGet(AOP(result),offset)));
12741 /* FIXME: for pointers we need to extend differently (according
12742 * to pointer type DATA/CODE/EEPROM/... :*/
12743 size = getSize(OP_SYM_TYPE(right));
12744 if(AOP_SIZE(result) > size) {
12745 size = AOP_SIZE(result) - size;
12747 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12755 /* VR - What is this?! */
12756 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12759 if(aopIdx(AOP(result),0) == 4) {
12760 /* this is a workaround to save value of right into wreg too,
12761 * value of wreg is going to be used later */
12762 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12768 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12772 size = AOP_SIZE(right);
12773 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12776 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12777 if(AOP_TYPE(right) == AOP_LIT) {
12779 if(know_W != (lit&0xff))
12780 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12782 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12784 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12788 } else if (AOP_TYPE(right) == AOP_CRY) {
12789 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12791 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12792 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12793 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12795 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12796 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12797 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12801 if(!_G.resDirect) { /* use this aopForSym feature */
12802 if(AOP_TYPE(result) == AOP_ACC) {
12803 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12805 if(AOP_TYPE(right) == AOP_ACC) {
12806 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12808 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12815 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12818 pic16_freeAsmop (right,NULL,ic,FALSE);
12819 pic16_freeAsmop (result,NULL,ic,TRUE);
12822 /*-----------------------------------------------------------------*/
12823 /* genJumpTab - generates code for jump table */
12824 /*-----------------------------------------------------------------*/
12825 static void genJumpTab (iCode *ic)
12830 pCodeOp *jt_offs_hi;
12835 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12836 /* get the condition into accumulator */
12837 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12839 /* multiply by three */
12840 pic16_emitcode("add","a,acc");
12841 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12843 jtab = newiTempLabel(NULL);
12844 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12845 pic16_emitcode("jmp","@a+dptr");
12846 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12849 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12850 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12852 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12853 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12854 pic16_emitpLabel(jtab->key);
12858 jt_offs = pic16_popGetTempReg(0);
12859 jt_offs_hi = pic16_popGetTempReg(1);
12860 jt_label = pic16_popGetLabel (jtab->key);
12861 //fprintf (stderr, "Creating jump table...\n");
12863 // calculate offset into jump table (idx * sizeof (GOTO))
12864 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12865 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12866 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12867 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12868 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12869 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12870 pic16_emitpcode(POC_MOVWF , jt_offs);
12872 // prepare PCLATx (set to first entry in jump table)
12873 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12874 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12875 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12876 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12877 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12879 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12880 pic16_emitpcode(POC_ADDWF , jt_offs);
12881 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12882 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12884 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12886 // release temporaries and prepare jump into table (new PCL --> WREG)
12887 pic16_emitpcode(POC_MOVFW , jt_offs);
12888 pic16_popReleaseTempReg (jt_offs_hi, 1);
12889 pic16_popReleaseTempReg (jt_offs, 0);
12891 // jump into the table
12892 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12894 pic16_emitpLabelFORCE(jtab->key);
12897 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12898 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12900 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12901 /* now generate the jump labels */
12902 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12903 jtab = setNextItem(IC_JTLABELS(ic))) {
12904 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12905 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12908 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12912 /*-----------------------------------------------------------------*/
12913 /* genMixedOperation - gen code for operators between mixed types */
12914 /*-----------------------------------------------------------------*/
12916 TSD - Written for the PIC port - but this unfortunately is buggy.
12917 This routine is good in that it is able to efficiently promote
12918 types to different (larger) sizes. Unfortunately, the temporary
12919 variables that are optimized out by this routine are sometimes
12920 used in other places. So until I know how to really parse the
12921 iCode tree, I'm going to not be using this routine :(.
12923 static int genMixedOperation (iCode *ic)
12926 operand *result = IC_RESULT(ic);
12927 sym_link *ctype = operandType(IC_LEFT(ic));
12928 operand *right = IC_RIGHT(ic);
12934 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12936 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12942 nextright = IC_RIGHT(nextic);
12943 nextleft = IC_LEFT(nextic);
12944 nextresult = IC_RESULT(nextic);
12946 pic16_aopOp(right,ic,FALSE);
12947 pic16_aopOp(result,ic,FALSE);
12948 pic16_aopOp(nextright, nextic, FALSE);
12949 pic16_aopOp(nextleft, nextic, FALSE);
12950 pic16_aopOp(nextresult, nextic, FALSE);
12952 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12954 operand *t = right;
12958 pic16_emitcode(";remove right +","");
12960 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12962 operand *t = right;
12966 pic16_emitcode(";remove left +","");
12970 big = AOP_SIZE(nextleft);
12971 small = AOP_SIZE(nextright);
12973 switch(nextic->op) {
12976 pic16_emitcode(";optimize a +","");
12977 /* if unsigned or not an integral type */
12978 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12979 pic16_emitcode(";add a bit to something","");
12982 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12984 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12985 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12986 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12988 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12996 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12997 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12998 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13001 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13003 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13004 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13005 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13006 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13007 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13010 pic16_emitcode("rlf","known_zero,w");
13017 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13018 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13019 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13021 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13031 pic16_freeAsmop(right,NULL,ic,TRUE);
13032 pic16_freeAsmop(result,NULL,ic,TRUE);
13033 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13034 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13036 nextic->generated = 1;
13043 /*-----------------------------------------------------------------*/
13044 /* genCast - gen code for casting */
13045 /*-----------------------------------------------------------------*/
13046 static void genCast (iCode *ic)
13048 operand *result = IC_RESULT(ic);
13049 sym_link *ctype = operandType(IC_LEFT(ic));
13050 sym_link *rtype = operandType(IC_RIGHT(ic));
13051 sym_link *restype = operandType(IC_RESULT(ic));
13052 operand *right = IC_RIGHT(ic);
13058 /* if they are equivalent then do nothing */
13059 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13062 pic16_aopOp(result,ic,FALSE);
13063 pic16_aopOp(right,ic,FALSE) ;
13065 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13068 /* if the result is a bit */
13069 if (AOP_TYPE(result) == AOP_CRY) {
13071 /* if the right size is a literal then
13072 * we know what the value is */
13073 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13075 if (AOP_TYPE(right) == AOP_LIT) {
13076 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13077 pic16_popGet(AOP(result),0));
13079 if (((int) operandLitValue(right)))
13080 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13081 AOP(result)->aopu.aop_dir,
13082 AOP(result)->aopu.aop_dir);
13084 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13085 AOP(result)->aopu.aop_dir,
13086 AOP(result)->aopu.aop_dir);
13090 /* the right is also a bit variable */
13091 if (AOP_TYPE(right) == AOP_CRY) {
13093 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13095 pic16_emitcode("clrc","");
13096 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13097 AOP(right)->aopu.aop_dir,
13098 AOP(right)->aopu.aop_dir);
13099 pic16_aopPut(AOP(result),"c",0);
13103 /* we need to or */
13104 if (AOP_TYPE(right) == AOP_REG) {
13105 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13106 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13107 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13109 pic16_toBoolean(right);
13110 pic16_aopPut(AOP(result),"a",0);
13114 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13117 size = AOP_SIZE(result);
13119 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13121 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13122 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13123 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13126 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13131 if(IS_BITFIELD(getSpec(restype))
13132 && IS_BITFIELD(getSpec(rtype))) {
13133 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13136 /* port from pic14 to cope with generic pointers */
13137 if (PIC_IS_TAGGED(restype))
13139 operand *result = IC_RESULT(ic);
13140 //operand *left = IC_LEFT(ic);
13141 operand *right = IC_RIGHT(ic);
13144 /* copy common part */
13145 int max, size = AOP_SIZE(result);
13146 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13147 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13152 pic16_mov2w (AOP(right), size);
13153 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13156 /* upcast into generic pointer type? */
13157 if (IS_GENPTR(restype)
13158 && !PIC_IS_TAGGED(rtype)
13159 && (AOP_SIZE(result) > max))
13161 /* determine appropriate tag for right */
13162 if (PIC_IS_DATA_PTR(rtype))
13163 tag = GPTR_TAG_DATA;
13164 else if (IS_CODEPTR(rtype))
13165 tag = GPTR_TAG_CODE;
13166 else if (PIC_IS_DATA_PTR(ctype)) {
13167 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13168 tag = GPTR_TAG_DATA;
13169 } else if (IS_CODEPTR(ctype)) {
13170 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13171 tag = GPTR_TAG_CODE;
13172 } else if (IS_PTR(rtype)) {
13173 PERFORM_ONCE(weirdcast,
13174 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13176 tag = GPTR_TAG_DATA;
13178 PERFORM_ONCE(weirdcast,
13179 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13181 tag = GPTR_TAG_DATA;
13184 assert (AOP_SIZE(result) == 3);
13185 /* zero-extend address... */
13186 for (size = max; size < AOP_SIZE(result)-1; size++)
13187 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13188 /* ...and add tag */
13189 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13190 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13191 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13192 for (size = max; size < AOP_SIZE(result)-1; size++)
13193 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13194 /* add __code tag */
13195 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13196 } else if (AOP_SIZE(result) > max) {
13197 /* extend non-pointers */
13198 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13199 pic16_addSign(result, max, 0);
13204 /* if they are the same size : or less */
13205 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13207 /* if they are in the same place */
13208 if (pic16_sameRegs(AOP(right),AOP(result)))
13211 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13213 if (IS_PTR_CONST(rtype))
13215 if (IS_CODEPTR(rtype))
13217 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13220 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13222 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13224 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13227 if(AOP_TYPE(right) == AOP_IMMD) {
13228 pCodeOp *pcop0, *pcop1, *pcop2;
13229 symbol *sym = OP_SYMBOL( right );
13231 size = AOP_SIZE(result);
13233 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13235 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13237 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13240 pic16_emitpcode(POC_MOVLW, pcop0);
13241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13242 pic16_emitpcode(POC_MOVLW, pcop1);
13243 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13244 pic16_emitpcode(POC_MOVLW, pcop2);
13245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13248 pic16_emitpcode(POC_MOVLW, pcop0);
13249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13250 pic16_emitpcode(POC_MOVLW, pcop1);
13251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13253 pic16_emitpcode(POC_MOVLW, pcop0);
13254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13258 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13259 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13260 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13262 if(AOP_SIZE(result) < 2) {
13263 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13265 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13266 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13269 /* if they in different places then copy */
13270 size = AOP_SIZE(result);
13273 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13274 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13281 /* if the result is of type pointer */
13282 if (IS_PTR(ctype)) {
13284 sym_link *type = operandType(right);
13285 sym_link *etype = getSpec(type);
13287 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13289 /* pointer to generic pointer */
13290 if (IS_GENPTR(ctype)) {
13294 p_type = DCL_TYPE(type);
13296 /* we have to go by the storage class */
13297 p_type = PTR_TYPE(SPEC_OCLS(etype));
13299 /* if (SPEC_OCLS(etype)->codesp ) */
13300 /* p_type = CPOINTER ; */
13302 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13303 /* p_type = FPOINTER ; */
13305 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13306 /* p_type = PPOINTER; */
13308 /* if (SPEC_OCLS(etype) == idata ) */
13309 /* p_type = IPOINTER ; */
13311 /* p_type = POINTER ; */
13314 /* the first two bytes are known */
13315 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13316 size = GPTRSIZE - 1;
13319 if(offset < AOP_SIZE(right)) {
13320 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13321 pic16_mov2f(AOP(result), AOP(right), offset);
13323 if ((AOP_TYPE(right) == AOP_PCODE) &&
13324 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13325 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13326 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13329 pic16_aopPut(AOP(result),
13330 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13335 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13338 /* the last byte depending on type */
13343 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13347 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13351 pic16_emitcode(";BUG!? ","%d",__LINE__);
13356 if (GPTRSIZE > AOP_SIZE(right)) {
13357 // assume __data pointer... THIS MIGHT BE WRONG!
13358 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13360 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13365 /* this should never happen */
13366 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13367 "got unknown pointer type");
13370 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13376 /* just copy the pointers */
13377 size = AOP_SIZE(result);
13380 pic16_aopPut(AOP(result),
13381 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13390 /* so we now know that the size of destination is greater
13391 than the size of the source.
13392 Now, if the next iCode is an operator then we might be
13393 able to optimize the operation without performing a cast.
13395 if(genMixedOperation(ic))
13398 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13400 /* we move to result for the size of source */
13401 size = AOP_SIZE(right);
13406 pic16_mov2f(AOP(result), AOP(right), offset);
13410 /* now depending on the sign of the destination */
13411 size = AOP_SIZE(result) - AOP_SIZE(right);
13412 /* if unsigned or not an integral type */
13413 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13415 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13417 /* we need to extend the sign :( */
13420 /* Save one instruction of casting char to int */
13421 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13422 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13423 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13425 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13428 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13430 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13432 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13435 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13440 pic16_freeAsmop(right,NULL,ic,TRUE);
13441 pic16_freeAsmop(result,NULL,ic,TRUE);
13445 /*-----------------------------------------------------------------*/
13446 /* genDjnz - generate decrement & jump if not zero instrucion */
13447 /*-----------------------------------------------------------------*/
13448 static int genDjnz (iCode *ic, iCode *ifx)
13450 symbol *lbl, *lbl1;
13451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13456 /* if the if condition has a false label
13457 then we cannot save */
13461 /* if the minus is not of the form
13463 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13464 !IS_OP_LITERAL(IC_RIGHT(ic)))
13467 if (operandLitValue(IC_RIGHT(ic)) != 1)
13470 /* if the size of this greater than one then no
13472 if (getSize(operandType(IC_RESULT(ic))) > 1)
13475 /* otherwise we can save BIG */
13476 lbl = newiTempLabel(NULL);
13477 lbl1= newiTempLabel(NULL);
13479 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13481 if (IS_AOP_PREG(IC_RESULT(ic))) {
13482 pic16_emitcode("dec","%s",
13483 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13484 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13485 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13489 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13490 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13492 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13493 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13497 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13498 ifx->generated = 1;
13502 /*-----------------------------------------------------------------*/
13503 /* genReceive - generate code for a receive iCode */
13504 /*-----------------------------------------------------------------*/
13505 static void genReceive (iCode *ic)
13511 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13512 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13514 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13516 if (isOperandInFarSpace(IC_RESULT(ic))
13517 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13518 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13520 int size = getSize(operandType(IC_RESULT(ic)));
13521 int offset = pic16_fReturnSizePic - size;
13525 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13526 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13530 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13532 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13533 size = AOP_SIZE(IC_RESULT(ic));
13536 pic16_emitcode ("pop","acc");
13537 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13540 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13542 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13545 /* set pseudo stack pointer to where it should be - dw*/
13546 GpsuedoStkPtr = ic->parmBytes;
13548 /* setting GpsuedoStkPtr has side effects here: */
13549 /* FIXME: What's the correct size of the return(ed) value?
13550 * For now, assuming '4' as before... */
13551 assignResultValue(IC_RESULT(ic), 4, 0);
13554 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13557 /*-----------------------------------------------------------------*/
13558 /* genDummyRead - generate code for dummy read of volatiles */
13559 /*-----------------------------------------------------------------*/
13561 genDummyRead (iCode * ic)
13567 if (op && IS_SYMOP(op)) {
13568 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13569 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13572 pic16_aopOp (op, ic, FALSE);
13573 for (i=0; i < AOP_SIZE(op); i++) {
13574 // may need to protect this from the peepholer -- this is not nice but works...
13575 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13576 pic16_mov2w (AOP(op),i);
13577 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13579 pic16_freeAsmop (op, NULL, ic, TRUE);
13581 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13585 /*-----------------------------------------------------------------*/
13586 /* genpic16Code - generate code for pic16 based controllers */
13587 /*-----------------------------------------------------------------*/
13589 * At this point, ralloc.c has gone through the iCode and attempted
13590 * to optimize in a way suitable for a PIC. Now we've got to generate
13591 * PIC instructions that correspond to the iCode.
13593 * Once the instructions are generated, we'll pass through both the
13594 * peep hole optimizer and the pCode optimizer.
13595 *-----------------------------------------------------------------*/
13597 void genpic16Code (iCode *lic)
13602 lineHead = lineCurr = NULL;
13604 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13605 pic16_addpBlock(pb);
13608 /* if debug information required */
13609 if (options.debug && currFunc) {
13611 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13616 for (ic = lic ; ic ; ic = ic->next ) {
13618 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13619 if ( cln != ic->lineno ) {
13620 if ( options.debug ) {
13621 debugFile->writeCLine (ic);
13624 if(!options.noCcodeInAsm) {
13625 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13626 printCLine(ic->filename, ic->lineno)));
13632 if(options.iCodeInAsm) {
13635 /* insert here code to print iCode as comment */
13636 l = Safe_strdup(printILine(ic));
13637 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13640 /* if the result is marked as
13641 * spilt and rematerializable or code for
13642 * this has already been generated then
13644 if (resultRemat(ic) || ic->generated )
13647 /* depending on the operation */
13666 /* IPOP happens only when trying to restore a
13667 * spilt live range, if there is an ifx statement
13668 * following this pop then the if statement might
13669 * be using some of the registers being popped which
13670 * would destroy the contents of the register so
13671 * we need to check for this condition and handle it */
13673 && ic->next->op == IFX
13674 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13675 genIfx (ic->next,ic);
13693 genEndFunction (ic);
13709 pic16_genPlus (ic) ;
13713 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13714 pic16_genMinus (ic);
13730 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13734 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13740 /* note these two are xlated by algebraic equivalence
13741 * during parsing SDCC.y */
13742 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13743 "got '>=' or '<=' shouldn't have come here");
13747 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13759 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13763 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13767 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13791 genRightShift (ic);
13794 case GET_VALUE_AT_ADDRESS:
13799 if (POINTER_SET(ic))
13826 addSet(&_G.sendSet,ic);
13829 case DUMMY_READ_VOLATILE:
13839 /* now we are ready to call the
13840 peep hole optimizer */
13841 if (!options.nopeep)
13842 peepHole (&lineHead);
13844 /* now do the actual printing */
13845 printLine (lineHead, codeOutFile);
13848 DFPRINTF((stderr,"printing pBlock\n\n"));
13849 pic16_printpBlock(stdout,pb);