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 pic16_emitcode("","%s:",sym->rname);
3709 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3714 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3715 if(!strcmp(ab->name, sym->rname)) {
3716 pic16_pBlockConvert2Absolute(pb);
3722 if(IFFUNC_ISNAKED(ftype)) {
3723 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3727 /* if critical function then turn interrupts off */
3728 if (IFFUNC_ISCRITICAL(ftype)) {
3729 //pic16_emitcode("clr","ea");
3732 currFunc = sym; /* update the currFunc symbol */
3733 _G.fregsUsed = sym->regsUsed;
3734 _G.sregsAlloc = newBitVect(128);
3737 /* if this is an interrupt service routine then
3738 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3739 if (IFFUNC_ISISR(sym->type)) {
3740 _G.usefastretfie = 1; /* use shadow registers by default */
3742 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3743 if(!FUNC_ISSHADOWREGS(sym->type)) {
3744 /* do not save WREG,STATUS,BSR for high priority interrupts
3745 * because they are stored in the hardware shadow registers already */
3746 _G.usefastretfie = 0;
3747 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3748 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3749 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3752 /* these should really be optimized somehow, because not all
3753 * interrupt handlers modify them */
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3759 // pic16_pBlockConvert2ISR(pb);
3762 /* emit code to setup stack frame if user enabled,
3763 * and function is not main() */
3765 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3766 if(strcmp(sym->name, "main")) {
3768 || !options.ommitFramePtr
3770 || IFFUNC_ARGS(sym->type)
3771 || FUNC_HASSTACKPARM(sym->etype)
3773 /* setup the stack frame */
3774 if(STACK_MODEL_LARGE)
3775 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3776 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3778 if(STACK_MODEL_LARGE)
3779 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3780 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3784 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3787 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3789 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3790 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3792 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3795 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3796 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3803 /* if callee-save to be used for this function
3804 * then save the registers being used in this function */
3805 // if (IFFUNC_CALLEESAVES(sym->type))
3806 if(strcmp(sym->name, "main")) {
3809 /* if any registers used */
3810 if (sym->regsUsed) {
3811 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3814 /* save the registers used */
3815 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3816 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3817 if (bitVectBitValue(sym->regsUsed,i)) {
3819 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3821 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3824 if(!pic16_regWithIdx(i)->wasUsed) {
3825 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3826 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3827 pic16_regWithIdx(i)->wasUsed = 1;
3834 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3835 for(i=0;i<sym->regsUsed->size;i++) {
3836 if(bitVectBitValue(sym->regsUsed, i)) {
3841 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3844 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3849 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3850 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3853 /*-----------------------------------------------------------------*/
3854 /* genEndFunction - generates epilogue for functions */
3855 /*-----------------------------------------------------------------*/
3856 static void genEndFunction (iCode *ic)
3858 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3862 if(IFFUNC_ISNAKED(sym->type)) {
3863 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3869 /* add code for ISCRITICAL */
3870 if(IFFUNC_ISCRITICAL(sym->type)) {
3871 /* if critical function, turn on interrupts */
3873 /* TODO: add code here -- VR */
3876 // sym->regsUsed = _G.fregsUsed;
3878 /* now we need to restore the registers */
3879 /* if any registers used */
3881 /* first restore registers that might be used for stack access */
3882 if(_G.sregsAllocSet) {
3885 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3886 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3887 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3891 if (strcmp(sym->name, "main") && sym->regsUsed) {
3894 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3895 /* restore registers used */
3896 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3897 for ( i = sym->regsUsed->size; i >= 0; i--) {
3898 if (bitVectBitValue(sym->regsUsed,i)) {
3899 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3903 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3908 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3910 if (sym->stack == 1) {
3911 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3912 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3914 // we have to add more than one...
3915 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3916 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3917 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3919 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3920 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3921 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3925 if(strcmp(sym->name, "main")) {
3927 || !options.ommitFramePtr
3929 || IFFUNC_ARGS(sym->type)
3930 || FUNC_HASSTACKPARM(sym->etype)
3932 /* restore stack frame */
3933 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3934 if(STACK_MODEL_LARGE)
3935 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3941 if (IFFUNC_ISISR(sym->type)) {
3942 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3943 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3944 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3945 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3947 if(!FUNC_ISSHADOWREGS(sym->type)) {
3948 /* do not restore interrupt vector for WREG,STATUS,BSR
3949 * for high priority interrupt, see genFunction */
3950 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3951 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3952 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3954 // _G.interruptvector = 0; /* sanity check */
3957 /* if debug then send end of function */
3958 /* if (options.debug && currFunc) */
3960 debugFile->writeEndFunction (currFunc, ic, 1);
3963 if(_G.usefastretfie)
3964 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3966 pic16_emitpcodeNULLop(POC_RETFIE);
3968 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3970 _G.usefastretfie = 0;
3974 if (IFFUNC_ISCRITICAL(sym->type)) {
3975 pic16_emitcode("setb","ea");
3978 /* if debug then send end of function */
3980 debugFile->writeEndFunction (currFunc, ic, 1);
3983 /* insert code to restore stack frame, if user enabled it
3984 * and function is not main() */
3987 pic16_emitpcodeNULLop(POC_RETURN);
3989 /* Mark the end of a function */
3990 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3994 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3996 unsigned long lit=1;
4001 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4002 if(AOP_TYPE(op) == AOP_LIT) {
4003 if(!IS_FLOAT(operandType( op ))) {
4004 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4007 unsigned long lit_int;
4011 /* take care if literal is a float */
4012 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4017 if (AOP_TYPE(op) == AOP_LIT) {
4018 /* FIXME: broken for
4019 * char __at(0x456) foo;
4021 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4022 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4023 } else if (AOP_TYPE(op) == AOP_PCODE
4024 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4025 /* char *s= "aaa"; return s; */
4026 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4027 * that the generic pointer is interpreted correctly
4028 * as referring to __code space, but this is fragile! */
4029 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4030 /* XXX: should check that dest != WREG */
4031 pic16_emitpcode(POC_MOVWF, dest);
4033 if(dest->type == PO_WREG && (offset == 0)) {
4034 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4037 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4041 /*-----------------------------------------------------------------*/
4042 /* genRet - generate code for return statement */
4043 /*-----------------------------------------------------------------*/
4044 static void genRet (iCode *ic)
4050 /* if we have no return value then
4051 * just generate the "ret" */
4056 /* we have something to return then
4057 * move the return value into place */
4058 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4059 size = AOP_SIZE(IC_LEFT(ic));
4063 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4066 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4069 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4071 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4074 /* >32-bits, setup stack and FSR0 */
4076 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4077 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4079 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4081 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4086 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4087 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4089 if(STACK_MODEL_LARGE) {
4090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4091 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4093 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4098 /* old code, left here for reference -- VR */
4102 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4104 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4105 pic16_emitpcomment("push %s",l);
4108 DEBUGpic16_emitcode(";", "%d", __LINE__);
4109 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4110 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4112 if (strcmp(fReturn[offset],l)) {
4113 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4114 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4115 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4117 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4121 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4131 if (strcmp(fReturn[pushed],"a"))
4132 pic16_emitcode("pop",fReturn[pushed]);
4134 pic16_emitcode("pop","acc");
4140 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4143 /* generate a jump to the return label
4144 * if the next is not the return statement */
4145 if (!(ic->next && ic->next->op == LABEL
4146 && IC_LABEL(ic->next) == returnLabel)) {
4148 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4149 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4153 /*-----------------------------------------------------------------*/
4154 /* genLabel - generates a label */
4155 /*-----------------------------------------------------------------*/
4156 static void genLabel (iCode *ic)
4160 /* special case never generate */
4161 if (IC_LABEL(ic) == entryLabel)
4164 pic16_emitpLabel(IC_LABEL(ic)->key);
4165 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4168 /*-----------------------------------------------------------------*/
4169 /* genGoto - generates a goto */
4170 /*-----------------------------------------------------------------*/
4172 static void genGoto (iCode *ic)
4175 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4176 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4180 /*-----------------------------------------------------------------*/
4181 /* genMultbits :- multiplication of bits */
4182 /*-----------------------------------------------------------------*/
4183 static void genMultbits (operand *left,
4189 if(!pic16_sameRegs(AOP(result),AOP(right)))
4190 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4192 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4193 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4194 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4199 /*-----------------------------------------------------------------*/
4200 /* genMultOneByte : 8 bit multiplication & division */
4201 /*-----------------------------------------------------------------*/
4202 static void genMultOneByte (operand *left,
4208 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4209 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4211 /* (if two literals, the value is computed before) */
4212 /* if one literal, literal on the right */
4213 if (AOP_TYPE(left) == AOP_LIT){
4219 /* size is already checked in genMult == 1 */
4220 // size = AOP_SIZE(result);
4222 if (AOP_TYPE(right) == AOP_LIT){
4223 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4224 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4225 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4226 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4228 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4229 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4230 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4231 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4234 pic16_genMult8X8_n (left, right,result);
4238 /*-----------------------------------------------------------------*/
4239 /* genMultOneWord : 16 bit multiplication */
4240 /*-----------------------------------------------------------------*/
4241 static void genMultOneWord (operand *left,
4246 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4247 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4249 /* (if two literals, the value is computed before)
4250 * if one literal, literal on the right */
4251 if (AOP_TYPE(left) == AOP_LIT){
4257 /* size is checked already == 2 */
4258 // size = AOP_SIZE(result);
4260 if (AOP_TYPE(right) == AOP_LIT) {
4261 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4262 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4263 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4264 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4266 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4267 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4268 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4269 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4272 pic16_genMult16X16_16(left, right,result);
4277 /*-----------------------------------------------------------------*/
4278 /* genMultOneLong : 32 bit multiplication */
4279 /*-----------------------------------------------------------------*/
4280 static void genMultOneLong (operand *left,
4285 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4286 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4288 /* (if two literals, the value is computed before)
4289 * if one literal, literal on the right */
4290 if (AOP_TYPE(left) == AOP_LIT){
4296 /* size is checked already == 4 */
4297 // size = AOP_SIZE(result);
4299 if (AOP_TYPE(right) == AOP_LIT) {
4300 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4301 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4302 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4303 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4305 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4306 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4307 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4308 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4311 pic16_genMult32X32_32(left, right,result);
4317 /*-----------------------------------------------------------------*/
4318 /* genMult - generates code for multiplication */
4319 /*-----------------------------------------------------------------*/
4320 static void genMult (iCode *ic)
4322 operand *left = IC_LEFT(ic);
4323 operand *right = IC_RIGHT(ic);
4324 operand *result= IC_RESULT(ic);
4327 /* assign the amsops */
4328 pic16_aopOp (left,ic,FALSE);
4329 pic16_aopOp (right,ic,FALSE);
4330 pic16_aopOp (result,ic,TRUE);
4332 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4334 /* special cases first *
4336 if (AOP_TYPE(left) == AOP_CRY
4337 && AOP_TYPE(right)== AOP_CRY) {
4338 genMultbits(left,right,result);
4342 /* if both are of size == 1 */
4343 if(AOP_SIZE(left) == 1
4344 && AOP_SIZE(right) == 1) {
4345 genMultOneByte(left,right,result);
4350 /* if both are of size == 2 */
4351 if(AOP_SIZE(left) == 2
4352 && AOP_SIZE(right) == 2) {
4353 genMultOneWord(left, right, result);
4357 /* if both are of size == 4 */
4358 if(AOP_SIZE(left) == 4
4359 && AOP_SIZE(right) == 4) {
4360 genMultOneLong(left, right, result);
4365 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4366 assert( !"Multiplication should have been transformed into function call!" );
4368 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4371 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4372 /* should have been converted to function call */
4376 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4377 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4378 pic16_freeAsmop(result,NULL,ic,TRUE);
4382 /*-----------------------------------------------------------------*/
4383 /* genDivbits :- division of bits */
4384 /*-----------------------------------------------------------------*/
4385 static void genDivbits (operand *left,
4392 /* the result must be bit */
4393 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4394 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4398 pic16_emitcode("div","ab");
4399 pic16_emitcode("rrc","a");
4400 pic16_aopPut(AOP(result),"c",0);
4403 /*-----------------------------------------------------------------*/
4404 /* genDivOneByte : 8 bit division */
4405 /*-----------------------------------------------------------------*/
4406 static void genDivOneByte (operand *left,
4410 sym_link *opetype = operandType(result);
4415 /* result = divident / divisor
4416 * - divident may be a register or a literal,
4417 * - divisor may be a register or a literal,
4418 * so there are 3 cases (literal / literal is optimized
4419 * by the front-end) to handle.
4420 * In addition we must handle signed and unsigned, which
4421 * result in 6 final different cases -- VR */
4425 size = AOP_SIZE(result) - 1;
4427 /* signed or unsigned */
4428 if (SPEC_USIGN(opetype)) {
4429 pCodeOp *pct1, /* count */
4432 symbol *label1, *label2, *label3;;
4435 /* unsigned is easy */
4437 pct1 = pic16_popGetTempReg(1);
4438 pct2 = pic16_popGetTempReg(1);
4439 pct3 = pic16_popGetTempReg(1);
4441 label1 = newiTempLabel(NULL);
4442 label2 = newiTempLabel(NULL);
4443 label3 = newiTempLabel(NULL);
4445 /* the following algorithm is extracted from divuint.c */
4447 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4448 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4450 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4452 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4454 pic16_emitpLabel(label1->key);
4457 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4461 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4465 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4467 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4468 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4470 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4471 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4472 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4474 pic16_emitpLabel( label3->key );
4475 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4476 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4480 pic16_emitpLabel(label2->key);
4481 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4482 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4483 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4485 /* result is in wreg */
4486 if(AOP_TYPE(result) != AOP_ACC)
4487 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4489 pic16_popReleaseTempReg( pct3, 1);
4490 pic16_popReleaseTempReg( pct2, 1);
4491 pic16_popReleaseTempReg( pct1, 1);
4496 /* signed is a little bit more difficult */
4498 /* save the signs of the operands */
4499 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4501 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4502 pic16_emitcode("push","acc"); /* save it on the stack */
4504 /* now sign adjust for both left & right */
4505 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4507 lbl = newiTempLabel(NULL);
4508 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4509 pic16_emitcode("cpl","a");
4510 pic16_emitcode("inc","a");
4511 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4512 pic16_emitcode("mov","b,a");
4514 /* sign adjust left side */
4515 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4518 lbl = newiTempLabel(NULL);
4519 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4520 pic16_emitcode("cpl","a");
4521 pic16_emitcode("inc","a");
4522 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4524 /* now the division */
4525 pic16_emitcode("div","ab");
4526 /* we are interested in the lower order
4528 pic16_emitcode("mov","b,a");
4529 lbl = newiTempLabel(NULL);
4530 pic16_emitcode("pop","acc");
4531 /* if there was an over flow we don't
4532 adjust the sign of the result */
4533 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4534 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4536 pic16_emitcode("clr","a");
4537 pic16_emitcode("subb","a,b");
4538 pic16_emitcode("mov","b,a");
4539 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4541 /* now we are done */
4542 pic16_aopPut(AOP(result),"b",0);
4544 pic16_emitcode("mov","c,b.7");
4545 pic16_emitcode("subb","a,acc");
4548 pic16_aopPut(AOP(result),"a",offset++);
4553 /*-----------------------------------------------------------------*/
4554 /* genDiv - generates code for division */
4555 /*-----------------------------------------------------------------*/
4556 static void genDiv (iCode *ic)
4558 operand *left = IC_LEFT(ic);
4559 operand *right = IC_RIGHT(ic);
4560 operand *result= IC_RESULT(ic);
4562 int leftVal = 0, rightVal = 0;
4564 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4567 /* Division is a very lengthy algorithm, so it is better
4568 * to call support routines than inlining algorithm.
4569 * Division functions written here just in case someone
4570 * wants to inline and not use the support libraries -- VR */
4574 /* assign the amsops */
4575 pic16_aopOp (left,ic,FALSE);
4576 pic16_aopOp (right,ic,FALSE);
4577 pic16_aopOp (result,ic,TRUE);
4581 else if (ic->op == '%')
4584 assert( !"invalid operation requested in genDivMod" );
4586 /* get literal values */
4587 if (IS_VALOP(left)) {
4588 leftVal = (int)floatFromVal( OP_VALUE(left) );
4589 assert( leftVal >= -128 && leftVal < 256 );
4590 if (leftVal < 0) { signedLits++; }
4592 if (IS_VALOP(right)) {
4593 rightVal = (int)floatFromVal( OP_VALUE(right) );
4594 assert( rightVal >= -128 && rightVal < 256 );
4595 if (rightVal < 0) { signedLits++; }
4598 /* We should only come here to convert all
4599 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4600 * with exactly one operand being s8_t into
4601 * u8_t x u8_t -> u8_t. All other cases should have been
4602 * turned into calls to support routines beforehand... */
4603 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4604 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4606 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4607 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4609 /* Both operands are signed or negative, use _divschar
4610 * instead of _divuchar */
4611 pushaop(AOP(right), 0);
4612 pushaop(AOP(left), 0);
4614 /* call _divschar */
4615 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4619 sym = newSymbol( functions[op][0], 0 );
4621 strcpy(sym->rname, functions[op][0]);
4622 checkAddSym(&externs, sym);
4626 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4627 if (AOP_SIZE(result) > 1)
4629 pic16_emitpcode(POC_MOVFF,
4630 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4631 pic16_popGet(AOP(result), 1)));
4633 pic16_addSign(result, 2, 1);
4636 /* clean up stack */
4637 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4638 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4643 /* push right operand */
4644 if (IS_VALOP(right)) {
4646 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4649 pushaop(AOP(right), 0);
4651 } else if (!IS_UNSIGNED(operandType(right))) {
4652 pic16_mov2w(AOP(right), 0);
4653 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4654 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4655 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4658 pushaop(AOP(right), 0);
4661 /* push left operand */
4662 if (IS_VALOP(left)) {
4664 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4667 pushaop(AOP(left), 0);
4669 } else if (!IS_UNSIGNED(operandType(left))) {
4670 pic16_mov2w(AOP(left),0);
4671 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4672 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4673 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4676 pushaop(AOP(left), 0);
4679 /* call _divuchar */
4680 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4684 sym = newSymbol( functions[op][1], 0 );
4686 strcpy(sym->rname, functions[op][1]);
4687 checkAddSym(&externs, sym);
4690 /* Revert negation(s) from above.
4691 * This is inefficient: if both operands are negative, this
4692 * should not touch WREG. However, determining that exactly
4693 * one operand was negated costs at least 3 instructions,
4694 * so there is nothing to be gained here, is there?
4696 * I negate WREG because either operand might share registers with
4697 * result, so assigning first might destroy an operand. */
4699 /* For the modulus operator, (a/b)*b == a shall hold.
4700 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4701 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4702 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4703 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4704 * Only invert the result if the left operand is negative (sigh).
4706 if (AOP_SIZE(result) <= 1 || !negated)
4710 if (IS_VALOP(right)) {
4712 /* we negated this operand above */
4713 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4715 } else if (!IS_UNSIGNED(operandType(right))) {
4716 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4717 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4721 if (IS_VALOP(left)) {
4723 /* we negated this operand above */
4724 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4726 } else if (!IS_UNSIGNED(operandType(left))) {
4727 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4728 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4731 /* Move result to destination. */
4732 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4734 /* Zero-extend: no operand was signed (or result is just a byte). */
4735 pic16_addSign(result, 1, 0);
4737 assert( AOP_SIZE(result) > 1 );
4738 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4741 if (IS_VALOP(right)) {
4743 /* we negated this operand above */
4744 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4746 } else if (!IS_UNSIGNED(operandType(right))) {
4747 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4748 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4752 if (IS_VALOP(left)) {
4754 /* we negated this operand above */
4755 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4757 } else if (!IS_UNSIGNED(operandType(left))) {
4758 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4759 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4762 /* Move result to destination. */
4763 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4765 /* Negate result if required. */
4766 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4767 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4770 pic16_addSign(result, 2, 1);
4773 /* clean up stack */
4774 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4775 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4780 /* special cases first */
4782 if (AOP_TYPE(left) == AOP_CRY &&
4783 AOP_TYPE(right)== AOP_CRY) {
4784 genDivbits(left,right,result);
4788 /* if both are of size == 1 */
4789 if (AOP_SIZE(left) == 1 &&
4790 AOP_SIZE(right) == 1 ) {
4791 genDivOneByte(left,right,result);
4796 /* should have been converted to function call */
4799 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4800 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4801 pic16_freeAsmop(result,NULL,ic,TRUE);
4805 /*-----------------------------------------------------------------*/
4806 /* genModbits :- modulus of bits */
4807 /*-----------------------------------------------------------------*/
4808 static void genModbits (operand *left,
4816 werror(W_POSSBUG2, __FILE__, __LINE__);
4817 /* the result must be bit */
4818 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4819 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4823 pic16_emitcode("div","ab");
4824 pic16_emitcode("mov","a,b");
4825 pic16_emitcode("rrc","a");
4826 pic16_aopPut(AOP(result),"c",0);
4829 /*-----------------------------------------------------------------*/
4830 /* genModOneByte : 8 bit modulus */
4831 /*-----------------------------------------------------------------*/
4832 static void genModOneByte (operand *left,
4836 sym_link *opetype = operandType(result);
4841 werror(W_POSSBUG2, __FILE__, __LINE__);
4843 /* signed or unsigned */
4844 if (SPEC_USIGN(opetype)) {
4845 /* unsigned is easy */
4846 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4847 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4849 pic16_emitcode("div","ab");
4850 pic16_aopPut(AOP(result),"b",0);
4854 /* signed is a little bit more difficult */
4856 /* save the signs of the operands */
4857 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4860 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4861 pic16_emitcode("push","acc"); /* save it on the stack */
4863 /* now sign adjust for both left & right */
4864 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4867 lbl = newiTempLabel(NULL);
4868 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4869 pic16_emitcode("cpl","a");
4870 pic16_emitcode("inc","a");
4871 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4872 pic16_emitcode("mov","b,a");
4874 /* sign adjust left side */
4875 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4878 lbl = newiTempLabel(NULL);
4879 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4880 pic16_emitcode("cpl","a");
4881 pic16_emitcode("inc","a");
4882 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4884 /* now the multiplication */
4885 pic16_emitcode("div","ab");
4886 /* we are interested in the lower order
4888 lbl = newiTempLabel(NULL);
4889 pic16_emitcode("pop","acc");
4890 /* if there was an over flow we don't
4891 adjust the sign of the result */
4892 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4893 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4895 pic16_emitcode("clr","a");
4896 pic16_emitcode("subb","a,b");
4897 pic16_emitcode("mov","b,a");
4898 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4900 /* now we are done */
4901 pic16_aopPut(AOP(result),"b",0);
4906 /*-----------------------------------------------------------------*/
4907 /* genMod - generates code for division */
4908 /*-----------------------------------------------------------------*/
4909 static void genMod (iCode *ic)
4911 /* Task deferred to genDiv */
4914 operand *left = IC_LEFT(ic);
4915 operand *right = IC_RIGHT(ic);
4916 operand *result= IC_RESULT(ic);
4920 /* assign the amsops */
4921 pic16_aopOp (left,ic,FALSE);
4922 pic16_aopOp (right,ic,FALSE);
4923 pic16_aopOp (result,ic,TRUE);
4925 /* special cases first */
4927 if (AOP_TYPE(left) == AOP_CRY &&
4928 AOP_TYPE(right)== AOP_CRY) {
4929 genModbits(left,right,result);
4933 /* if both are of size == 1 */
4934 if (AOP_SIZE(left) == 1 &&
4935 AOP_SIZE(right) == 1 ) {
4936 genModOneByte(left,right,result);
4940 /* should have been converted to function call */
4944 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4945 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4946 pic16_freeAsmop(result,NULL,ic,TRUE);
4950 /*-----------------------------------------------------------------*/
4951 /* genIfxJump :- will create a jump depending on the ifx */
4952 /*-----------------------------------------------------------------*/
4954 note: May need to add parameter to indicate when a variable is in bit space.
4956 static void genIfxJump (iCode *ic, char *jval)
4960 /* if true label then we jump if condition
4962 if ( IC_TRUE(ic) ) {
4964 if(strcmp(jval,"a") == 0)
4966 else if (strcmp(jval,"c") == 0)
4969 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4970 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4973 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4974 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4978 /* false label is present */
4979 if(strcmp(jval,"a") == 0)
4981 else if (strcmp(jval,"c") == 0)
4984 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4985 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4988 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4989 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4994 /* mark the icode as generated */
4998 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5002 /* if true label then we jump if condition
5004 if ( IC_TRUE(ic) ) {
5005 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5006 pic16_emitpcode(POC_BTFSC, jop);
5008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5009 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5012 /* false label is present */
5013 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5014 pic16_emitpcode(POC_BTFSS, jop);
5016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5017 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5021 /* mark the icode as generated */
5028 /*-----------------------------------------------------------------*/
5030 /*-----------------------------------------------------------------*/
5031 static void genSkip(iCode *ifx,int status_bit)
5033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5037 if ( IC_TRUE(ifx) ) {
5038 switch(status_bit) {
5053 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5054 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5058 switch(status_bit) {
5072 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5073 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5080 /*-----------------------------------------------------------------*/
5082 /*-----------------------------------------------------------------*/
5083 static void genSkipc(resolvedIfx *rifx)
5085 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5095 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5096 rifx->generated = 1;
5099 #if !(USE_SIMPLE_GENCMP)
5100 /*-----------------------------------------------------------------*/
5102 /*-----------------------------------------------------------------*/
5103 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5105 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5110 if( (rifx->condition ^ invert_condition) & 1)
5115 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5116 rifx->generated = 1;
5121 /*-----------------------------------------------------------------*/
5123 /*-----------------------------------------------------------------*/
5124 static void genSkipz(iCode *ifx, int condition)
5135 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5137 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5140 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5142 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5147 #if !(USE_SIMPLE_GENCMP)
5148 /*-----------------------------------------------------------------*/
5150 /*-----------------------------------------------------------------*/
5151 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5157 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5159 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5162 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5163 rifx->generated = 1;
5168 /*-----------------------------------------------------------------*/
5169 /* genChkZeroes :- greater or less than comparison */
5170 /* For each byte in a literal that is zero, inclusive or the */
5171 /* the corresponding byte in the operand with W */
5172 /* returns true if any of the bytes are zero */
5173 /*-----------------------------------------------------------------*/
5174 static int genChkZeroes(operand *op, int lit, int size)
5181 i = (lit >> (size*8)) & 0xff;
5185 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5187 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5197 /*-----------------------------------------------------------------*/
5198 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5199 /* aop (if it's NOT a literal) or from lit (if */
5200 /* aop is a literal) */
5201 /*-----------------------------------------------------------------*/
5202 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5203 if (aop->type == AOP_LIT) {
5204 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5206 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5210 /*-----------------------------------------------------------------*/
5211 /* genCmp :- greater or less than comparison */
5212 /*-----------------------------------------------------------------*/
5214 #if USE_SIMPLE_GENCMP /* { */
5216 /* genCmp performs a left < right comparison, stores
5217 * the outcome in result (if != NULL) and generates
5218 * control flow code for the ifx (if != NULL).
5220 * This version leaves in sequences like
5221 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5222 * which should be optmized by the peephole
5223 * optimizer - RN 2005-01-01 */
5224 static void genCmp (operand *left,operand *right,
5225 operand *result, iCode *ifx, int sign)
5238 assert (left && right);
5239 assert (AOP_SIZE(left) == AOP_SIZE(right));
5241 size = AOP_SIZE(right) - 1;
5242 mask = (0x100UL << (size*8)) - 1;
5243 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5248 resolveIfx (&rIfx, ifx);
5250 /* handle for special cases */
5251 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5254 /**********************************************************************
5255 * handle bits - bit compares are promoted to int compares seemingly! *
5256 **********************************************************************/
5258 // THIS IS COMPLETELY UNTESTED!
5259 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5260 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5261 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5262 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5265 // 1 < {0,1} is false --> clear C by skipping the next instruction
5266 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5267 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5268 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5269 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5270 emitCLRC; // only skipped for left=0 && right=1
5272 goto correct_result_in_carry;
5276 /*************************************************
5277 * make sure that left is register (or the like) *
5278 *************************************************/
5279 if (!isAOP_REGlike(left)) {
5280 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5281 assert (isAOP_LIT(left));
5282 assert (isAOP_REGlike(right));
5283 // swap left and right
5284 // left < right <==> right > left <==> (right >= left + 1)
5285 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5287 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5288 // MAXVALUE < right? always false
5289 if (performedLt) emitCLRC; else emitSETC;
5290 goto correct_result_in_carry;
5293 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5294 // that's why we handled it above.
5301 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5302 } else if (isAOP_LIT(right)) {
5303 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5306 assert (isAOP_REGlike(left)); // left must be register or the like
5307 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5309 /*************************************************
5310 * special cases go here *
5311 *************************************************/
5313 if (isAOP_LIT(right)) {
5315 // unsigned comparison to a literal
5316 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5318 // unsigned left < 0? always false
5319 if (performedLt) emitCLRC; else emitSETC;
5320 goto correct_result_in_carry;
5323 // signed comparison to a literal
5324 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5325 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5326 // signed left < 0x80000000? always false
5327 if (performedLt) emitCLRC; else emitSETC;
5328 goto correct_result_in_carry;
5329 } else if (lit == 0) {
5330 // compare left < 0; set CARRY if SIGNBIT(left) is set
5331 if (performedLt) emitSETC; else emitCLRC;
5332 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5333 if (performedLt) emitCLRC; else emitSETC;
5334 goto correct_result_in_carry;
5337 } // right is literal
5339 /*************************************************
5340 * perform a general case comparison *
5341 * make sure we get CARRY==1 <==> left >= right *
5342 *************************************************/
5343 // compare most significant bytes
5344 //DEBUGpc ("comparing bytes at offset %d", size);
5346 // unsigned comparison
5347 mov2w_regOrLit (AOP(right), lit, size);
5348 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5350 // signed comparison
5351 // (add 2^n to both operands then perform an unsigned comparison)
5352 if (isAOP_LIT(right)) {
5353 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5354 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5356 if (litbyte == 0x80) {
5357 // left >= 0x80 -- always true, but more bytes to come
5358 pic16_mov2w (AOP(left), size);
5359 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5362 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5363 pic16_mov2w (AOP(left), size);
5364 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5365 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5368 /* using PRODL as a temporary register here */
5369 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5370 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5371 pic16_mov2w (AOP(left), size);
5372 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5373 pic16_emitpcode (POC_MOVWF, pctemp);
5374 pic16_mov2w (AOP(right), size);
5375 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5376 pic16_emitpcode (POC_SUBFW, pctemp);
5377 //pic16_popReleaseTempReg(pctemp, 1);
5381 // compare remaining bytes (treat as unsigned case from above)
5382 templbl = newiTempLabel ( NULL );
5385 //DEBUGpc ("comparing bytes at offset %d", offs);
5386 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5387 mov2w_regOrLit (AOP(right), lit, offs);
5388 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5390 pic16_emitpLabel (templbl->key);
5391 goto result_in_carry;
5395 /****************************************************
5396 * now CARRY contains the result of the comparison: *
5397 * SUBWF sets CARRY iff *
5398 * F-W >= 0 <==> F >= W <==> !(F < W) *
5399 * (F=left, W=right) *
5400 ****************************************************/
5403 if (result && AOP_TYPE(result) != AOP_CRY) {
5404 // value will be stored
5407 // value wil only be used in the following genSkipc()
5408 rIfx.condition ^= 1;
5412 correct_result_in_carry:
5414 // assign result to variable (if neccessary)
5415 if (result && AOP_TYPE(result) != AOP_CRY) {
5416 //DEBUGpc ("assign result");
5417 size = AOP_SIZE(result);
5419 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5421 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5424 // perform conditional jump
5426 //DEBUGpc ("generate control flow");
5435 static void genCmp (operand *left,operand *right,
5436 operand *result, iCode *ifx, int sign)
5438 int size; //, offset = 0 ;
5439 unsigned long lit = 0L,i = 0;
5440 resolvedIfx rFalseIfx;
5441 // resolvedIfx rTrueIfx;
5443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5446 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5447 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5453 resolveIfx(&rFalseIfx,ifx);
5454 truelbl = newiTempLabel(NULL);
5455 size = max(AOP_SIZE(left),AOP_SIZE(right));
5457 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5461 /* if literal is on the right then swap with left */
5462 if ((AOP_TYPE(right) == AOP_LIT)) {
5463 operand *tmp = right ;
5464 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5465 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5468 lit = (lit - 1) & mask;
5471 rFalseIfx.condition ^= 1;
5474 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5475 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5479 //if(IC_TRUE(ifx) == NULL)
5480 /* if left & right are bit variables */
5481 if (AOP_TYPE(left) == AOP_CRY &&
5482 AOP_TYPE(right) == AOP_CRY ) {
5483 assert (0 && "bit variables used in genCmp");
5484 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5485 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5487 /* subtract right from left if at the
5488 end the carry flag is set then we know that
5489 left is greater than right */
5491 symbol *lbl = newiTempLabel(NULL);
5494 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5495 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5499 if(AOP_TYPE(right) == AOP_LIT) {
5501 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5503 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5510 genSkipCond(&rFalseIfx,left,size-1,7);
5512 /* no need to compare to 0...*/
5513 /* NOTE: this is a de-generate compare that most certainly
5514 * creates some dead code. */
5515 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5517 if(ifx) ifx->generated = 1;
5524 //i = (lit >> (size*8)) & 0xff;
5525 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5527 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5529 i = ((0-lit) & 0xff);
5532 /* lit is 0x7f, all signed chars are less than
5533 * this except for 0x7f itself */
5534 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5535 genSkipz2(&rFalseIfx,0);
5537 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5538 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5539 genSkipc(&rFalseIfx);
5544 genSkipz2(&rFalseIfx,1);
5546 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5547 genSkipc(&rFalseIfx);
5551 if(ifx) ifx->generated = 1;
5555 /* chars are out of the way. now do ints and longs */
5558 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5565 genSkipCond(&rFalseIfx,left,size,7);
5566 if(ifx) ifx->generated = 1;
5571 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5573 //rFalseIfx.condition ^= 1;
5574 //genSkipCond(&rFalseIfx,left,size,7);
5575 //rFalseIfx.condition ^= 1;
5577 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5578 if(rFalseIfx.condition)
5579 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5581 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5583 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5584 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5585 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5588 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5590 if(rFalseIfx.condition) {
5592 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5598 genSkipc(&rFalseIfx);
5599 pic16_emitpLabel(truelbl->key);
5600 if(ifx) ifx->generated = 1;
5607 if( (lit & 0xff) == 0) {
5608 /* lower byte is zero */
5609 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5610 i = ((lit >> 8) & 0xff) ^0x80;
5611 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5612 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5613 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5614 genSkipc(&rFalseIfx);
5617 if(ifx) ifx->generated = 1;
5622 /* Special cases for signed longs */
5623 if( (lit & 0xffffff) == 0) {
5624 /* lower byte is zero */
5625 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5626 i = ((lit >> 8*3) & 0xff) ^0x80;
5627 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5628 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5629 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5630 genSkipc(&rFalseIfx);
5633 if(ifx) ifx->generated = 1;
5641 if(lit & (0x80 << (size*8))) {
5642 /* lit is negative */
5643 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5645 //genSkipCond(&rFalseIfx,left,size,7);
5647 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5649 if(rFalseIfx.condition)
5650 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5652 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5656 /* lit is positive */
5657 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5658 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5659 if(rFalseIfx.condition)
5660 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5662 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5667 This works, but is only good for ints.
5668 It also requires a "known zero" register.
5669 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5670 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5671 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5672 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5673 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5674 genSkipc(&rFalseIfx);
5676 pic16_emitpLabel(truelbl->key);
5677 if(ifx) ifx->generated = 1;
5681 /* There are no more special cases, so perform a general compare */
5683 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5684 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5688 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5690 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5692 //rFalseIfx.condition ^= 1;
5693 genSkipc(&rFalseIfx);
5695 pic16_emitpLabel(truelbl->key);
5697 if(ifx) ifx->generated = 1;
5704 /* sign is out of the way. So now do an unsigned compare */
5705 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5708 /* General case - compare to an unsigned literal on the right.*/
5710 i = (lit >> (size*8)) & 0xff;
5711 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5712 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5714 i = (lit >> (size*8)) & 0xff;
5717 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5719 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5721 /* this byte of the lit is zero,
5722 *if it's not the last then OR in the variable */
5724 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5729 pic16_emitpLabel(lbl->key);
5730 // pic16_emitpLabel(truelbl->key);
5731 //if(emitFinalCheck)
5732 genSkipc(&rFalseIfx);
5734 pic16_emitpLabel(truelbl->key);
5736 if(ifx) ifx->generated = 1;
5743 if(AOP_TYPE(left) == AOP_LIT) {
5744 //symbol *lbl = newiTempLabel(NULL);
5746 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5749 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5752 if((lit == 0) && (sign == 0)){
5755 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5757 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5759 genSkipz2(&rFalseIfx,0);
5760 if(ifx) ifx->generated = 1;
5767 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5768 /* degenerate compare can never be true */
5769 if(rFalseIfx.condition == 0)
5770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5772 if(ifx) ifx->generated = 1;
5777 /* signed comparisons to a literal byte */
5779 int lp1 = (lit+1) & 0xff;
5781 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5784 rFalseIfx.condition ^= 1;
5785 genSkipCond(&rFalseIfx,right,0,7);
5788 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5789 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5790 genSkipz2(&rFalseIfx,1);
5793 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5794 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5795 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5796 rFalseIfx.condition ^= 1;
5797 genSkipc(&rFalseIfx);
5801 /* unsigned comparisons to a literal byte */
5803 switch(lit & 0xff ) {
5805 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5806 genSkipz2(&rFalseIfx,0);
5809 rFalseIfx.condition ^= 1;
5810 genSkipCond(&rFalseIfx,right,0,7);
5814 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5815 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5816 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5817 rFalseIfx.condition ^= 1;
5818 if (AOP_TYPE(result) == AOP_CRY)
5819 genSkipc(&rFalseIfx);
5821 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5822 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5828 if(ifx) ifx->generated = 1;
5829 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5835 /* Size is greater than 1 */
5843 /* this means lit = 0xffffffff, or -1 */
5846 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5847 rFalseIfx.condition ^= 1;
5848 genSkipCond(&rFalseIfx,right,size,7);
5849 if(ifx) ifx->generated = 1;
5851 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5860 if(rFalseIfx.condition) {
5861 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5862 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5865 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5867 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5871 if(rFalseIfx.condition) {
5872 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5873 pic16_emitpLabel(truelbl->key);
5875 rFalseIfx.condition ^= 1;
5876 genSkipCond(&rFalseIfx,right,s,7);
5879 if(ifx) ifx->generated = 1;
5881 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5887 if((size == 1) && (0 == (lp1&0xff))) {
5888 /* lower byte of signed word is zero */
5889 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5890 i = ((lp1 >> 8) & 0xff) ^0x80;
5891 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5892 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5893 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5895 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5897 if(ifx) ifx->generated = 1;
5900 rFalseIfx.condition ^= 1;
5901 genSkipc(&rFalseIfx);
5902 if(ifx) ifx->generated = 1;
5908 if(lit & (0x80 << (size*8))) {
5909 /* Lit is less than zero */
5910 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5911 //rFalseIfx.condition ^= 1;
5912 //genSkipCond(&rFalseIfx,left,size,7);
5913 //rFalseIfx.condition ^= 1;
5914 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5915 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5917 if(rFalseIfx.condition)
5918 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5920 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5924 /* Lit is greater than or equal to zero */
5925 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5926 //rFalseIfx.condition ^= 1;
5927 //genSkipCond(&rFalseIfx,right,size,7);
5928 //rFalseIfx.condition ^= 1;
5930 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5931 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5933 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5934 if(rFalseIfx.condition)
5935 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5937 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5941 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5942 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5946 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5948 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5950 rFalseIfx.condition ^= 1;
5951 //rFalseIfx.condition = 1;
5952 genSkipc(&rFalseIfx);
5954 pic16_emitpLabel(truelbl->key);
5956 if(ifx) ifx->generated = 1;
5959 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5966 /* compare word or long to an unsigned literal on the right.*/
5971 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5974 break; /* handled above */
5977 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5979 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5980 genSkipz2(&rFalseIfx,0);
5984 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5986 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5989 if(rFalseIfx.condition)
5990 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5992 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5995 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5996 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5998 rFalseIfx.condition ^= 1;
5999 genSkipc(&rFalseIfx);
6002 pic16_emitpLabel(truelbl->key);
6004 if(ifx) ifx->generated = 1;
6006 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6014 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6015 i = (lit >> (size*8)) & 0xff;
6017 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6018 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6021 i = (lit >> (size*8)) & 0xff;
6024 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6026 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6028 /* this byte of the lit is zero,
6029 * if it's not the last then OR in the variable */
6031 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6036 pic16_emitpLabel(lbl->key);
6038 rFalseIfx.condition ^= 1;
6040 genSkipc(&rFalseIfx);
6044 pic16_emitpLabel(truelbl->key);
6045 if(ifx) ifx->generated = 1;
6047 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6053 /* Compare two variables */
6055 DEBUGpic16_emitcode(";sign","%d",sign);
6059 /* Sigh. thus sucks... */
6063 pctemp = pic16_popGetTempReg(1);
6064 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6065 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6067 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6068 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6069 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6070 pic16_popReleaseTempReg(pctemp, 1);
6072 /* Signed char comparison */
6073 /* Special thanks to Nikolai Golovchenko for this snippet */
6074 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6075 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6076 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6077 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6078 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6079 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6082 genSkipc(&rFalseIfx);
6084 if(ifx) ifx->generated = 1;
6086 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6094 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6095 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6099 /* The rest of the bytes of a multi-byte compare */
6103 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6106 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6107 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6112 pic16_emitpLabel(lbl->key);
6114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6115 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6116 (AOP_TYPE(result) == AOP_REG)) {
6117 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6118 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6120 genSkipc(&rFalseIfx);
6122 //genSkipc(&rFalseIfx);
6123 if(ifx) ifx->generated = 1;
6126 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6134 if ((AOP_TYPE(result) != AOP_CRY)
6135 && AOP_SIZE(result)) {
6136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6138 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6140 pic16_outBitC(result);
6142 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6143 /* if the result is used in the next
6144 ifx conditional branch then generate
6145 code a little differently */
6147 genIfxJump (ifx,"c");
6149 pic16_outBitC(result);
6150 /* leave the result in acc */
6155 #elif 0 /* VR version of genCmp() */ /* } else { */
6157 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6158 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6159 operand *result, int offset, int invert_op)
6163 /* check condition, > or < ?? */
6164 if(rIfx->condition != 0)invert_op ^= 1;
6166 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6168 if(!ifx)invert_op ^= 1;
6170 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6171 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6174 if(!invert_op)return POC_CPFSGT;
6175 else return POC_CPFSLT;
6178 static int compareAopfirstpass=1;
6180 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6181 operand *oper, int offset, operand *result,
6182 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6188 /* invert if there is a result to be loaded, in order to fit,
6189 * SETC/CLRC sequence */
6190 if(AOP_SIZE(result))invert_op ^= 1;
6192 // if(sign && !offset)invert_op ^= 1;
6194 // if(sign)invert_op ^= 1;
6196 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6198 if(AOP_SIZE(result) && compareAopfirstpass) {
6201 pic16_emitpcode(POC_SETF, pcop2);
6206 pic16_emitpcode(POC_CLRF, pcop2);
6212 compareAopfirstpass = 0;
6214 /* there is a bug when comparing operands with size > 1,
6215 * because higher bytes can be equal and test should be performed
6216 * to the next lower byte, current algorithm, considers operands
6217 * inequal in these cases! -- VR 20041107 */
6221 pic16_emitpcode(op, pcop);
6223 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6226 if((!sign || !offset) && AOP_SIZE(result)) {
6229 pic16_emitpcode(POC_CLRF, pcop2);
6234 pic16_emitpcode(POC_SETF, pcop2);
6239 /* don't emit final branch (offset == 0) */
6243 pic16_emitpcode(POC_RRCF, pcop2);
6245 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6248 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6249 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6250 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6252 truelbl = newiTempLabel( NULL );
6253 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6254 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6255 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6257 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6258 pic16_emitpLabel(truelbl->key);
6260 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6265 static void genCmp (operand *left, operand *right,
6266 operand *result, iCode *ifx, int sign)
6270 resolvedIfx rFalseIfx;
6271 symbol *falselbl, *tlbl;
6275 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6277 resolveIfx(&rFalseIfx, ifx);
6278 size = max(AOP_SIZE(left), AOP_SIZE(right));
6280 /* if left & right are bit variables */
6281 if(AOP_TYPE(left) == AOP_CRY
6282 && AOP_TYPE(right) == AOP_CRY ) {
6284 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6285 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6287 werror(W_POSSBUG2, __FILE__, __LINE__);
6291 /* if literal is on the right then swap with left */
6292 if((AOP_TYPE(right) == AOP_LIT)) {
6293 operand *tmp = right ;
6294 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6296 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6298 // lit = (lit - 1) & mask;
6301 rFalseIfx.condition ^= 1; /* reverse compare */
6303 if ((AOP_TYPE(left) == AOP_LIT)) {
6304 /* float compares are handled by support functions */
6305 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6308 /* actual comparing algorithm */
6309 // size = AOP_SIZE( right );
6311 falselbl = newiTempLabel( NULL );
6312 if(AOP_TYPE(left) == AOP_LIT) {
6313 /* compare to literal */
6314 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6317 pCodeOp *pct, *pct2;
6320 /* signed compare */
6321 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6323 /* using PRODL:PRODH as a temporary register here */
6324 pct = pic16_popCopyReg(&pic16_pc_prodl);
6325 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6326 tlbl = newiTempLabel( NULL );
6328 /* first compare signs:
6329 * a. if both are positive, compare just like unsigned
6330 * b. if both are negative, invert cmpop, compare just like unsigned
6331 * c. if different signs, determine the result directly */
6337 tlbl1 = newiTempLabel( NULL );
6338 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6342 /* literal is zero or positive:
6343 * a. if carry is zero, too, continue compare,
6344 * b. if carry is set, then continue depending on cmpop ^ condition:
6345 * 1. '<' return false (literal < variable),
6346 * 2. '>' return true (literal > variable) */
6347 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6348 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6351 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6352 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6356 /* literal is negative:
6357 * a. if carry is set, too, continue compare,
6358 * b. if carry is zero, then continue depending on cmpop ^ condition:
6359 * 1. '<' return true (literal < variable),
6360 * 2. '>' return false (literal > variable) */
6361 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6362 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6364 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6365 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6370 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6372 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6373 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6378 pic16_emitpLabel( tlbl1->key );
6381 compareAopfirstpass=1;
6382 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6383 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6384 // pic16_emitpcode(POC_MOVWF, pct);
6386 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6387 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6388 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6389 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6393 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6394 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6395 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6396 // pic16_emitpcode(POC_MOVWF, pct);
6398 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6399 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6400 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6401 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6402 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6405 if(ifx)ifx->generated = 1;
6407 if(AOP_SIZE(result)) {
6408 pic16_emitpLabel(tlbl->key);
6409 pic16_emitpLabel(falselbl->key);
6410 pic16_outBitOp( result, pct2 );
6412 pic16_emitpLabel(tlbl->key);
6416 /* unsigned compare */
6417 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6419 compareAopfirstpass=1;
6422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6423 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6426 if(ifx)ifx->generated = 1;
6428 if(AOP_SIZE(result)) {
6429 pic16_emitpLabel(falselbl->key);
6430 pic16_outBitC( result );
6435 /* compare registers */
6436 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6440 pCodeOp *pct, *pct2;
6442 /* signed compare */
6443 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6445 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6446 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6447 tlbl = newiTempLabel( NULL );
6449 compareAopfirstpass=1;
6452 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6453 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6454 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6455 pic16_emitpcode(POC_MOVWF, pct);
6457 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6458 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6459 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6461 /* WREG already holds left + 0x80 */
6462 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6465 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6466 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6467 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6468 pic16_emitpcode(POC_MOVWF, pct);
6470 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6471 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6472 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6474 /* WREG already holds left + 0x80 */
6475 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6476 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6479 if(ifx)ifx->generated = 1;
6481 if(AOP_SIZE(result)) {
6482 pic16_emitpLabel(tlbl->key);
6483 pic16_emitpLabel(falselbl->key);
6484 pic16_outBitOp( result, pct2 );
6486 pic16_emitpLabel(tlbl->key);
6490 /* unsigned compare */
6491 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6493 compareAopfirstpass=1;
6496 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6497 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6501 if(ifx)ifx->generated = 1;
6502 if(AOP_SIZE(result)) {
6504 pic16_emitpLabel(falselbl->key);
6505 pic16_outBitC( result );
6516 /*-----------------------------------------------------------------*/
6517 /* genCmpGt :- greater than comparison */
6518 /*-----------------------------------------------------------------*/
6519 static void genCmpGt (iCode *ic, iCode *ifx)
6521 operand *left, *right, *result;
6522 sym_link *letype , *retype;
6528 right= IC_RIGHT(ic);
6529 result = IC_RESULT(ic);
6531 letype = getSpec(operandType(left));
6532 retype =getSpec(operandType(right));
6533 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6534 /* assign the amsops */
6535 pic16_aopOp (left,ic,FALSE);
6536 pic16_aopOp (right,ic,FALSE);
6537 pic16_aopOp (result,ic,TRUE);
6539 genCmp(right, left, result, ifx, sign);
6541 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6542 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6543 pic16_freeAsmop(result,NULL,ic,TRUE);
6546 /*-----------------------------------------------------------------*/
6547 /* genCmpLt - less than comparisons */
6548 /*-----------------------------------------------------------------*/
6549 static void genCmpLt (iCode *ic, iCode *ifx)
6551 operand *left, *right, *result;
6552 sym_link *letype , *retype;
6558 right= IC_RIGHT(ic);
6559 result = IC_RESULT(ic);
6561 letype = getSpec(operandType(left));
6562 retype =getSpec(operandType(right));
6563 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6565 /* assign the amsops */
6566 pic16_aopOp (left,ic,FALSE);
6567 pic16_aopOp (right,ic,FALSE);
6568 pic16_aopOp (result,ic,TRUE);
6570 genCmp(left, right, result, ifx, sign);
6572 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6573 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6574 pic16_freeAsmop(result,NULL,ic,TRUE);
6579 // FIXME reenable literal optimisation when the pic16 port is stable
6581 /*-----------------------------------------------------------------*/
6582 /* genc16bit2lit - compare a 16 bit value to a literal */
6583 /*-----------------------------------------------------------------*/
6584 static void genc16bit2lit(operand *op, int lit, int offset)
6588 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6589 if( (lit&0xff) == 0)
6594 switch( BYTEofLONG(lit,i)) {
6596 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6599 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6602 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6605 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6606 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6611 switch( BYTEofLONG(lit,i)) {
6613 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6617 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6621 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6624 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6626 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6635 /*-----------------------------------------------------------------*/
6636 /* gencjneshort - compare and jump if not equal */
6637 /*-----------------------------------------------------------------*/
6638 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6640 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6642 int res_offset = 0; /* the result may be a different size then left or right */
6643 int res_size = AOP_SIZE(result);
6645 symbol *lbl, *lbl_done;
6647 unsigned long lit = 0L;
6648 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6651 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6653 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6654 resolveIfx(&rIfx,ifx);
6655 lbl = newiTempLabel(NULL);
6656 lbl_done = newiTempLabel(NULL);
6659 /* if the left side is a literal or
6660 if the right is in a pointer register and left
6662 if ((AOP_TYPE(left) == AOP_LIT) ||
6663 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6668 if(AOP_TYPE(right) == AOP_LIT)
6669 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6671 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6672 preserve_result = 1;
6674 if(result && !preserve_result)
6677 for(i = 0; i < AOP_SIZE(result); i++)
6678 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6682 /* if the right side is a literal then anything goes */
6683 if (AOP_TYPE(right) == AOP_LIT &&
6684 AOP_TYPE(left) != AOP_DIR ) {
6687 genc16bit2lit(left, lit, 0);
6689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6692 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6695 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6696 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6698 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6702 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6704 if(res_offset < res_size-1)
6712 /* if the right side is in a register or in direct space or
6713 if the left is a pointer register & right is not */
6714 else if (AOP_TYPE(right) == AOP_REG ||
6715 AOP_TYPE(right) == AOP_DIR ||
6716 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6717 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6718 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6719 int lbl_key = lbl->key;
6722 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6723 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6725 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6726 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6727 __FUNCTION__,__LINE__);
6731 /* switch(size) { */
6733 /* genc16bit2lit(left, lit, 0); */
6735 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6740 if((AOP_TYPE(left) == AOP_DIR) &&
6741 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6743 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6744 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6746 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6748 switch (lit & 0xff) {
6750 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6753 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6754 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6759 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6760 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6761 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6766 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6767 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6772 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6775 if(AOP_TYPE(result) == AOP_CRY) {
6776 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6781 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6783 /* fix me. probably need to check result size too */
6784 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6789 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6790 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6797 if(res_offset < res_size-1)
6802 } else if(AOP_TYPE(right) == AOP_REG &&
6803 AOP_TYPE(left) != AOP_DIR){
6806 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6807 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6808 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6813 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6815 if(res_offset < res_size-1)
6820 /* right is a pointer reg need both a & b */
6822 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6824 pic16_emitcode("mov","b,%s",l);
6825 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6826 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6831 if(result && preserve_result)
6834 for(i = 0; i < AOP_SIZE(result); i++)
6835 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6838 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6840 if(result && preserve_result)
6841 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6846 pic16_emitpLabel(lbl->key);
6848 if(result && preserve_result)
6851 for(i = 0; i < AOP_SIZE(result); i++)
6852 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6854 pic16_emitpLabel(lbl_done->key);
6857 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6865 /*-----------------------------------------------------------------*/
6866 /* gencjne - compare and jump if not equal */
6867 /*-----------------------------------------------------------------*/
6868 static void gencjne(operand *left, operand *right, iCode *ifx)
6870 symbol *tlbl = newiTempLabel(NULL);
6872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6873 gencjneshort(left, right, lbl);
6875 pic16_emitcode("mov","a,%s",one);
6876 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6877 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6878 pic16_emitcode("clr","a");
6879 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6881 pic16_emitpLabel(lbl->key);
6882 pic16_emitpLabel(tlbl->key);
6888 /*-----------------------------------------------------------------*/
6889 /* is_LitOp - check if operand has to be treated as literal */
6890 /*-----------------------------------------------------------------*/
6891 static bool is_LitOp(operand *op)
6893 return ((AOP_TYPE(op) == AOP_LIT)
6894 || ( (AOP_TYPE(op) == AOP_PCODE)
6895 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6896 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6899 /*-----------------------------------------------------------------*/
6900 /* is_LitAOp - check if operand has to be treated as literal */
6901 /*-----------------------------------------------------------------*/
6902 static bool is_LitAOp(asmop *aop)
6904 return ((aop->type == AOP_LIT)
6905 || ( (aop->type == AOP_PCODE)
6906 && ( (aop->aopu.pcop->type == PO_LITERAL)
6907 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6912 /*-----------------------------------------------------------------*/
6913 /* genCmpEq - generates code for equal to */
6914 /*-----------------------------------------------------------------*/
6915 static void genCmpEq (iCode *ic, iCode *ifx)
6917 operand *left, *right, *result;
6918 symbol *falselbl = newiTempLabel(NULL);
6919 symbol *donelbl = newiTempLabel(NULL);
6921 int preserve_result = 0;
6922 int generate_result = 0;
6924 unsigned long lit = -1;
6928 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6929 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6930 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6932 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6934 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6936 werror(W_POSSBUG2, __FILE__, __LINE__);
6937 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6938 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6942 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6944 operand *tmp = right ;
6949 if (AOP_TYPE(right) == AOP_LIT) {
6950 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6953 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6954 preserve_result = 1;
6956 if(result && AOP_SIZE(result))
6957 generate_result = 1;
6959 if(generate_result && !preserve_result)
6961 for(i = 0; i < AOP_SIZE(result); i++)
6962 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6965 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6966 for(i=0; i < AOP_SIZE(left); i++)
6968 if(AOP_TYPE(left) != AOP_ACC)
6971 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6973 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6975 if(is_LitOp(right)) {
6976 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6977 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6980 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6982 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6987 if(generate_result && preserve_result)
6989 for(i = 0; i < AOP_SIZE(result); i++)
6990 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6994 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6996 if(generate_result && preserve_result)
6997 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6999 if(ifx && IC_TRUE(ifx))
7000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7002 if(ifx && IC_FALSE(ifx))
7003 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7005 pic16_emitpLabel(falselbl->key);
7009 if(ifx && IC_FALSE(ifx))
7010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7012 if(generate_result && preserve_result)
7014 for(i = 0; i < AOP_SIZE(result); i++)
7015 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7018 pic16_emitpLabel(donelbl->key);
7024 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7025 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7026 pic16_freeAsmop(result,NULL,ic,TRUE);
7032 // old version kept for reference
7034 /*-----------------------------------------------------------------*/
7035 /* genCmpEq - generates code for equal to */
7036 /*-----------------------------------------------------------------*/
7037 static void genCmpEq (iCode *ic, iCode *ifx)
7039 operand *left, *right, *result;
7040 unsigned long lit = 0L;
7042 symbol *falselbl = newiTempLabel(NULL);
7045 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7048 DEBUGpic16_emitcode ("; ifx is non-null","");
7050 DEBUGpic16_emitcode ("; ifx is null","");
7052 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7053 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7054 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7056 size = max(AOP_SIZE(left),AOP_SIZE(right));
7058 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7060 /* if literal, literal on the right or
7061 if the right is in a pointer register and left
7063 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7064 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7065 operand *tmp = right ;
7071 if(ifx && !AOP_SIZE(result)){
7073 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7074 /* if they are both bit variables */
7075 if (AOP_TYPE(left) == AOP_CRY &&
7076 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7077 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7078 if(AOP_TYPE(right) == AOP_LIT){
7079 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7081 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7082 pic16_emitcode("cpl","c");
7083 } else if(lit == 1L) {
7084 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7086 pic16_emitcode("clr","c");
7088 /* AOP_TYPE(right) == AOP_CRY */
7090 symbol *lbl = newiTempLabel(NULL);
7091 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7093 pic16_emitcode("cpl","c");
7094 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7096 /* if true label then we jump if condition
7098 tlbl = newiTempLabel(NULL);
7099 if ( IC_TRUE(ifx) ) {
7100 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7101 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7103 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7104 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7106 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7109 /* left and right are both bit variables, result is carry */
7112 resolveIfx(&rIfx,ifx);
7114 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7115 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7116 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7117 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7122 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7124 /* They're not both bit variables. Is the right a literal? */
7125 if(AOP_TYPE(right) == AOP_LIT) {
7126 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7131 switch(lit & 0xff) {
7133 if ( IC_TRUE(ifx) ) {
7134 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7136 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7138 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7139 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7143 if ( IC_TRUE(ifx) ) {
7144 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7146 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7148 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7149 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7153 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7155 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7160 /* end of size == 1 */
7164 genc16bit2lit(left,lit,offset);
7167 /* end of size == 2 */
7172 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7173 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7174 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7175 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7178 /* search for patterns that can be optimized */
7180 genc16bit2lit(left,lit,0);
7184 emitSKPZ; // if hi word unequal
7186 emitSKPNZ; // if hi word equal
7188 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7189 genc16bit2lit(left,lit,2);
7192 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7193 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7197 pic16_emitpLabel(falselbl->key);
7206 } else if(AOP_TYPE(right) == AOP_CRY ) {
7207 /* we know the left is not a bit, but that the right is */
7208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7209 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7210 pic16_popGet(AOP(right),offset));
7211 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7213 /* if the two are equal, then W will be 0 and the Z bit is set
7214 * we could test Z now, or go ahead and check the high order bytes if
7215 * the variable we're comparing is larger than a byte. */
7218 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7220 if ( IC_TRUE(ifx) ) {
7222 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7223 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7226 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7227 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7231 /* They're both variables that are larger than bits */
7234 tlbl = newiTempLabel(NULL);
7237 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7238 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7240 if ( IC_TRUE(ifx) ) {
7244 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7246 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7247 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7251 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7254 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7255 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7260 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7262 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7263 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7267 if(s>1 && IC_TRUE(ifx)) {
7268 pic16_emitpLabel(tlbl->key);
7269 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7273 /* mark the icode as generated */
7278 /* if they are both bit variables */
7279 if (AOP_TYPE(left) == AOP_CRY &&
7280 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7281 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7282 if(AOP_TYPE(right) == AOP_LIT){
7283 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7285 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7286 pic16_emitcode("cpl","c");
7287 } else if(lit == 1L) {
7288 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7290 pic16_emitcode("clr","c");
7292 /* AOP_TYPE(right) == AOP_CRY */
7294 symbol *lbl = newiTempLabel(NULL);
7295 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7297 pic16_emitcode("cpl","c");
7298 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7301 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7302 pic16_outBitC(result);
7306 genIfxJump (ifx,"c");
7309 /* if the result is used in an arithmetic operation
7310 then put the result in place */
7311 pic16_outBitC(result);
7314 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7315 gencjne(left,right,result,ifx);
7318 gencjne(left,right,newiTempLabel(NULL));
7320 if(IC_TRUE(ifx)->key)
7321 gencjne(left,right,IC_TRUE(ifx)->key);
7323 gencjne(left,right,IC_FALSE(ifx)->key);
7327 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7328 pic16_aopPut(AOP(result),"a",0);
7333 genIfxJump (ifx,"a");
7337 /* if the result is used in an arithmetic operation
7338 then put the result in place */
7340 if (AOP_TYPE(result) != AOP_CRY)
7341 pic16_outAcc(result);
7343 /* leave the result in acc */
7347 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7348 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7349 pic16_freeAsmop(result,NULL,ic,TRUE);
7353 /*-----------------------------------------------------------------*/
7354 /* ifxForOp - returns the icode containing the ifx for operand */
7355 /*-----------------------------------------------------------------*/
7356 static iCode *ifxForOp ( operand *op, iCode *ic )
7360 /* if true symbol then needs to be assigned */
7361 if (IS_TRUE_SYMOP(op))
7364 /* if this has register type condition and
7365 the next instruction is ifx with the same operand
7366 and live to of the operand is upto the ifx only then */
7368 && ic->next->op == IFX
7369 && IC_COND(ic->next)->key == op->key
7370 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7372 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7378 ic->next->op == IFX &&
7379 IC_COND(ic->next)->key == op->key) {
7380 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7385 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7387 ic->next->op == IFX)
7388 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7391 ic->next->op == IFX &&
7392 IC_COND(ic->next)->key == op->key) {
7393 DEBUGpic16_emitcode ("; "," key is okay");
7394 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7395 OP_SYMBOL(op)->liveTo,
7400 /* the code below is completely untested
7401 * it just allows ulong2fs.c compile -- VR */
7404 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7405 __FILE__, __FUNCTION__, __LINE__);
7407 /* if this has register type condition and
7408 the next instruction is ifx with the same operand
7409 and live to of the operand is upto the ifx only then */
7411 ic->next->op == IFX &&
7412 IC_COND(ic->next)->key == op->key &&
7413 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7417 ic->next->op == IFX &&
7418 IC_COND(ic->next)->key == op->key) {
7419 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7423 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7424 __FILE__, __FUNCTION__, __LINE__);
7426 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7431 /*-----------------------------------------------------------------*/
7432 /* genAndOp - for && operation */
7433 /*-----------------------------------------------------------------*/
7434 static void genAndOp (iCode *ic)
7436 operand *left,*right, *result;
7441 /* note here that && operations that are in an
7442 if statement are taken away by backPatchLabels
7443 only those used in arthmetic operations remain */
7444 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7445 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7446 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7448 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7450 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7451 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7452 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7454 /* if both are bit variables */
7455 /* if (AOP_TYPE(left) == AOP_CRY && */
7456 /* AOP_TYPE(right) == AOP_CRY ) { */
7457 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7458 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7459 /* pic16_outBitC(result); */
7461 /* tlbl = newiTempLabel(NULL); */
7462 /* pic16_toBoolean(left); */
7463 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7464 /* pic16_toBoolean(right); */
7465 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7466 /* pic16_outBitAcc(result); */
7469 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7470 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7471 pic16_freeAsmop(result,NULL,ic,TRUE);
7475 /*-----------------------------------------------------------------*/
7476 /* genOrOp - for || operation */
7477 /*-----------------------------------------------------------------*/
7480 modified this code, but it doesn't appear to ever get called
7483 static void genOrOp (iCode *ic)
7485 operand *left,*right, *result;
7490 /* note here that || operations that are in an
7491 if statement are taken away by backPatchLabels
7492 only those used in arthmetic operations remain */
7493 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7494 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7495 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7497 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7499 /* if both are bit variables */
7500 if (AOP_TYPE(left) == AOP_CRY &&
7501 AOP_TYPE(right) == AOP_CRY ) {
7502 pic16_emitcode("clrc","");
7503 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7504 AOP(left)->aopu.aop_dir,
7505 AOP(left)->aopu.aop_dir);
7506 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7507 AOP(right)->aopu.aop_dir,
7508 AOP(right)->aopu.aop_dir);
7509 pic16_emitcode("setc","");
7512 tlbl = newiTempLabel(NULL);
7513 pic16_toBoolean(left);
7515 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7516 pic16_toBoolean(right);
7517 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7519 pic16_outBitAcc(result);
7522 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7523 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7524 pic16_freeAsmop(result,NULL,ic,TRUE);
7527 /*-----------------------------------------------------------------*/
7528 /* isLiteralBit - test if lit == 2^n */
7529 /*-----------------------------------------------------------------*/
7530 static int isLiteralBit(unsigned long lit)
7532 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7533 0x100L,0x200L,0x400L,0x800L,
7534 0x1000L,0x2000L,0x4000L,0x8000L,
7535 0x10000L,0x20000L,0x40000L,0x80000L,
7536 0x100000L,0x200000L,0x400000L,0x800000L,
7537 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7538 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7542 for(idx = 0; idx < 32; idx++)
7548 /*-----------------------------------------------------------------*/
7549 /* continueIfTrue - */
7550 /*-----------------------------------------------------------------*/
7551 static void continueIfTrue (iCode *ic)
7555 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7559 /*-----------------------------------------------------------------*/
7561 /*-----------------------------------------------------------------*/
7562 static void jumpIfTrue (iCode *ic)
7566 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7570 /*-----------------------------------------------------------------*/
7571 /* jmpTrueOrFalse - */
7572 /*-----------------------------------------------------------------*/
7573 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7575 // ugly but optimized by peephole
7578 symbol *nlbl = newiTempLabel(NULL);
7579 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7580 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7581 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7582 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7584 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7585 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7590 /*-----------------------------------------------------------------*/
7591 /* genAnd - code for and */
7592 /*-----------------------------------------------------------------*/
7593 static void genAnd (iCode *ic, iCode *ifx)
7595 operand *left, *right, *result;
7597 unsigned long lit = 0L;
7603 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7604 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7605 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7607 resolveIfx(&rIfx,ifx);
7609 /* if left is a literal & right is not then exchange them */
7610 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7611 AOP_NEEDSACC(left)) {
7612 operand *tmp = right ;
7617 /* if result = right then exchange them */
7618 if(pic16_sameRegs(AOP(result),AOP(right))){
7619 operand *tmp = right ;
7624 /* if right is bit then exchange them */
7625 if (AOP_TYPE(right) == AOP_CRY &&
7626 AOP_TYPE(left) != AOP_CRY){
7627 operand *tmp = right ;
7631 if(AOP_TYPE(right) == AOP_LIT)
7632 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7634 size = AOP_SIZE(result);
7636 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7639 // result = bit & yy;
7640 if (AOP_TYPE(left) == AOP_CRY){
7641 // c = bit & literal;
7642 if(AOP_TYPE(right) == AOP_LIT){
7644 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7647 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7650 if(size && (AOP_TYPE(result) == AOP_CRY)){
7651 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7654 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7658 pic16_emitcode("clr","c");
7661 if (AOP_TYPE(right) == AOP_CRY){
7663 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7664 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7667 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7669 pic16_emitcode("rrc","a");
7670 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7676 pic16_outBitC(result);
7678 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7679 genIfxJump(ifx, "c");
7683 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7684 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7685 if((AOP_TYPE(right) == AOP_LIT) &&
7686 (AOP_TYPE(result) == AOP_CRY) &&
7687 (AOP_TYPE(left) != AOP_CRY)){
7688 int posbit = isLiteralBit(lit);
7692 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7695 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7701 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7702 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7704 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7708 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7709 size = AOP_SIZE(left);
7712 int bp = posbit, ofs=0;
7719 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7720 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7724 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7725 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7727 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7734 symbol *tlbl = newiTempLabel(NULL);
7735 int sizel = AOP_SIZE(left);
7741 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7743 /* patch provided by Aaron Colwell */
7744 if((posbit = isLiteralBit(bytelit)) != 0) {
7745 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7746 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7747 (posbit-1),0, PO_GPR_REGISTER));
7749 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7750 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7752 if (bytelit == 0xff) {
7753 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7754 * a peephole could optimize it out -- VR */
7755 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7758 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7761 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7762 pic16_popGetLabel(tlbl->key));
7766 /* old code, left here for reference -- VR 09/2004 */
7767 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7769 if((posbit = isLiteralBit(bytelit)) != 0)
7770 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7772 if(bytelit != 0x0FFL)
7773 pic16_emitcode("anl","a,%s",
7774 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7775 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7781 // bit = left & literal
7784 pic16_emitpLabel(tlbl->key);
7786 // if(left & literal)
7789 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7792 pic16_emitpLabel(tlbl->key);
7797 pic16_outBitC(result);
7801 /* if left is same as result */
7802 if(pic16_sameRegs(AOP(result),AOP(left))){
7804 for(;size--; offset++,lit>>=8) {
7805 if(AOP_TYPE(right) == AOP_LIT){
7806 switch(lit & 0xff) {
7808 /* and'ing with 0 has clears the result */
7809 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7810 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7813 /* and'ing with 0xff is a nop when the result and left are the same */
7818 int p = pic16_my_powof2( (~lit) & 0xff );
7820 /* only one bit is set in the literal, so use a bcf instruction */
7821 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7822 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7825 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7826 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7827 if(know_W != (lit&0xff))
7828 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7830 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7835 if (AOP_TYPE(left) == AOP_ACC) {
7836 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7838 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7839 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7846 // left & result in different registers
7847 if(AOP_TYPE(result) == AOP_CRY){
7849 // if(size), result in bit
7850 // if(!size && ifx), conditional oper: if(left & right)
7851 symbol *tlbl = newiTempLabel(NULL);
7852 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7854 pic16_emitcode("setb","c");
7856 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7857 pic16_emitcode("anl","a,%s",
7858 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7859 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7864 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7865 pic16_outBitC(result);
7867 jmpTrueOrFalse(ifx, tlbl);
7869 for(;(size--);offset++) {
7871 // result = left & right
7872 if(AOP_TYPE(right) == AOP_LIT){
7873 int t = (lit >> (offset*8)) & 0x0FFL;
7876 pic16_emitcode("clrf","%s",
7877 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7878 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7881 pic16_emitcode("movf","%s,w",
7882 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7883 pic16_emitcode("movwf","%s",
7884 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7885 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7886 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7889 pic16_emitcode("movlw","0x%x",t);
7890 pic16_emitcode("andwf","%s,w",
7891 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7892 pic16_emitcode("movwf","%s",
7893 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7895 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7896 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7897 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7902 if (AOP_TYPE(left) == AOP_ACC) {
7903 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7906 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7907 pic16_emitcode("andwf","%s,w",
7908 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7909 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7910 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7912 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7913 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7919 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7920 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7921 pic16_freeAsmop(result,NULL,ic,TRUE);
7924 /*-----------------------------------------------------------------*/
7925 /* genOr - code for or */
7926 /*-----------------------------------------------------------------*/
7927 static void genOr (iCode *ic, iCode *ifx)
7929 operand *left, *right, *result;
7931 unsigned long lit = 0L;
7933 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7936 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7937 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7938 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7940 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7942 /* if left is a literal & right is not then exchange them */
7943 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7944 AOP_NEEDSACC(left)) {
7945 operand *tmp = right ;
7950 /* if result = right then exchange them */
7951 if(pic16_sameRegs(AOP(result),AOP(right))){
7952 operand *tmp = right ;
7957 /* if right is bit then exchange them */
7958 if (AOP_TYPE(right) == AOP_CRY &&
7959 AOP_TYPE(left) != AOP_CRY){
7960 operand *tmp = right ;
7965 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7967 if(AOP_TYPE(right) == AOP_LIT)
7968 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7970 size = AOP_SIZE(result);
7974 if (AOP_TYPE(left) == AOP_CRY){
7975 if(AOP_TYPE(right) == AOP_LIT){
7976 // c = bit & literal;
7978 // lit != 0 => result = 1
7979 if(AOP_TYPE(result) == AOP_CRY){
7981 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7982 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7983 // AOP(result)->aopu.aop_dir,
7984 // AOP(result)->aopu.aop_dir);
7986 continueIfTrue(ifx);
7990 // lit == 0 => result = left
7991 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7993 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7996 if (AOP_TYPE(right) == AOP_CRY){
7997 if(pic16_sameRegs(AOP(result),AOP(left))){
7999 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8000 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8001 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8003 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8004 AOP(result)->aopu.aop_dir,
8005 AOP(result)->aopu.aop_dir);
8006 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8007 AOP(right)->aopu.aop_dir,
8008 AOP(right)->aopu.aop_dir);
8009 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8010 AOP(result)->aopu.aop_dir,
8011 AOP(result)->aopu.aop_dir);
8013 if( AOP_TYPE(result) == AOP_ACC) {
8014 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8015 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8016 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8017 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8021 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),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_BSF, pic16_popGet(AOP(result),0));
8026 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8027 AOP(result)->aopu.aop_dir,
8028 AOP(result)->aopu.aop_dir);
8029 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8030 AOP(right)->aopu.aop_dir,
8031 AOP(right)->aopu.aop_dir);
8032 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8033 AOP(left)->aopu.aop_dir,
8034 AOP(left)->aopu.aop_dir);
8035 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8036 AOP(result)->aopu.aop_dir,
8037 AOP(result)->aopu.aop_dir);
8042 symbol *tlbl = newiTempLabel(NULL);
8043 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8046 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8047 if( AOP_TYPE(right) == AOP_ACC) {
8048 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8050 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8051 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8056 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8057 pic16_emitcode(";XXX setb","c");
8058 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8059 AOP(left)->aopu.aop_dir,tlbl->key+100);
8060 pic16_toBoolean(right);
8061 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8062 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8063 jmpTrueOrFalse(ifx, tlbl);
8067 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8074 pic16_outBitC(result);
8076 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8077 genIfxJump(ifx, "c");
8081 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8082 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8083 if((AOP_TYPE(right) == AOP_LIT) &&
8084 (AOP_TYPE(result) == AOP_CRY) &&
8085 (AOP_TYPE(left) != AOP_CRY)){
8087 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8090 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8092 continueIfTrue(ifx);
8095 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8096 // lit = 0, result = boolean(left)
8098 pic16_emitcode(";XXX setb","c");
8099 pic16_toBoolean(right);
8101 symbol *tlbl = newiTempLabel(NULL);
8102 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8104 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8106 genIfxJump (ifx,"a");
8110 pic16_outBitC(result);
8114 /* if left is same as result */
8115 if(pic16_sameRegs(AOP(result),AOP(left))){
8117 for(;size--; offset++,lit>>=8) {
8118 if(AOP_TYPE(right) == AOP_LIT){
8119 if((lit & 0xff) == 0)
8120 /* or'ing with 0 has no effect */
8123 int p = pic16_my_powof2(lit & 0xff);
8125 /* only one bit is set in the literal, so use a bsf instruction */
8126 pic16_emitpcode(POC_BSF,
8127 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8129 if(know_W != (lit & 0xff))
8130 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8131 know_W = lit & 0xff;
8132 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8137 if (AOP_TYPE(left) == AOP_ACC) {
8138 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8139 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8141 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8142 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8144 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8145 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8151 // left & result in different registers
8152 if(AOP_TYPE(result) == AOP_CRY){
8154 // if(size), result in bit
8155 // if(!size && ifx), conditional oper: if(left | right)
8156 symbol *tlbl = newiTempLabel(NULL);
8157 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8158 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8162 pic16_emitcode(";XXX setb","c");
8164 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8165 pic16_emitcode(";XXX orl","a,%s",
8166 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8167 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8172 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8173 pic16_outBitC(result);
8175 jmpTrueOrFalse(ifx, tlbl);
8176 } else for(;(size--);offset++){
8178 // result = left & right
8179 if(AOP_TYPE(right) == AOP_LIT){
8180 int t = (lit >> (offset*8)) & 0x0FFL;
8183 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8184 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8186 // pic16_emitcode("movf","%s,w",
8187 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8188 // pic16_emitcode("movwf","%s",
8189 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8192 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8193 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8196 // pic16_emitcode("movlw","0x%x",t);
8197 // pic16_emitcode("iorwf","%s,w",
8198 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199 // pic16_emitcode("movwf","%s",
8200 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8206 // faster than result <- left, anl result,right
8207 // and better if result is SFR
8208 if (AOP_TYPE(left) == AOP_ACC) {
8209 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8210 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8212 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8213 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8215 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8216 // pic16_emitcode("iorwf","%s,w",
8217 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8219 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8220 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8225 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8226 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8227 pic16_freeAsmop(result,NULL,ic,TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genXor - code for xclusive or */
8232 /*-----------------------------------------------------------------*/
8233 static void genXor (iCode *ic, iCode *ifx)
8235 operand *left, *right, *result;
8237 unsigned long lit = 0L;
8239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8242 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8243 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8244 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8246 /* if left is a literal & right is not ||
8247 if left needs acc & right does not */
8248 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8249 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8250 operand *tmp = right ;
8255 /* if result = right then exchange them */
8256 if(pic16_sameRegs(AOP(result),AOP(right))){
8257 operand *tmp = right ;
8262 /* if right is bit then exchange them */
8263 if (AOP_TYPE(right) == AOP_CRY &&
8264 AOP_TYPE(left) != AOP_CRY){
8265 operand *tmp = right ;
8269 if(AOP_TYPE(right) == AOP_LIT)
8270 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8272 size = AOP_SIZE(result);
8276 if (AOP_TYPE(left) == AOP_CRY){
8277 if(AOP_TYPE(right) == AOP_LIT){
8278 // c = bit & literal;
8280 // lit>>1 != 0 => result = 1
8281 if(AOP_TYPE(result) == AOP_CRY){
8283 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8284 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8286 continueIfTrue(ifx);
8289 pic16_emitcode("setb","c");
8293 // lit == 0, result = left
8294 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8296 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8298 // lit == 1, result = not(left)
8299 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8300 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8301 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8302 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8305 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8306 pic16_emitcode("cpl","c");
8313 symbol *tlbl = newiTempLabel(NULL);
8314 if (AOP_TYPE(right) == AOP_CRY){
8316 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8319 int sizer = AOP_SIZE(right);
8321 // if val>>1 != 0, result = 1
8322 pic16_emitcode("setb","c");
8324 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8326 // test the msb of the lsb
8327 pic16_emitcode("anl","a,#0xfe");
8328 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8332 pic16_emitcode("rrc","a");
8334 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8335 pic16_emitcode("cpl","c");
8336 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8341 pic16_outBitC(result);
8343 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8344 genIfxJump(ifx, "c");
8348 if(pic16_sameRegs(AOP(result),AOP(left))){
8349 /* if left is same as result */
8350 for(;size--; offset++) {
8351 if(AOP_TYPE(right) == AOP_LIT){
8352 int t = (lit >> (offset*8)) & 0x0FFL;
8356 if (IS_AOP_PREG(left)) {
8357 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8358 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8359 pic16_aopPut(AOP(result),"a",offset);
8361 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8362 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8363 pic16_emitcode("xrl","%s,%s",
8364 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8365 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8368 if (AOP_TYPE(left) == AOP_ACC)
8369 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8372 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8374 if (IS_AOP_PREG(left)) {
8375 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8376 pic16_aopPut(AOP(result),"a",offset);
8378 pic16_emitcode("xrl","%s,a",
8379 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8385 // left & result in different registers
8386 if(AOP_TYPE(result) == AOP_CRY){
8388 // if(size), result in bit
8389 // if(!size && ifx), conditional oper: if(left ^ right)
8390 symbol *tlbl = newiTempLabel(NULL);
8391 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8393 pic16_emitcode("setb","c");
8395 if((AOP_TYPE(right) == AOP_LIT) &&
8396 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8397 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8399 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8400 pic16_emitcode("xrl","a,%s",
8401 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8403 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8408 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8409 pic16_outBitC(result);
8411 jmpTrueOrFalse(ifx, tlbl);
8412 } else for(;(size--);offset++){
8414 // result = left & right
8415 if(AOP_TYPE(right) == AOP_LIT){
8416 int t = (lit >> (offset*8)) & 0x0FFL;
8419 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8420 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8421 pic16_emitcode("movf","%s,w",
8422 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8423 pic16_emitcode("movwf","%s",
8424 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8427 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8428 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8429 pic16_emitcode("comf","%s,w",
8430 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8431 pic16_emitcode("movwf","%s",
8432 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8435 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8436 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8437 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8438 pic16_emitcode("movlw","0x%x",t);
8439 pic16_emitcode("xorwf","%s,w",
8440 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8441 pic16_emitcode("movwf","%s",
8442 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8448 // faster than result <- left, anl result,right
8449 // and better if result is SFR
8450 if (AOP_TYPE(left) == AOP_ACC) {
8451 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8452 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8454 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8455 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8456 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8457 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8459 if ( AOP_TYPE(result) != AOP_ACC){
8460 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8461 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8467 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8468 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8469 pic16_freeAsmop(result,NULL,ic,TRUE);
8472 /*-----------------------------------------------------------------*/
8473 /* genInline - write the inline code out */
8474 /*-----------------------------------------------------------------*/
8475 static void genInline (iCode *ic)
8477 char *buffer, *bp, *bp1;
8479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8481 _G.inLine += (!options.asmpeep);
8483 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8484 strcpy(buffer,IC_INLINE(ic));
8486 while((bp1=strstr(bp, "\\n"))) {
8494 /* This is an experimental code for #pragma inline
8495 and is temporarily disabled for 2.5.0 release */
8503 cbuf = Safe_strdup(buffer);
8504 cblen = strlen(buffer)+1;
8505 memset(cbuf, 0, cblen);
8510 if(*bp != '%')*bp1++ = *bp++;
8516 if(i>elementsInSet(asmInlineMap))break;
8519 s = indexSet(asmInlineMap, i);
8520 DEBUGpc("searching symbol s = `%s'", s);
8521 sym = findSym(SymbolTab, NULL, s);
8524 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8526 strcat(bp1, sym->rname);
8532 if(strlen(bp1) > cblen - 16) {
8533 int i = strlen(cbuf);
8535 cbuf = realloc(cbuf, cblen);
8536 memset(cbuf+i, 0, 50);
8542 buffer = Safe_strdup( cbuf );
8549 /* emit each line as a code */
8555 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8563 /* print label, use this special format with NULL directive
8564 * to denote that the argument should not be indented with tab */
8565 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8568 /* advance to end of line (prevent splitting of comments at ':' */
8569 while (*bp && *bp != '\n') {
8577 if ((bp1 != bp) && *bp1)
8578 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8583 _G.inLine -= (!options.asmpeep);
8586 /*-----------------------------------------------------------------*/
8587 /* genRRC - rotate right with carry */
8588 /*-----------------------------------------------------------------*/
8589 static void genRRC (iCode *ic)
8591 operand *left , *result ;
8592 int size, offset = 0, same;
8594 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8596 /* rotate right with carry */
8598 result=IC_RESULT(ic);
8599 pic16_aopOp (left,ic,FALSE);
8600 pic16_aopOp (result,ic,TRUE);
8602 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8604 same = pic16_sameRegs(AOP(result),AOP(left));
8606 size = AOP_SIZE(result);
8608 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8610 /* get the lsb and put it into the carry */
8611 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8618 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8620 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8627 pic16_freeAsmop(left,NULL,ic,TRUE);
8628 pic16_freeAsmop(result,NULL,ic,TRUE);
8631 /*-----------------------------------------------------------------*/
8632 /* genRLC - generate code for rotate left with carry */
8633 /*-----------------------------------------------------------------*/
8634 static void genRLC (iCode *ic)
8636 operand *left , *result ;
8637 int size, offset = 0;
8640 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8641 /* rotate right with carry */
8643 result=IC_RESULT(ic);
8644 pic16_aopOp (left,ic,FALSE);
8645 pic16_aopOp (result,ic,TRUE);
8647 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8649 same = pic16_sameRegs(AOP(result),AOP(left));
8651 /* move it to the result */
8652 size = AOP_SIZE(result);
8654 /* get the msb and put it into the carry */
8655 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8662 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8664 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8672 pic16_freeAsmop(left,NULL,ic,TRUE);
8673 pic16_freeAsmop(result,NULL,ic,TRUE);
8677 /* gpasm can get the highest order bit with HIGH/UPPER
8678 * so the following probably is not needed -- VR */
8680 /*-----------------------------------------------------------------*/
8681 /* genGetHbit - generates code get highest order bit */
8682 /*-----------------------------------------------------------------*/
8683 static void genGetHbit (iCode *ic)
8685 operand *left, *result;
8687 result=IC_RESULT(ic);
8688 pic16_aopOp (left,ic,FALSE);
8689 pic16_aopOp (result,ic,FALSE);
8691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8692 /* get the highest order byte into a */
8693 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8694 if(AOP_TYPE(result) == AOP_CRY){
8695 pic16_emitcode("rlc","a");
8696 pic16_outBitC(result);
8699 pic16_emitcode("rl","a");
8700 pic16_emitcode("anl","a,#0x01");
8701 pic16_outAcc(result);
8705 pic16_freeAsmop(left,NULL,ic,TRUE);
8706 pic16_freeAsmop(result,NULL,ic,TRUE);
8710 /*-----------------------------------------------------------------*/
8711 /* AccRol - rotate left accumulator by known count */
8712 /*-----------------------------------------------------------------*/
8713 static void AccRol (int shCount)
8715 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8716 shCount &= 0x0007; // shCount : 0..7
8721 pic16_emitcode("rl","a");
8724 pic16_emitcode("rl","a");
8725 pic16_emitcode("rl","a");
8728 pic16_emitcode("swap","a");
8729 pic16_emitcode("rr","a");
8732 pic16_emitcode("swap","a");
8735 pic16_emitcode("swap","a");
8736 pic16_emitcode("rl","a");
8739 pic16_emitcode("rr","a");
8740 pic16_emitcode("rr","a");
8743 pic16_emitcode("rr","a");
8749 /*-----------------------------------------------------------------*/
8750 /* AccLsh - left shift accumulator by known count */
8751 /*-----------------------------------------------------------------*/
8752 static void AccLsh (int shCount, int doMask)
8754 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8760 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8763 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8764 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8767 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8768 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8771 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8774 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8775 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8778 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8779 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8782 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786 /* no masking is required in genPackBits */
8787 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8791 /*-----------------------------------------------------------------*/
8792 /* AccRsh - right shift accumulator by known count */
8793 /*-----------------------------------------------------------------*/
8794 static void AccRsh (int shCount, int andmask)
8796 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8801 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8804 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8805 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8808 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8809 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8815 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8816 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8819 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8820 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8823 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8828 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8830 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8834 /*-----------------------------------------------------------------*/
8835 /* AccSRsh - signed right shift accumulator by known count */
8836 /*-----------------------------------------------------------------*/
8837 static void AccSRsh (int shCount)
8840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8843 pic16_emitcode("mov","c,acc.7");
8844 pic16_emitcode("rrc","a");
8845 } else if(shCount == 2){
8846 pic16_emitcode("mov","c,acc.7");
8847 pic16_emitcode("rrc","a");
8848 pic16_emitcode("mov","c,acc.7");
8849 pic16_emitcode("rrc","a");
8851 tlbl = newiTempLabel(NULL);
8852 /* rotate right accumulator */
8853 AccRol(8 - shCount);
8854 /* and kill the higher order bits */
8855 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8856 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8857 pic16_emitcode("orl","a,#0x%02x",
8858 (unsigned char)~SRMask[shCount]);
8859 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8865 /*-----------------------------------------------------------------*/
8866 /* shiftR1Left2Result - shift right one byte from left to result */
8867 /*-----------------------------------------------------------------*/
8868 static void shiftR1Left2ResultSigned (operand *left, int offl,
8869 operand *result, int offr,
8874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8876 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8880 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8882 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8885 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8893 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8895 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8896 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8898 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8899 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8905 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8907 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8911 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8912 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8915 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8916 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8918 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8922 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8923 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8924 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8925 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8930 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8932 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8936 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8937 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8938 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8945 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8946 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8947 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8948 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8953 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8955 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8961 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8962 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8963 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8968 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8976 /*-----------------------------------------------------------------*/
8977 /* shiftR1Left2Result - shift right one byte from left to result */
8978 /*-----------------------------------------------------------------*/
8979 static void shiftR1Left2Result (operand *left, int offl,
8980 operand *result, int offr,
8981 int shCount, int sign)
8985 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8987 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8989 /* Copy the msb into the carry if signed. */
8991 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9001 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9028 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9035 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9036 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9041 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9042 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9050 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9051 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9052 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9053 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9059 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9060 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9069 /*-----------------------------------------------------------------*/
9070 /* shiftL1Left2Result - shift left one byte from left to result */
9071 /*-----------------------------------------------------------------*/
9072 static void shiftL1Left2Result (operand *left, int offl,
9073 operand *result, int offr, int shCount)
9078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9080 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9081 DEBUGpic16_emitcode ("; ***","same = %d",same);
9082 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9084 /* shift left accumulator */
9085 //AccLsh(shCount, 1); // don't comment out just yet...
9086 // pic16_aopPut(AOP(result),"a",offr);
9090 /* Shift left 1 bit position */
9091 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9093 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9095 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9096 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9100 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9101 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9102 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9107 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9108 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9110 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9114 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9119 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9120 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9124 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9125 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9126 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9132 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9133 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9137 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9142 /*-----------------------------------------------------------------*/
9143 /* movLeft2Result - move byte from left to result */
9144 /*-----------------------------------------------------------------*/
9145 static void movLeft2Result (operand *left, int offl,
9146 operand *result, int offr)
9149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9150 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9151 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9153 if (*l == '@' && (IS_AOP_PREG(result))) {
9154 pic16_emitcode("mov","a,%s",l);
9155 pic16_aopPut(AOP(result),"a",offr);
9157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9158 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9163 /*-----------------------------------------------------------------*/
9164 /* shiftL2Left2Result - shift left two bytes from left to result */
9165 /*-----------------------------------------------------------------*/
9166 static void shiftL2Left2Result (operand *left, int offl,
9167 operand *result, int offr, int shCount)
9169 int same = pic16_sameRegs(AOP(result), AOP(left));
9172 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9174 if (same && (offl != offr)) { // shift bytes
9177 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9180 } else { // just treat as different later on
9193 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9194 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9195 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9199 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9200 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9206 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9207 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9208 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9209 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9210 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9211 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9212 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9214 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9219 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9220 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9221 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9222 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9223 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9224 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9225 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9226 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9227 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9228 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9231 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9232 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9234 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9235 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9245 /* note, use a mov/add for the shift since the mov has a
9246 chance of getting optimized out */
9247 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9248 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9249 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9250 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9255 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9256 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9262 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9263 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9265 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9266 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9267 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9268 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9269 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9273 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9274 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9278 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9279 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9280 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9283 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9284 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9285 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9286 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9287 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9288 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9289 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9290 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9293 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9294 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9295 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9297 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9302 /*-----------------------------------------------------------------*/
9303 /* shiftR2Left2Result - shift right two bytes from left to result */
9304 /*-----------------------------------------------------------------*/
9305 static void shiftR2Left2Result (operand *left, int offl,
9306 operand *result, int offr,
9307 int shCount, int sign)
9309 int same = pic16_sameRegs(AOP(result), AOP(left));
9311 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9313 if (same && (offl != offr)) { // shift right bytes
9316 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9317 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9319 } else { // just treat as different later on
9330 /* obtain sign from left operand */
9332 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9337 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9338 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9340 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9341 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9342 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9343 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9348 /* now get sign from already assigned result (avoid BANKSEL) */
9349 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9352 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9353 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9360 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9361 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9362 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9364 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9365 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9366 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9367 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9369 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9370 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9371 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9373 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9374 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9375 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9376 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9377 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9381 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9382 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9386 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9387 pic16_emitpcode(POC_BTFSC,
9388 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9389 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9397 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9398 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9400 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9401 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9402 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9403 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9405 pic16_emitpcode(POC_BTFSC,
9406 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9407 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9409 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9410 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9411 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9412 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9414 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9415 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9416 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9417 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9418 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9419 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9420 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9421 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9423 pic16_emitpcode(POC_BTFSC,
9424 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9425 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9427 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9428 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9435 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9436 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9437 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9438 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9441 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9443 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9448 /*-----------------------------------------------------------------*/
9449 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9450 /*-----------------------------------------------------------------*/
9451 static void shiftLLeftOrResult (operand *left, int offl,
9452 operand *result, int offr, int shCount)
9454 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9456 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9457 /* shift left accumulator */
9459 /* or with result */
9460 /* back to result */
9461 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9464 /*-----------------------------------------------------------------*/
9465 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9466 /*-----------------------------------------------------------------*/
9467 static void shiftRLeftOrResult (operand *left, int offl,
9468 operand *result, int offr, int shCount)
9470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9472 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9473 /* shift right accumulator */
9475 /* or with result */
9476 /* back to result */
9477 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9480 /*-----------------------------------------------------------------*/
9481 /* genlshOne - left shift a one byte quantity by known count */
9482 /*-----------------------------------------------------------------*/
9483 static void genlshOne (operand *result, operand *left, int shCount)
9485 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9486 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9489 /*-----------------------------------------------------------------*/
9490 /* genlshTwo - left shift two bytes by known amount != 0 */
9491 /*-----------------------------------------------------------------*/
9492 static void genlshTwo (operand *result,operand *left, int shCount)
9496 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9497 size = pic16_getDataSize(result);
9499 /* if shCount >= 8 */
9505 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9507 movLeft2Result(left, LSB, result, MSB16);
9509 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9512 /* 1 <= shCount <= 7 */
9515 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9517 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9521 /*-----------------------------------------------------------------*/
9522 /* shiftLLong - shift left one long from left to result */
9523 /* offr = LSB or MSB16 */
9524 /*-----------------------------------------------------------------*/
9525 static void shiftLLong (operand *left, operand *result, int offr )
9527 int size = AOP_SIZE(result);
9528 int same = pic16_sameRegs(AOP(left),AOP(result));
9531 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9533 if (same && (offr == MSB16)) { //shift one byte
9534 for(i=size-1;i>=MSB16;i--) {
9535 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9536 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9539 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9542 if (size > LSB+offr ){
9544 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9546 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9547 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9551 if(size > MSB16+offr){
9553 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9555 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9556 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9560 if(size > MSB24+offr){
9562 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9564 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9565 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9569 if(size > MSB32+offr){
9571 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9573 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9574 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9578 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9582 /*-----------------------------------------------------------------*/
9583 /* genlshFour - shift four byte by a known amount != 0 */
9584 /*-----------------------------------------------------------------*/
9585 static void genlshFour (operand *result, operand *left, int shCount)
9589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9590 size = AOP_SIZE(result);
9592 /* if shifting more that 3 bytes */
9593 if (shCount >= 24 ) {
9596 /* lowest order of left goes to the highest
9597 order of the destination */
9598 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9600 movLeft2Result(left, LSB, result, MSB32);
9602 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9603 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9604 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9609 /* more than two bytes */
9610 else if ( shCount >= 16 ) {
9611 /* lower order two bytes goes to higher order two bytes */
9613 /* if some more remaining */
9615 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9617 movLeft2Result(left, MSB16, result, MSB32);
9618 movLeft2Result(left, LSB, result, MSB24);
9620 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9621 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9625 /* if more than 1 byte */
9626 else if ( shCount >= 8 ) {
9627 /* lower order three bytes goes to higher order three bytes */
9631 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9633 movLeft2Result(left, LSB, result, MSB16);
9635 else{ /* size = 4 */
9637 movLeft2Result(left, MSB24, result, MSB32);
9638 movLeft2Result(left, MSB16, result, MSB24);
9639 movLeft2Result(left, LSB, result, MSB16);
9640 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9642 else if(shCount == 1)
9643 shiftLLong(left, result, MSB16);
9645 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9646 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9647 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9648 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9653 /* 1 <= shCount <= 7 */
9654 else if(shCount <= 3)
9656 shiftLLong(left, result, LSB);
9657 while(--shCount >= 1)
9658 shiftLLong(result, result, LSB);
9660 /* 3 <= shCount <= 7, optimize */
9662 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9663 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9664 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9668 /*-----------------------------------------------------------------*/
9669 /* genLeftShiftLiteral - left shifting by known count */
9670 /*-----------------------------------------------------------------*/
9671 void pic16_genLeftShiftLiteral (operand *left,
9676 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9680 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9681 pic16_freeAsmop(right,NULL,ic,TRUE);
9683 pic16_aopOp(left,ic,FALSE);
9684 pic16_aopOp(result,ic,TRUE);
9686 size = getSize(operandType(result));
9689 pic16_emitcode("; shift left ","result %d, left %d",size,
9693 /* I suppose that the left size >= result size */
9696 movLeft2Result(left, size, result, size);
9700 else if(shCount >= (size * 8))
9702 pic16_aopPut(AOP(result),zero,size);
9706 genlshOne (result,left,shCount);
9711 genlshTwo (result,left,shCount);
9715 genlshFour (result,left,shCount);
9719 pic16_freeAsmop(left,NULL,ic,TRUE);
9720 pic16_freeAsmop(result,NULL,ic,TRUE);
9723 /*-----------------------------------------------------------------*
9724 * genMultiAsm - repeat assembly instruction for size of register.
9725 * if endian == 1, then the high byte (i.e base address + size of
9726 * register) is used first else the low byte is used first;
9727 *-----------------------------------------------------------------*/
9728 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9733 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9746 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9752 #if !(USE_GENERIC_SIGNED_SHIFT)
9753 /*-----------------------------------------------------------------*/
9754 /* genLeftShift - generates code for left shifting */
9755 /*-----------------------------------------------------------------*/
9756 static void genLeftShift (iCode *ic)
9758 operand *left,*right, *result;
9761 symbol *tlbl , *tlbl1;
9764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9766 right = IC_RIGHT(ic);
9768 result = IC_RESULT(ic);
9770 pic16_aopOp(right,ic,FALSE);
9772 /* if the shift count is known then do it
9773 as efficiently as possible */
9774 if (AOP_TYPE(right) == AOP_LIT) {
9775 pic16_genLeftShiftLiteral (left,right,result,ic);
9779 /* shift count is unknown then we have to form
9780 * a loop. Get the loop count in WREG : Note: we take
9781 * only the lower order byte since shifting
9782 * more than 32 bits make no sense anyway, ( the
9783 * largest size of an object can be only 32 bits ) */
9785 pic16_aopOp(left,ic,FALSE);
9786 pic16_aopOp(result,ic,FALSE);
9788 /* now move the left to the result if they are not the
9789 * same, and if size > 1,
9790 * and if right is not same to result (!!!) -- VR */
9791 if (!pic16_sameRegs(AOP(left),AOP(result))
9792 && (AOP_SIZE(result) > 1)) {
9794 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9796 size = AOP_SIZE(result);
9801 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9802 if (*l == '@' && (IS_AOP_PREG(result))) {
9804 pic16_emitcode("mov","a,%s",l);
9805 pic16_aopPut(AOP(result),"a",offset);
9809 /* we don't know if left is a literal or a register, take care -- VR */
9810 pic16_mov2f(AOP(result), AOP(left), offset);
9816 size = AOP_SIZE(result);
9818 /* if it is only one byte then */
9820 if(optimized_for_speed) {
9821 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9822 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9823 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9824 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9825 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9826 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9827 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9828 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9829 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9830 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9831 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9832 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9837 tlbl = newiTempLabel(NULL);
9840 /* this is already done, why change it? */
9841 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9842 pic16_mov2f(AOP(result), AOP(left), 0);
9846 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9847 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9848 pic16_emitpLabel(tlbl->key);
9849 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9850 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9852 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9857 if (pic16_sameRegs(AOP(left),AOP(result))) {
9859 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9861 tlbl = newiTempLabel(NULL);
9862 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9863 genMultiAsm(POC_RRCF, result, size,1);
9864 pic16_emitpLabel(tlbl->key);
9865 genMultiAsm(POC_RLCF, result, size,0);
9866 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9868 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9872 //tlbl = newiTempLabel(NULL);
9874 //tlbl1 = newiTempLabel(NULL);
9876 //reAdjustPreg(AOP(result));
9878 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9879 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9880 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9882 //pic16_emitcode("add","a,acc");
9883 //pic16_aopPut(AOP(result),"a",offset++);
9885 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9887 // pic16_emitcode("rlc","a");
9888 // pic16_aopPut(AOP(result),"a",offset++);
9890 //reAdjustPreg(AOP(result));
9892 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9893 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9896 tlbl = newiTempLabel(NULL);
9897 tlbl1= newiTempLabel(NULL);
9899 size = AOP_SIZE(result);
9902 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9906 /* offset should be 0, 1 or 3 */
9908 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9910 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9912 pic16_emitpcode(POC_MOVWF, pctemp);
9915 pic16_emitpLabel(tlbl->key);
9918 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9920 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9922 pic16_emitpcode(POC_DECFSZ, pctemp);
9923 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9924 pic16_emitpLabel(tlbl1->key);
9926 pic16_popReleaseTempReg(pctemp,1);
9930 pic16_freeAsmop (right,NULL,ic,TRUE);
9931 pic16_freeAsmop(left,NULL,ic,TRUE);
9932 pic16_freeAsmop(result,NULL,ic,TRUE);
9938 #error old code (left here for reference)
9939 /*-----------------------------------------------------------------*/
9940 /* genLeftShift - generates code for left shifting */
9941 /*-----------------------------------------------------------------*/
9942 static void genLeftShift (iCode *ic)
9944 operand *left,*right, *result;
9947 symbol *tlbl , *tlbl1;
9950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9952 right = IC_RIGHT(ic);
9954 result = IC_RESULT(ic);
9956 pic16_aopOp(right,ic,FALSE);
9958 /* if the shift count is known then do it
9959 as efficiently as possible */
9960 if (AOP_TYPE(right) == AOP_LIT) {
9961 pic16_genLeftShiftLiteral (left,right,result,ic);
9965 /* shift count is unknown then we have to form
9966 a loop get the loop count in B : Note: we take
9967 only the lower order byte since shifting
9968 more that 32 bits make no sense anyway, ( the
9969 largest size of an object can be only 32 bits ) */
9972 pic16_aopOp(left,ic,FALSE);
9973 pic16_aopOp(result,ic,FALSE);
9975 /* now move the left to the result if they are not the
9977 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9978 AOP_SIZE(result) > 1) {
9980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9982 size = AOP_SIZE(result);
9985 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9986 if (*l == '@' && (IS_AOP_PREG(result))) {
9988 pic16_emitcode("mov","a,%s",l);
9989 pic16_aopPut(AOP(result),"a",offset);
9992 /* we don't know if left is a literal or a register, take care -- VR */
9993 pic16_mov2f(AOP(result), AOP(left), offset);
9999 size = AOP_SIZE(result);
10001 /* if it is only one byte then */
10003 if(optimized_for_speed) {
10004 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10005 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10006 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10007 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10009 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10010 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10011 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10012 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10013 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10014 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10015 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10018 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10020 tlbl = newiTempLabel(NULL);
10021 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10022 pic16_mov2f(AOP(result), AOP(left), 0);
10024 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10025 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10028 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10029 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10030 pic16_emitpLabel(tlbl->key);
10031 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10032 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10034 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10039 if (pic16_sameRegs(AOP(left),AOP(result))) {
10041 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10043 tlbl = newiTempLabel(NULL);
10044 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10045 genMultiAsm(POC_RRCF, result, size,1);
10046 pic16_emitpLabel(tlbl->key);
10047 genMultiAsm(POC_RLCF, result, size,0);
10048 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10050 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10054 //tlbl = newiTempLabel(NULL);
10056 //tlbl1 = newiTempLabel(NULL);
10058 //reAdjustPreg(AOP(result));
10060 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10061 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10062 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10064 //pic16_emitcode("add","a,acc");
10065 //pic16_aopPut(AOP(result),"a",offset++);
10067 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10069 // pic16_emitcode("rlc","a");
10070 // pic16_aopPut(AOP(result),"a",offset++);
10072 //reAdjustPreg(AOP(result));
10074 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10075 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10078 tlbl = newiTempLabel(NULL);
10079 tlbl1= newiTempLabel(NULL);
10081 size = AOP_SIZE(result);
10084 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10086 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10088 /* offset should be 0, 1 or 3 */
10090 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10092 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10094 pic16_emitpcode(POC_MOVWF, pctemp);
10097 pic16_emitpLabel(tlbl->key);
10100 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10102 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10104 pic16_emitpcode(POC_DECFSZ, pctemp);
10105 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10106 pic16_emitpLabel(tlbl1->key);
10108 pic16_popReleaseTempReg(pctemp,1);
10112 pic16_freeAsmop (right,NULL,ic,TRUE);
10113 pic16_freeAsmop(left,NULL,ic,TRUE);
10114 pic16_freeAsmop(result,NULL,ic,TRUE);
10118 /*-----------------------------------------------------------------*/
10119 /* genrshOne - right shift a one byte quantity by known count */
10120 /*-----------------------------------------------------------------*/
10121 static void genrshOne (operand *result, operand *left,
10122 int shCount, int sign)
10124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10125 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10128 /*-----------------------------------------------------------------*/
10129 /* genrshTwo - right shift two bytes by known amount != 0 */
10130 /*-----------------------------------------------------------------*/
10131 static void genrshTwo (operand *result,operand *left,
10132 int shCount, int sign)
10134 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10135 /* if shCount >= 8 */
10136 if (shCount >= 8) {
10139 shiftR1Left2Result(left, MSB16, result, LSB,
10142 movLeft2Result(left, MSB16, result, LSB);
10144 pic16_addSign (result, 1, sign);
10147 /* 1 <= shCount <= 7 */
10149 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10152 /*-----------------------------------------------------------------*/
10153 /* shiftRLong - shift right one long from left to result */
10154 /* offl = LSB or MSB16 */
10155 /*-----------------------------------------------------------------*/
10156 static void shiftRLong (operand *left, int offl,
10157 operand *result, int sign)
10159 int size = AOP_SIZE(result);
10160 int same = pic16_sameRegs(AOP(left),AOP(result));
10162 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10164 if (same && (offl == MSB16)) { //shift one byte right
10165 for(i=MSB16;i<size;i++) {
10166 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10167 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10172 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10178 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10180 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10181 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10184 if(offl == MSB16) {
10185 /* add sign of "a" */
10186 pic16_addSign(result, MSB32, sign);
10190 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10192 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10197 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10199 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10200 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10204 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10207 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10208 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10213 /*-----------------------------------------------------------------*/
10214 /* genrshFour - shift four byte by a known amount != 0 */
10215 /*-----------------------------------------------------------------*/
10216 static void genrshFour (operand *result, operand *left,
10217 int shCount, int sign)
10219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10220 /* if shifting more that 3 bytes */
10221 if(shCount >= 24 ) {
10224 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10226 movLeft2Result(left, MSB32, result, LSB);
10228 pic16_addSign(result, MSB16, sign);
10230 else if(shCount >= 16){
10233 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10235 movLeft2Result(left, MSB24, result, LSB);
10236 movLeft2Result(left, MSB32, result, MSB16);
10238 pic16_addSign(result, MSB24, sign);
10240 else if(shCount >= 8){
10243 shiftRLong(left, MSB16, result, sign);
10244 else if(shCount == 0){
10245 movLeft2Result(left, MSB16, result, LSB);
10246 movLeft2Result(left, MSB24, result, MSB16);
10247 movLeft2Result(left, MSB32, result, MSB24);
10248 pic16_addSign(result, MSB32, sign);
10250 else{ //shcount >= 2
10251 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10252 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10253 /* the last shift is signed */
10254 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10255 pic16_addSign(result, MSB32, sign);
10258 else{ /* 1 <= shCount <= 7 */
10260 shiftRLong(left, LSB, result, sign);
10262 shiftRLong(result, LSB, result, sign);
10265 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10266 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10267 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10272 /*-----------------------------------------------------------------*/
10273 /* genRightShiftLiteral - right shifting by known count */
10274 /*-----------------------------------------------------------------*/
10275 static void genRightShiftLiteral (operand *left,
10281 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10282 int lsize,res_size;
10284 pic16_freeAsmop(right,NULL,ic,TRUE);
10286 pic16_aopOp(left,ic,FALSE);
10287 pic16_aopOp(result,ic,TRUE);
10289 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10292 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10296 lsize = pic16_getDataSize(left);
10297 res_size = pic16_getDataSize(result);
10298 /* test the LEFT size !!! */
10300 /* I suppose that the left size >= result size */
10302 assert (res_size <= lsize);
10303 while (res_size--) {
10304 pic16_mov2f (AOP(result), AOP(left), res_size);
10308 else if(shCount >= (lsize * 8)){
10310 if(res_size == 1) {
10311 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10313 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10314 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10319 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10320 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10321 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10328 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10333 switch (res_size) {
10335 genrshOne (result,left,shCount,sign);
10339 genrshTwo (result,left,shCount,sign);
10343 genrshFour (result,left,shCount,sign);
10351 pic16_freeAsmop(left,NULL,ic,TRUE);
10352 pic16_freeAsmop(result,NULL,ic,TRUE);
10355 #if !(USE_GENERIC_SIGNED_SHIFT)
10356 /*-----------------------------------------------------------------*/
10357 /* genSignedRightShift - right shift of signed number */
10358 /*-----------------------------------------------------------------*/
10359 static void genSignedRightShift (iCode *ic)
10361 operand *right, *left, *result;
10364 symbol *tlbl, *tlbl1 ;
10367 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10369 /* we do it the hard way put the shift count in b
10370 and loop thru preserving the sign */
10371 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10373 right = IC_RIGHT(ic);
10374 left = IC_LEFT(ic);
10375 result = IC_RESULT(ic);
10377 pic16_aopOp(right,ic,FALSE);
10378 pic16_aopOp(left,ic,FALSE);
10379 pic16_aopOp(result,ic,FALSE);
10382 if ( AOP_TYPE(right) == AOP_LIT) {
10383 genRightShiftLiteral (left,right,result,ic,1);
10386 /* shift count is unknown then we have to form
10387 a loop get the loop count in B : Note: we take
10388 only the lower order byte since shifting
10389 more that 32 bits make no sense anyway, ( the
10390 largest size of an object can be only 32 bits ) */
10392 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10393 //pic16_emitcode("inc","b");
10394 //pic16_freeAsmop (right,NULL,ic,TRUE);
10395 //pic16_aopOp(left,ic,FALSE);
10396 //pic16_aopOp(result,ic,FALSE);
10398 /* now move the left to the result if they are not the
10400 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10401 AOP_SIZE(result) > 1) {
10403 size = AOP_SIZE(result);
10407 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10408 if (*l == '@' && IS_AOP_PREG(result)) {
10410 pic16_emitcode("mov","a,%s",l);
10411 pic16_aopPut(AOP(result),"a",offset);
10413 pic16_aopPut(AOP(result),l,offset);
10415 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10416 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10422 /* mov the highest order bit to OVR */
10423 tlbl = newiTempLabel(NULL);
10424 tlbl1= newiTempLabel(NULL);
10426 size = AOP_SIZE(result);
10429 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10431 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10433 /* offset should be 0, 1 or 3 */
10434 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10436 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10438 pic16_emitpcode(POC_MOVWF, pctemp);
10441 pic16_emitpLabel(tlbl->key);
10443 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10444 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10447 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10450 pic16_emitpcode(POC_DECFSZ, pctemp);
10451 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10452 pic16_emitpLabel(tlbl1->key);
10454 pic16_popReleaseTempReg(pctemp,1);
10456 size = AOP_SIZE(result);
10458 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10459 pic16_emitcode("rlc","a");
10460 pic16_emitcode("mov","ov,c");
10461 /* if it is only one byte then */
10463 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10465 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10466 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10467 pic16_emitcode("mov","c,ov");
10468 pic16_emitcode("rrc","a");
10469 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10470 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10471 pic16_aopPut(AOP(result),"a",0);
10475 reAdjustPreg(AOP(result));
10476 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10477 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10478 pic16_emitcode("mov","c,ov");
10480 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10482 pic16_emitcode("rrc","a");
10483 pic16_aopPut(AOP(result),"a",offset--);
10485 reAdjustPreg(AOP(result));
10486 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10487 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10492 pic16_freeAsmop(left,NULL,ic,TRUE);
10493 pic16_freeAsmop(result,NULL,ic,TRUE);
10494 pic16_freeAsmop(right,NULL,ic,TRUE);
10498 #if !(USE_GENERIC_SIGNED_SHIFT)
10499 #warning This implementation of genRightShift() is incomplete!
10500 /*-----------------------------------------------------------------*/
10501 /* genRightShift - generate code for right shifting */
10502 /*-----------------------------------------------------------------*/
10503 static void genRightShift (iCode *ic)
10505 operand *right, *left, *result;
10509 symbol *tlbl, *tlbl1 ;
10511 /* if signed then we do it the hard way preserve the
10512 sign bit moving it inwards */
10513 letype = getSpec(operandType(IC_LEFT(ic)));
10514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10516 if (!SPEC_USIGN(letype)) {
10517 genSignedRightShift (ic);
10521 /* signed & unsigned types are treated the same : i.e. the
10522 signed is NOT propagated inwards : quoting from the
10523 ANSI - standard : "for E1 >> E2, is equivalent to division
10524 by 2**E2 if unsigned or if it has a non-negative value,
10525 otherwise the result is implementation defined ", MY definition
10526 is that the sign does not get propagated */
10528 right = IC_RIGHT(ic);
10529 left = IC_LEFT(ic);
10530 result = IC_RESULT(ic);
10532 pic16_aopOp(right,ic,FALSE);
10534 /* if the shift count is known then do it
10535 as efficiently as possible */
10536 if (AOP_TYPE(right) == AOP_LIT) {
10537 genRightShiftLiteral (left,right,result,ic, 0);
10541 /* shift count is unknown then we have to form
10542 a loop get the loop count in B : Note: we take
10543 only the lower order byte since shifting
10544 more that 32 bits make no sense anyway, ( the
10545 largest size of an object can be only 32 bits ) */
10547 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10548 pic16_emitcode("inc","b");
10549 pic16_aopOp(left,ic,FALSE);
10550 pic16_aopOp(result,ic,FALSE);
10552 /* now move the left to the result if they are not the
10554 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10555 AOP_SIZE(result) > 1) {
10557 size = AOP_SIZE(result);
10560 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10561 if (*l == '@' && IS_AOP_PREG(result)) {
10563 pic16_emitcode("mov","a,%s",l);
10564 pic16_aopPut(AOP(result),"a",offset);
10566 pic16_aopPut(AOP(result),l,offset);
10571 tlbl = newiTempLabel(NULL);
10572 tlbl1= newiTempLabel(NULL);
10573 size = AOP_SIZE(result);
10576 /* if it is only one byte then */
10579 tlbl = newiTempLabel(NULL);
10580 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10581 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10582 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10585 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10586 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10587 pic16_emitpLabel(tlbl->key);
10588 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10589 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10591 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10596 reAdjustPreg(AOP(result));
10597 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10598 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10601 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10603 pic16_emitcode("rrc","a");
10604 pic16_aopPut(AOP(result),"a",offset--);
10606 reAdjustPreg(AOP(result));
10608 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10609 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10612 pic16_freeAsmop(left,NULL,ic,TRUE);
10613 pic16_freeAsmop (right,NULL,ic,TRUE);
10614 pic16_freeAsmop(result,NULL,ic,TRUE);
10618 #if (USE_GENERIC_SIGNED_SHIFT)
10619 /*-----------------------------------------------------------------*/
10620 /* genGenericShift - generates code for left or right shifting */
10621 /*-----------------------------------------------------------------*/
10622 static void genGenericShift (iCode *ic, int isShiftLeft) {
10623 operand *left,*right, *result;
10625 int sign, signedCount;
10626 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10627 PIC_OPCODE pos_shift, neg_shift;
10631 right = IC_RIGHT(ic);
10632 left = IC_LEFT(ic);
10633 result = IC_RESULT(ic);
10635 pic16_aopOp(right,ic,FALSE);
10636 pic16_aopOp(left,ic,FALSE);
10637 pic16_aopOp(result,ic,TRUE);
10639 sign = !SPEC_USIGN(operandType (left));
10640 signedCount = !SPEC_USIGN(operandType (right));
10642 /* if the shift count is known then do it
10643 as efficiently as possible */
10644 if (AOP_TYPE(right) == AOP_LIT) {
10645 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10646 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10647 // we should modify right->aopu.aop_lit here!
10648 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10649 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10651 pic16_genLeftShiftLiteral (left,right,result,ic);
10653 genRightShiftLiteral (left,right,result,ic, sign);
10656 } // if (right is literal)
10658 /* shift count is unknown then we have to form a loop.
10659 * Note: we take only the lower order byte since shifting
10660 * more than 32 bits make no sense anyway, ( the
10661 * largest size of an object can be only 32 bits )
10662 * Note: we perform arithmetic shifts if the left operand is
10663 * signed and we do an (effective) right shift, i. e. we
10664 * shift in the sign bit from the left. */
10666 label_complete = newiTempLabel ( NULL );
10667 label_loop_pos = newiTempLabel ( NULL );
10668 label_loop_neg = NULL;
10669 label_negative = NULL;
10670 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10671 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10674 // additional labels needed
10675 label_loop_neg = newiTempLabel ( NULL );
10676 label_negative = newiTempLabel ( NULL );
10679 // copy source to result -- this will effectively truncate the left operand to the size of result!
10680 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10681 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10682 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10683 pic16_mov2f (AOP(result),AOP(left), offset);
10686 // if result is longer than left, fill with zeros (or sign)
10687 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10688 if (sign && AOP_SIZE(left) > 0) {
10689 // shift signed operand -- fill with sign
10690 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10691 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10692 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10693 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10694 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10697 // shift unsigned operand -- fill result with zeros
10698 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10699 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10702 } // if (size mismatch)
10704 pic16_mov2w (AOP(right), 0);
10705 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10706 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10709 // perform a shift by one (shift count is positive)
10710 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10711 // 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])
10712 pic16_emitpLabel (label_loop_pos->key);
10714 if (sign && (pos_shift == POC_RRCF)) {
10715 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10718 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10719 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10720 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10722 // perform a shift by one (shift count is positive)
10723 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10724 // 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])
10725 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10726 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10728 pic16_emitpLabel (label_loop_pos->key);
10729 if (sign && (pos_shift == POC_RRCF)) {
10730 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10733 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10734 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10735 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10736 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10740 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10742 pic16_emitpLabel (label_negative->key);
10743 // perform a shift by -1 (shift count is negative)
10744 // 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)
10746 pic16_emitpLabel (label_loop_neg->key);
10747 if (sign && (neg_shift == POC_RRCF)) {
10748 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10751 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10752 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10753 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10754 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10755 } // if (signedCount)
10757 pic16_emitpLabel (label_complete->key);
10760 pic16_freeAsmop (right,NULL,ic,TRUE);
10761 pic16_freeAsmop(left,NULL,ic,TRUE);
10762 pic16_freeAsmop(result,NULL,ic,TRUE);
10765 static void genLeftShift (iCode *ic) {
10766 genGenericShift (ic, 1);
10769 static void genRightShift (iCode *ic) {
10770 genGenericShift (ic, 0);
10775 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10776 void pic16_loadFSR0(operand *op, int lit)
10778 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10779 if (AOP_TYPE(op) == AOP_LIT) {
10780 /* handle 12 bit integers correctly */
10781 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10782 if ((val & 0x0fff) != val) {
10783 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10784 val, (val & 0x0fff) );
10787 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10789 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10792 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10793 // set up FSR0 with address of result
10794 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10795 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10799 /*----------------------------------------------------------------*/
10800 /* pic16_derefPtr - move one byte from the location ptr points to */
10801 /* to WREG (doWrite == 0) or one byte from WREG */
10802 /* to the location ptr points to (doWrite != 0) */
10803 /*----------------------------------------------------------------*/
10804 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10806 if (!IS_PTR(operandType(ptr)))
10808 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10809 else pic16_mov2w (AOP(ptr), 0);
10813 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10814 /* We might determine pointer type right here: */
10815 p_type = DCL_TYPE(operandType(ptr));
10820 if (!fsr0_setup || !*fsr0_setup)
10822 pic16_loadFSR0( ptr, 0 );
10823 if (fsr0_setup) *fsr0_setup = 1;
10826 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10828 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10832 if (AOP(ptr)->aopu.aop_reg[2]) {
10833 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10834 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10835 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10836 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10837 pic16_mov2w(AOP(ptr), 2);
10838 pic16_callGenericPointerRW(doWrite, 1);
10840 // data pointer (just 2 byte given)
10841 if (!fsr0_setup || !*fsr0_setup)
10843 pic16_loadFSR0( ptr, 0 );
10844 if (fsr0_setup) *fsr0_setup = 1;
10847 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10849 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10854 assert (0 && "invalid pointer type specified");
10859 /*-----------------------------------------------------------------*/
10860 /* genUnpackBits - generates code for unpacking bits */
10861 /*-----------------------------------------------------------------*/
10862 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10865 sym_link *etype, *letype;
10866 int blen=0, bstr=0;
10871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10872 etype = getSpec(operandType(result));
10873 letype = getSpec(operandType(left));
10875 // if(IS_BITFIELD(etype)) {
10876 blen = SPEC_BLEN(etype);
10877 bstr = SPEC_BSTR(etype);
10880 lbstr = SPEC_BSTR( letype );
10882 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10883 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10886 if((blen == 1) && (bstr < 8)
10887 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10888 /* it is a single bit, so use the appropriate bit instructions */
10889 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10891 same = pic16_sameRegs(AOP(left),AOP(result));
10892 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10893 pic16_emitpcode(POC_CLRF, op);
10895 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10896 /* workaround to reduce the extra lfsr instruction */
10897 pic16_emitpcode(POC_BTFSC,
10898 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10900 assert (PIC_IS_DATA_PTR (operandType(left)));
10901 pic16_loadFSR0 (left, 0);
10902 pic16_emitpcode(POC_BTFSC,
10903 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10906 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10907 /* unsigned bitfields result in either 0 or 1 */
10908 pic16_emitpcode(POC_INCF, op);
10910 /* signed bitfields result in either 0 or -1 */
10911 pic16_emitpcode(POC_DECF, op);
10914 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10917 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10923 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10924 // access symbol directly
10925 pic16_mov2w (AOP(left), 0);
10927 pic16_derefPtr (left, ptype, 0, NULL);
10930 /* if we have bitdisplacement then it fits */
10931 /* into this byte completely or if length is */
10932 /* less than a byte */
10933 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10935 /* shift right acc */
10938 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10939 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10941 /* VR -- normally I would use the following, but since we use the hack,
10942 * to avoid the masking from AccRsh, why not mask it right now? */
10945 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10948 /* extend signed bitfields to 8 bits */
10949 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10951 assert (blen + bstr > 0);
10952 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10953 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10958 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10962 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10963 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10964 exit(EXIT_FAILURE);
10970 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10972 int size, offset = 0, leoffset=0 ;
10974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10975 pic16_aopOp(result, ic, TRUE);
10979 size = AOP_SIZE(result);
10980 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10984 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10985 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10986 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10991 if(AOP(left)->aopu.pcop->type == PO_DIR)
10992 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10994 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10997 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10999 // pic16_DumpOp("(result)",result);
11000 if(is_LitAOp(AOP(result))) {
11001 pic16_mov2w(AOP(left), offset); // patch 8
11002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11004 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11005 pic16_popGet(AOP(left), offset), //patch 8
11006 pic16_popGet(AOP(result), offset)));
11014 pic16_freeAsmop(result,NULL,ic,TRUE);
11019 /*-----------------------------------------------------------------*/
11020 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11021 /*-----------------------------------------------------------------*/
11022 static void genNearPointerGet (operand *left,
11026 // asmop *aop = NULL;
11027 //regs *preg = NULL ;
11028 sym_link *rtype, *retype;
11029 sym_link *ltype, *letype;
11033 rtype = operandType(result);
11034 retype= getSpec(rtype);
11035 ltype = operandType(left);
11036 letype= getSpec(ltype);
11038 pic16_aopOp(left,ic,FALSE);
11040 // pic16_DumpOp("(left)",left);
11041 // pic16_DumpOp("(result)",result);
11043 /* if left is rematerialisable and
11044 * result is not bit variable type and
11045 * the left is pointer to data space i.e
11046 * lower 128 bytes of space */
11048 if (AOP_TYPE(left) == AOP_PCODE
11049 && !IS_BITFIELD(retype)
11050 && DCL_TYPE(ltype) == POINTER) {
11052 genDataPointerGet (left,result,ic);
11053 pic16_freeAsmop(left, NULL, ic, TRUE);
11057 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11058 pic16_aopOp (result,ic,TRUE);
11060 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11063 if(IS_BITFIELD( retype )
11064 && (SPEC_BLEN(operandType(result))==1)
11068 int bitstrt, bytestrt;
11070 /* if this is bitfield of size 1, see if we are checking the value
11071 * of a single bit in an if-statement,
11072 * if yes, then don't generate usual code, but execute the
11073 * genIfx directly -- VR */
11077 /* CHECK: if next iCode is IFX
11078 * and current result operand is nextic's conditional operand
11079 * and current result operand live ranges ends at nextic's key number
11081 if((nextic->op == IFX)
11082 && (result == IC_COND(nextic))
11083 && (OP_LIVETO(result) == nextic->seq)
11084 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11086 /* everything is ok then */
11087 /* find a way to optimize the genIfx iCode */
11089 bytestrt = SPEC_BSTR(operandType(result))/8;
11090 bitstrt = SPEC_BSTR(operandType(result))%8;
11092 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11094 genIfxpCOpJump(nextic, jop);
11096 pic16_freeAsmop(left, NULL, ic, TRUE);
11097 pic16_freeAsmop(result, NULL, ic, TRUE);
11103 /* if bitfield then unpack the bits */
11104 if (IS_BITFIELD(letype))
11105 genUnpackBits (result, left, NULL, POINTER);
11107 /* we have can just get the values */
11108 int size = AOP_SIZE(result);
11111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11113 pic16_loadFSR0( left, 0 );
11117 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11118 pic16_popGet(AOP(result), offset++)));
11120 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11121 pic16_popGet(AOP(result), offset++)));
11127 /* now some housekeeping stuff */
11129 /* we had to allocate for this iCode */
11130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11131 pic16_freeAsmop(NULL,aop,ic,TRUE);
11133 /* we did not allocate which means left
11134 * already in a pointer register, then
11135 * if size > 0 && this could be used again
11136 * we have to point it back to where it
11138 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11139 if (AOP_SIZE(result) > 1
11140 && !OP_SYMBOL(left)->remat
11141 && ( OP_SYMBOL(left)->liveTo > ic->seq
11143 // int size = AOP_SIZE(result) - 1;
11145 // pic16_emitcode("dec","%s",rname);
11151 pic16_freeAsmop(left,NULL,ic,TRUE);
11152 pic16_freeAsmop(result,NULL,ic,TRUE);
11155 /*-----------------------------------------------------------------*/
11156 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11157 /*-----------------------------------------------------------------*/
11158 static void genPagedPointerGet (operand *left,
11163 regs *preg = NULL ;
11165 sym_link *rtype, *retype;
11167 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11169 rtype = operandType(result);
11170 retype= getSpec(rtype);
11172 pic16_aopOp(left,ic,FALSE);
11174 /* if the value is already in a pointer register
11175 then don't need anything more */
11176 if (!AOP_INPREG(AOP(left))) {
11177 /* otherwise get a free pointer register */
11179 preg = getFreePtr(ic,&aop,FALSE);
11180 pic16_emitcode("mov","%s,%s",
11182 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11183 rname = preg->name ;
11185 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11187 pic16_freeAsmop(left,NULL,ic,TRUE);
11188 pic16_aopOp (result,ic,TRUE);
11190 /* if bitfield then unpack the bits */
11191 if (IS_BITFIELD(retype))
11192 genUnpackBits (result,left,rname,PPOINTER);
11194 /* we have can just get the values */
11195 int size = AOP_SIZE(result);
11200 pic16_emitcode("movx","a,@%s",rname);
11201 pic16_aopPut(AOP(result),"a",offset);
11206 pic16_emitcode("inc","%s",rname);
11210 /* now some housekeeping stuff */
11212 /* we had to allocate for this iCode */
11213 pic16_freeAsmop(NULL,aop,ic,TRUE);
11215 /* we did not allocate which means left
11216 already in a pointer register, then
11217 if size > 0 && this could be used again
11218 we have to point it back to where it
11220 if (AOP_SIZE(result) > 1 &&
11221 !OP_SYMBOL(left)->remat &&
11222 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11224 int size = AOP_SIZE(result) - 1;
11226 pic16_emitcode("dec","%s",rname);
11231 pic16_freeAsmop(result,NULL,ic,TRUE);
11237 /* This code is not adjusted to PIC16 and fails utterly.
11238 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11240 /*-----------------------------------------------------------------*/
11241 /* genFarPointerGet - gget value from far space */
11242 /*-----------------------------------------------------------------*/
11243 static void genFarPointerGet (operand *left,
11244 operand *result, iCode *ic)
11247 sym_link *retype = getSpec(operandType(result));
11249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11251 pic16_aopOp(left,ic,FALSE);
11253 /* if the operand is already in dptr
11254 then we do nothing else we move the value to dptr */
11255 if (AOP_TYPE(left) != AOP_STR) {
11256 /* if this is remateriazable */
11257 if (AOP_TYPE(left) == AOP_IMMD)
11258 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11259 else { /* we need to get it byte by byte */
11260 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11261 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11262 if (options.model == MODEL_FLAT24)
11264 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11268 /* so dptr know contains the address */
11269 pic16_freeAsmop(left,NULL,ic,TRUE);
11270 pic16_aopOp(result,ic,TRUE);
11272 /* if bit then unpack */
11273 if (IS_BITFIELD(retype))
11274 genUnpackBits(result,left,"dptr",FPOINTER);
11276 size = AOP_SIZE(result);
11280 pic16_emitcode("movx","a,@dptr");
11281 pic16_aopPut(AOP(result),"a",offset++);
11283 pic16_emitcode("inc","dptr");
11287 pic16_freeAsmop(result,NULL,ic,TRUE);
11292 /*-----------------------------------------------------------------*/
11293 /* genCodePointerGet - get value from code space */
11294 /*-----------------------------------------------------------------*/
11295 static void genCodePointerGet (operand *left,
11296 operand *result, iCode *ic)
11299 sym_link *retype = getSpec(operandType(result));
11301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11303 pic16_aopOp(left,ic,FALSE);
11305 /* if the operand is already in dptr
11306 then we do nothing else we move the value to dptr */
11307 if (AOP_TYPE(left) != AOP_STR) {
11308 /* if this is remateriazable */
11309 if (AOP_TYPE(left) == AOP_IMMD)
11310 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11311 else { /* we need to get it byte by byte */
11312 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11313 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11314 if (options.model == MODEL_FLAT24)
11316 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11320 /* so dptr know contains the address */
11321 pic16_freeAsmop(left,NULL,ic,TRUE);
11322 pic16_aopOp(result,ic,FALSE);
11324 /* if bit then unpack */
11325 if (IS_BITFIELD(retype))
11326 genUnpackBits(result,left,"dptr",CPOINTER);
11328 size = AOP_SIZE(result);
11332 pic16_emitcode("clr","a");
11333 pic16_emitcode("movc","a,@a+dptr");
11334 pic16_aopPut(AOP(result),"a",offset++);
11336 pic16_emitcode("inc","dptr");
11340 pic16_freeAsmop(result,NULL,ic,TRUE);
11345 /*-----------------------------------------------------------------*/
11346 /* genGenPointerGet - gget value from generic pointer space */
11347 /*-----------------------------------------------------------------*/
11348 static void genGenPointerGet (operand *left,
11349 operand *result, iCode *ic)
11351 int size, offset, lit;
11352 sym_link *retype = getSpec(operandType(result));
11354 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11355 pic16_aopOp(left,ic,FALSE);
11356 pic16_aopOp(result,ic,FALSE);
11357 size = AOP_SIZE(result);
11359 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11361 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11363 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11364 // load FSR0 from immediate
11365 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11367 // pic16_loadFSR0( left );
11372 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11374 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11381 else { /* we need to get it byte by byte */
11382 // set up FSR0 with address from left
11383 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11390 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11392 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11399 /* if bit then unpack */
11400 if (IS_BITFIELD(retype))
11401 genUnpackBits(result,left,"BAD",GPOINTER);
11404 pic16_freeAsmop(left,NULL,ic,TRUE);
11405 pic16_freeAsmop(result,NULL,ic,TRUE);
11411 /*-----------------------------------------------------------------*/
11412 /* genGenPointerGet - gget value from generic pointer space */
11413 /*-----------------------------------------------------------------*/
11414 static void genGenPointerGet (operand *left,
11415 operand *result, iCode *ic)
11417 int size, offset, lit;
11418 sym_link *letype = getSpec(operandType(left));
11420 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11421 pic16_aopOp(left,ic,FALSE);
11422 pic16_aopOp(result,ic,TRUE);
11423 size = AOP_SIZE(result);
11425 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11427 /* if bit then unpack */
11428 if (IS_BITFIELD(letype)) {
11429 genUnpackBits(result,left,"BAD",GPOINTER);
11433 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11435 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11436 // load FSR0 from immediate
11437 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11439 werror(W_POSSBUG2, __FILE__, __LINE__);
11444 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11446 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11453 } else { /* we need to get it byte by byte */
11455 /* set up WREG:PRODL:FSR0L with address from left */
11456 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11457 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11458 pic16_mov2w(AOP(left), 2);
11459 pic16_callGenericPointerRW(0, size);
11461 assignResultValue(result, size, 1);
11467 pic16_freeAsmop(left,NULL,ic,TRUE);
11468 pic16_freeAsmop(result,NULL,ic,TRUE);
11471 /*-----------------------------------------------------------------*/
11472 /* genConstPointerGet - get value from const generic pointer space */
11473 /*-----------------------------------------------------------------*/
11474 static void genConstPointerGet (operand *left,
11475 operand *result, iCode *ic)
11477 //sym_link *retype = getSpec(operandType(result));
11478 // symbol *albl = newiTempLabel(NULL); // patch 15
11479 // symbol *blbl = newiTempLabel(NULL); //
11480 // PIC_OPCODE poc; // patch 15
11484 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11485 pic16_aopOp(left,ic,FALSE);
11486 pic16_aopOp(result,ic,TRUE);
11487 size = AOP_SIZE(result);
11489 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11491 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11493 // set up table pointer
11494 if( (AOP_TYPE(left) == AOP_PCODE)
11495 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11496 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11498 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11499 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11500 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11501 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11502 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11503 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11505 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11506 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11507 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11511 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11512 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11516 pic16_freeAsmop(left,NULL,ic,TRUE);
11517 pic16_freeAsmop(result,NULL,ic,TRUE);
11521 /*-----------------------------------------------------------------*/
11522 /* genPointerGet - generate code for pointer get */
11523 /*-----------------------------------------------------------------*/
11524 static void genPointerGet (iCode *ic)
11526 operand *left, *result ;
11527 sym_link *type, *etype;
11532 left = IC_LEFT(ic);
11533 result = IC_RESULT(ic) ;
11535 /* depending on the type of pointer we need to
11536 move it to the correct pointer register */
11537 type = operandType(left);
11538 etype = getSpec(type);
11541 if (IS_PTR_CONST(type))
11543 if (IS_CODEPTR(type))
11545 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11547 /* if left is of type of pointer then it is simple */
11548 if (IS_PTR(type) && !IS_FUNC(type->next))
11549 p_type = DCL_TYPE(type);
11551 /* we have to go by the storage class */
11552 p_type = PTR_TYPE(SPEC_OCLS(etype));
11554 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11556 if (SPEC_OCLS(etype)->codesp ) {
11557 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11558 //p_type = CPOINTER ;
11560 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11561 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11562 /*p_type = FPOINTER ;*/
11564 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11565 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11566 /* p_type = PPOINTER; */
11568 if (SPEC_OCLS(etype) == idata ) {
11569 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11570 /* p_type = IPOINTER; */
11572 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11573 /* p_type = POINTER ; */
11577 /* now that we have the pointer type we assign
11578 the pointer values */
11583 genNearPointerGet (left,result,ic);
11587 genPagedPointerGet(left,result,ic);
11591 /* PICs do not support FAR pointers... */
11592 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11594 genFarPointerGet (left,result,ic);
11599 genConstPointerGet (left,result,ic);
11600 //pic16_emitcodePointerGet (left,result,ic);
11605 if (IS_PTR_CONST(type))
11606 genConstPointerGet (left,result,ic);
11609 genGenPointerGet (left,result,ic);
11613 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11614 "genPointerGet: illegal pointer type");
11619 /*-----------------------------------------------------------------*/
11620 /* genPackBits - generates code for packed bit storage */
11621 /*-----------------------------------------------------------------*/
11622 static void genPackBits (sym_link *etype , operand *result,
11624 char *rname, int p_type)
11630 int shifted_and_masked = 0;
11631 unsigned long lit = (unsigned long)-1;
11634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11635 blen = SPEC_BLEN(etype);
11636 bstr = SPEC_BSTR(etype);
11638 retype = getSpec(operandType(right));
11640 if(AOP_TYPE(right) == AOP_LIT) {
11641 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11643 if((blen == 1) && (bstr < 8)) {
11644 /* it is a single bit, so use the appropriate bit instructions */
11646 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11648 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11649 /* workaround to reduce the extra lfsr instruction */
11651 pic16_emitpcode(POC_BSF,
11652 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11654 pic16_emitpcode(POC_BCF,
11655 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11658 if (PIC_IS_DATA_PTR(operandType(result))) {
11659 pic16_loadFSR0(result, 0);
11660 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11661 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11663 /* get old value */
11664 pic16_derefPtr (result, p_type, 0, NULL);
11665 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11666 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11667 /* write back new value */
11668 pic16_derefPtr (result, p_type, 1, NULL);
11674 /* IORLW below is more efficient */
11675 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11676 lit = (lit & ((1UL << blen) - 1)) << bstr;
11677 shifted_and_masked = 1;
11680 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11681 && IS_BITFIELD(retype)
11682 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11686 rblen = SPEC_BLEN( retype );
11687 rbstr = SPEC_BSTR( retype );
11689 if(IS_BITFIELD(etype)) {
11690 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11691 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11693 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11696 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11698 if(IS_BITFIELD(etype)) {
11699 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11701 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11704 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11708 /* move right to W */
11709 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11712 /* if the bit length is less than or */
11713 /* it exactly fits a byte then */
11714 if((shCnt=SPEC_BSTR(etype))
11715 || SPEC_BLEN(etype) <= 8 ) {
11716 int fsr0_setup = 0;
11718 if (blen != 8 || bstr != 0) {
11719 // we need to combine the value with the old value
11720 if(!shifted_and_masked)
11722 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11724 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11725 SPEC_BSTR(etype), SPEC_BLEN(etype));
11727 /* shift left acc, do NOT mask the result again */
11730 /* using PRODH as a temporary register here */
11731 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11734 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11735 || IS_DIRECT(result)) {
11736 /* access symbol directly */
11737 pic16_mov2w (AOP(result), 0);
11739 /* get old value */
11740 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11743 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11744 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11745 (unsigned char)(0xff >> (8-bstr))) ));
11746 if (!shifted_and_masked) {
11747 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11749 /* We have the shifted and masked (literal) right value in `lit' */
11751 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11753 } // if (blen != 8 || bstr != 0)
11755 /* write new value back */
11756 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11757 || IS_DIRECT(result)) {
11758 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11760 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11769 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11770 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11771 exit(EXIT_FAILURE);
11775 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11776 rLen = SPEC_BLEN(etype)-8;
11778 /* now generate for lengths greater than one byte */
11782 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11788 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11794 pic16_emitcode("movx","@dptr,a");
11799 DEBUGpic16_emitcode(";lcall","__gptrput");
11807 pic16_mov2w(AOP(right), offset++);
11810 /* last last was not complete */
11812 /* save the byte & read byte */
11815 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11816 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11821 pic16_emitcode ("mov","b,a");
11822 pic16_emitcode("movx","a,@dptr");
11826 pic16_emitcode ("push","b");
11827 pic16_emitcode ("push","acc");
11828 pic16_emitcode ("lcall","__gptrget");
11829 pic16_emitcode ("pop","b");
11835 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11836 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11837 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11838 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11839 // pic16_emitcode ("orl","a,b");
11842 // if (p_type == GPOINTER)
11843 // pic16_emitcode("pop","b");
11848 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11849 // pic16_emitcode("mov","@%s,a",rname);
11853 pic16_emitcode("movx","@dptr,a");
11857 DEBUGpic16_emitcode(";lcall","__gptrput");
11864 // pic16_freeAsmop(right, NULL, ic, TRUE);
11867 /*-----------------------------------------------------------------*/
11868 /* genDataPointerSet - remat pointer to data space */
11869 /*-----------------------------------------------------------------*/
11870 static void genDataPointerSet(operand *right,
11874 int size, offset = 0, resoffset=0 ;
11876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11877 pic16_aopOp(right,ic,FALSE);
11879 size = AOP_SIZE(right);
11881 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11884 if ( AOP_TYPE(result) == AOP_PCODE) {
11885 fprintf(stderr,"genDataPointerSet %s, %d\n",
11886 AOP(result)->aopu.pcop->name,
11887 (AOP(result)->aopu.pcop->type == PO_DIR)?
11888 PCOR(AOP(result)->aopu.pcop)->instance:
11889 PCOI(AOP(result)->aopu.pcop)->offset);
11893 if(AOP(result)->aopu.pcop->type == PO_DIR)
11894 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11897 if (AOP_TYPE(right) == AOP_LIT) {
11898 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11899 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11901 pic16_mov2w(AOP(right), offset);
11902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11908 pic16_freeAsmop(right,NULL,ic,TRUE);
11913 /*-----------------------------------------------------------------*/
11914 /* genNearPointerSet - pic16_emitcode for near pointer put */
11915 /*-----------------------------------------------------------------*/
11916 static void genNearPointerSet (operand *right,
11922 sym_link *ptype = operandType(result);
11923 sym_link *resetype;
11925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11926 retype= getSpec(operandType(right));
11927 resetype = getSpec(operandType(result));
11929 pic16_aopOp(result,ic,FALSE);
11931 /* if the result is rematerializable &
11932 * in data space & not a bit variable */
11934 /* and result is not a bit variable */
11935 if (AOP_TYPE(result) == AOP_PCODE
11936 // && AOP_TYPE(result) == AOP_IMMD
11937 && DCL_TYPE(ptype) == POINTER
11938 && !IS_BITFIELD(retype)
11939 && !IS_BITFIELD(resetype)) {
11941 genDataPointerSet (right,result,ic);
11942 pic16_freeAsmop(result,NULL,ic,TRUE);
11946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11947 pic16_aopOp(right,ic,FALSE);
11948 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11950 /* if bitfield then unpack the bits */
11951 if (IS_BITFIELD(resetype)) {
11952 genPackBits (resetype, result, right, NULL, POINTER);
11954 /* we have can just get the values */
11955 int size = AOP_SIZE(right);
11958 pic16_loadFSR0(result, 0);
11960 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11962 if (AOP_TYPE(right) == AOP_LIT) {
11963 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11965 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11967 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11969 } else { // no literal
11971 pic16_emitpcode(POC_MOVFF,
11972 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11973 pic16_popCopyReg(&pic16_pc_postinc0)));
11975 pic16_emitpcode(POC_MOVFF,
11976 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11977 pic16_popCopyReg(&pic16_pc_indf0)));
11985 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11986 /* now some housekeeping stuff */
11988 /* we had to allocate for this iCode */
11989 pic16_freeAsmop(NULL,aop,ic,TRUE);
11991 /* we did not allocate which means left
11992 * already in a pointer register, then
11993 * if size > 0 && this could be used again
11994 * we have to point it back to where it
11996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11997 if (AOP_SIZE(right) > 1
11998 && !OP_SYMBOL(result)->remat
11999 && ( OP_SYMBOL(result)->liveTo > ic->seq
12002 int size = AOP_SIZE(right) - 1;
12005 pic16_emitcode("decf","fsr0,f");
12006 //pic16_emitcode("dec","%s",rname);
12010 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12013 pic16_freeAsmop(right,NULL,ic,TRUE);
12014 pic16_freeAsmop(result,NULL,ic,TRUE);
12017 /*-----------------------------------------------------------------*/
12018 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12019 /*-----------------------------------------------------------------*/
12020 static void genPagedPointerSet (operand *right,
12025 regs *preg = NULL ;
12029 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12031 retype= getSpec(operandType(right));
12033 pic16_aopOp(result,ic,FALSE);
12035 /* if the value is already in a pointer register
12036 then don't need anything more */
12037 if (!AOP_INPREG(AOP(result))) {
12038 /* otherwise get a free pointer register */
12040 preg = getFreePtr(ic,&aop,FALSE);
12041 pic16_emitcode("mov","%s,%s",
12043 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12044 rname = preg->name ;
12046 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12048 pic16_freeAsmop(result,NULL,ic,TRUE);
12049 pic16_aopOp (right,ic,FALSE);
12051 /* if bitfield then unpack the bits */
12052 if (IS_BITFIELD(retype))
12053 genPackBits (retype,result,right,rname,PPOINTER);
12055 /* we have can just get the values */
12056 int size = AOP_SIZE(right);
12060 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12063 pic16_emitcode("movx","@%s,a",rname);
12066 pic16_emitcode("inc","%s",rname);
12072 /* now some housekeeping stuff */
12074 /* we had to allocate for this iCode */
12075 pic16_freeAsmop(NULL,aop,ic,TRUE);
12077 /* we did not allocate which means left
12078 already in a pointer register, then
12079 if size > 0 && this could be used again
12080 we have to point it back to where it
12082 if (AOP_SIZE(right) > 1 &&
12083 !OP_SYMBOL(result)->remat &&
12084 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12086 int size = AOP_SIZE(right) - 1;
12088 pic16_emitcode("dec","%s",rname);
12093 pic16_freeAsmop(right,NULL,ic,TRUE);
12099 /* This code is not adjusted to PIC16 and fails utterly...
12100 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12102 /*-----------------------------------------------------------------*/
12103 /* genFarPointerSet - set value from far space */
12104 /*-----------------------------------------------------------------*/
12105 static void genFarPointerSet (operand *right,
12106 operand *result, iCode *ic)
12109 sym_link *retype = getSpec(operandType(right));
12111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12112 pic16_aopOp(result,ic,FALSE);
12114 /* if the operand is already in dptr
12115 then we do nothing else we move the value to dptr */
12116 if (AOP_TYPE(result) != AOP_STR) {
12117 /* if this is remateriazable */
12118 if (AOP_TYPE(result) == AOP_IMMD)
12119 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12120 else { /* we need to get it byte by byte */
12121 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12122 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12123 if (options.model == MODEL_FLAT24)
12125 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12129 /* so dptr know contains the address */
12130 pic16_freeAsmop(result,NULL,ic,TRUE);
12131 pic16_aopOp(right,ic,FALSE);
12133 /* if bit then unpack */
12134 if (IS_BITFIELD(retype))
12135 genPackBits(retype,result,right,"dptr",FPOINTER);
12137 size = AOP_SIZE(right);
12141 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12143 pic16_emitcode("movx","@dptr,a");
12145 pic16_emitcode("inc","dptr");
12149 pic16_freeAsmop(right,NULL,ic,TRUE);
12153 /*-----------------------------------------------------------------*/
12154 /* genGenPointerSet - set value from generic pointer space */
12155 /*-----------------------------------------------------------------*/
12157 static void genGenPointerSet (operand *right,
12158 operand *result, iCode *ic)
12160 int i, size, offset, lit;
12161 sym_link *retype = getSpec(operandType(right));
12163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12165 pic16_aopOp(result,ic,FALSE);
12166 pic16_aopOp(right,ic,FALSE);
12167 size = AOP_SIZE(right);
12170 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12172 /* if the operand is already in dptr
12173 then we do nothing else we move the value to dptr */
12174 if (AOP_TYPE(result) != AOP_STR) {
12175 /* if this is remateriazable */
12176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12177 // WARNING: anythig until "else" is untested!
12178 if (AOP_TYPE(result) == AOP_IMMD) {
12179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12180 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12181 // load FSR0 from immediate
12182 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12186 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12188 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12194 else { /* we need to get it byte by byte */
12195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12196 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12198 // set up FSR0 with address of result
12199 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12200 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12202 /* hack hack! see if this the FSR. If so don't load W */
12203 if(AOP_TYPE(right) != AOP_ACC) {
12205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12207 if(AOP_TYPE(right) == AOP_LIT)
12210 // note: pic16_popGet handles sign extension
12211 for(i=0;i<size;i++) {
12212 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12214 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12216 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12221 for(i=0;i<size;i++) {
12223 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12224 pic16_popCopyReg(&pic16_pc_postinc0)));
12226 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12227 pic16_popCopyReg(&pic16_pc_indf0)));
12233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12234 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12236 } // if (AOP_TYPE(result) != AOP_IMMD)
12238 } // if (AOP_TYPE(result) != AOP_STR)
12239 /* so dptr know contains the address */
12242 /* if bit then unpack */
12243 if (IS_BITFIELD(retype))
12244 genPackBits(retype,result,right,"dptr",GPOINTER);
12246 size = AOP_SIZE(right);
12249 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12251 // set up FSR0 with address of result
12252 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12253 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12256 if (AOP_TYPE(right) == AOP_LIT) {
12257 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12261 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12263 } else { // no literal
12265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12267 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12275 pic16_freeAsmop(right,NULL,ic,TRUE);
12276 pic16_freeAsmop(result,NULL,ic,TRUE);
12280 static void genGenPointerSet (operand *right,
12281 operand *result, iCode *ic)
12284 sym_link *retype = getSpec(operandType(result));
12286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12288 pic16_aopOp(result,ic,FALSE);
12289 pic16_aopOp(right,ic,FALSE);
12290 size = AOP_SIZE(right);
12292 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12295 /* if bit then unpack */
12296 if (IS_BITFIELD(retype)) {
12297 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12298 genPackBits(retype,result,right,"dptr",GPOINTER);
12302 size = AOP_SIZE(right);
12304 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12307 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12309 /* value of right+0 is placed on stack, which will be retrieved
12310 * by the support function thus restoring the stack. The important
12311 * thing is that there is no need to manually restore stack pointer
12313 pushaop(AOP(right), 0);
12314 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12315 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12316 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12317 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12319 /* load address to write to in WREG:FSR0H:FSR0L */
12320 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12321 pic16_popCopyReg(&pic16_pc_fsr0l)));
12322 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12323 pic16_popCopyReg(&pic16_pc_prodl)));
12324 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12326 pic16_callGenericPointerRW(1, size);
12329 pic16_freeAsmop(right,NULL,ic,TRUE);
12330 pic16_freeAsmop(result,NULL,ic,TRUE);
12333 /*-----------------------------------------------------------------*/
12334 /* genPointerSet - stores the value into a pointer location */
12335 /*-----------------------------------------------------------------*/
12336 static void genPointerSet (iCode *ic)
12338 operand *right, *result ;
12339 sym_link *type, *etype;
12344 right = IC_RIGHT(ic);
12345 result = IC_RESULT(ic) ;
12347 /* depending on the type of pointer we need to
12348 move it to the correct pointer register */
12349 type = operandType(result);
12350 etype = getSpec(type);
12352 /* if left is of type of pointer then it is simple */
12353 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12354 p_type = DCL_TYPE(type);
12357 /* we have to go by the storage class */
12358 p_type = PTR_TYPE(SPEC_OCLS(etype));
12360 /* if (SPEC_OCLS(etype)->codesp ) { */
12361 /* p_type = CPOINTER ; */
12364 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12365 /* p_type = FPOINTER ; */
12367 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12368 /* p_type = PPOINTER ; */
12370 /* if (SPEC_OCLS(etype) == idata ) */
12371 /* p_type = IPOINTER ; */
12373 /* p_type = POINTER ; */
12376 /* now that we have the pointer type we assign
12377 the pointer values */
12382 genNearPointerSet (right,result,ic);
12386 genPagedPointerSet (right,result,ic);
12390 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12392 genFarPointerSet (right,result,ic);
12397 genGenPointerSet (right,result,ic);
12401 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12402 "genPointerSet: illegal pointer type");
12406 /*-----------------------------------------------------------------*/
12407 /* genIfx - generate code for Ifx statement */
12408 /*-----------------------------------------------------------------*/
12409 static void genIfx (iCode *ic, iCode *popIc)
12411 operand *cond = IC_COND(ic);
12416 pic16_aopOp(cond,ic,FALSE);
12418 /* get the value into acc */
12419 if (AOP_TYPE(cond) != AOP_CRY)
12420 pic16_toBoolean(cond);
12423 /* the result is now in the accumulator */
12424 pic16_freeAsmop(cond,NULL,ic,TRUE);
12426 /* if there was something to be popped then do it */
12430 /* if the condition is a bit variable */
12431 if (isbit && IS_ITEMP(cond) &&
12433 genIfxJump(ic,"c");
12434 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12436 if (isbit && !IS_ITEMP(cond))
12437 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12439 genIfxJump(ic,"a");
12444 /*-----------------------------------------------------------------*/
12445 /* genAddrOf - generates code for address of */
12446 /*-----------------------------------------------------------------*/
12447 static void genAddrOf (iCode *ic)
12449 operand *result, *left;
12451 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12452 pCodeOp *pcop0, *pcop1, *pcop2;
12456 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12458 sym = OP_SYMBOL( IC_LEFT(ic) );
12461 /* get address of symbol on stack */
12462 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12464 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12465 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12468 // operands on stack are accessible via "FSR2 + index" with index
12469 // starting at 2 for arguments and growing from 0 downwards for
12470 // local variables (index == 0 is not assigned so we add one here)
12472 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12475 assert (soffs < 0);
12479 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12480 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12481 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12482 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12483 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12484 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12485 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12491 // if(pic16_debug_verbose) {
12492 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12493 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12496 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12497 size = AOP_SIZE(IC_RESULT(ic));
12499 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12500 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12501 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12504 pic16_emitpcode(POC_MOVLW, pcop0);
12505 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12506 pic16_emitpcode(POC_MOVLW, pcop1);
12507 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12508 pic16_emitpcode(POC_MOVLW, pcop2);
12509 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12512 pic16_emitpcode(POC_MOVLW, pcop0);
12513 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12514 pic16_emitpcode(POC_MOVLW, pcop1);
12515 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12517 pic16_emitpcode(POC_MOVLW, pcop0);
12518 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12521 pic16_freeAsmop(left, NULL, ic, FALSE);
12523 pic16_freeAsmop(result,NULL,ic,TRUE);
12528 /*-----------------------------------------------------------------*/
12529 /* genFarFarAssign - assignment when both are in far space */
12530 /*-----------------------------------------------------------------*/
12531 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12533 int size = AOP_SIZE(right);
12536 /* first push the right side on to the stack */
12538 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12540 pic16_emitcode ("push","acc");
12543 pic16_freeAsmop(right,NULL,ic,FALSE);
12544 /* now assign DPTR to result */
12545 pic16_aopOp(result,ic,FALSE);
12546 size = AOP_SIZE(result);
12548 pic16_emitcode ("pop","acc");
12549 pic16_aopPut(AOP(result),"a",--offset);
12551 pic16_freeAsmop(result,NULL,ic,FALSE);
12556 /*-----------------------------------------------------------------*/
12557 /* genAssign - generate code for assignment */
12558 /*-----------------------------------------------------------------*/
12559 static void genAssign (iCode *ic)
12561 operand *result, *right;
12562 sym_link *restype, *rtype;
12563 int size, offset,know_W;
12564 unsigned long lit = 0L;
12566 result = IC_RESULT(ic);
12567 right = IC_RIGHT(ic) ;
12571 /* if they are the same */
12572 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12575 /* reversed order operands are aopOp'ed so that result operand
12576 * is effective in case right is a stack symbol. This maneauver
12577 * allows to use the _G.resDirect flag later */
12578 pic16_aopOp(result,ic,TRUE);
12579 pic16_aopOp(right,ic,FALSE);
12581 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12583 /* if they are the same registers */
12584 if (pic16_sameRegs(AOP(right),AOP(result)))
12587 /* if the result is a bit */
12588 if (AOP_TYPE(result) == AOP_CRY) {
12589 /* if the right size is a literal then
12590 we know what the value is */
12591 if (AOP_TYPE(right) == AOP_LIT) {
12593 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12594 pic16_popGet(AOP(result),0));
12596 if (((int) operandLitValue(right)))
12597 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12598 AOP(result)->aopu.aop_dir,
12599 AOP(result)->aopu.aop_dir);
12601 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12602 AOP(result)->aopu.aop_dir,
12603 AOP(result)->aopu.aop_dir);
12608 /* the right is also a bit variable */
12609 if (AOP_TYPE(right) == AOP_CRY) {
12610 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12611 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12612 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12617 /* we need to or */
12618 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12619 pic16_toBoolean(right);
12621 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12622 //pic16_aopPut(AOP(result),"a",0);
12626 /* bit variables done */
12628 size = AOP_SIZE(result);
12631 /* bit variables done */
12633 size = AOP_SIZE(result);
12634 restype = operandType(result);
12635 rtype = operandType(right);
12638 if(AOP_TYPE(right) == AOP_LIT) {
12639 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12641 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12643 /* patch tag for literals that are cast to pointers */
12644 if (IS_CODEPTR(restype)) {
12645 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12646 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12648 if (IS_GENPTR(restype))
12650 if (IS_CODEPTR(rtype)) {
12651 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12652 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12653 } else if (PIC_IS_DATA_PTR(rtype)) {
12654 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12655 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12656 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12657 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12658 } else if (IS_PTR(rtype)) {
12659 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12660 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12666 unsigned long lit_int;
12671 if(IS_FIXED16X16(operandType(right))) {
12672 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12674 /* take care if literal is a float */
12675 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12676 lit = info.lit_int;
12681 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12682 // sizeof(unsigned long int), sizeof(float));
12685 if (AOP_TYPE(right) == AOP_REG) {
12686 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12688 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12693 /* when do we have to read the program memory?
12694 * - if right itself is a symbol in code space
12695 * (we don't care what it points to if it's a pointer)
12696 * - AND right is not a function (we would want its address)
12698 if(AOP_TYPE(right) != AOP_LIT
12699 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12700 && !IS_FUNC(OP_SYM_TYPE(right))
12701 && !IS_ITEMP(right)) {
12703 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12704 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12706 // set up table pointer
12707 if(is_LitOp(right)) {
12708 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12709 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12710 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12711 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12712 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12713 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12714 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12716 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12717 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12718 pic16_popCopyReg(&pic16_pc_tblptrl)));
12719 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12720 pic16_popCopyReg(&pic16_pc_tblptrh)));
12721 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12722 pic16_popCopyReg(&pic16_pc_tblptru)));
12725 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12726 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12728 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12729 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12730 pic16_popGet(AOP(result),offset)));
12734 /* FIXME: for pointers we need to extend differently (according
12735 * to pointer type DATA/CODE/EEPROM/... :*/
12736 size = getSize(OP_SYM_TYPE(right));
12737 if(AOP_SIZE(result) > size) {
12738 size = AOP_SIZE(result) - size;
12740 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12748 /* VR - What is this?! */
12749 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12752 if(aopIdx(AOP(result),0) == 4) {
12753 /* this is a workaround to save value of right into wreg too,
12754 * value of wreg is going to be used later */
12755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12756 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12761 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12765 size = AOP_SIZE(right);
12766 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12769 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12770 if(AOP_TYPE(right) == AOP_LIT) {
12772 if(know_W != (lit&0xff))
12773 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12777 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12781 } else if (AOP_TYPE(right) == AOP_CRY) {
12782 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12784 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12785 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12786 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12788 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12789 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12794 if(!_G.resDirect) { /* use this aopForSym feature */
12795 if(AOP_TYPE(result) == AOP_ACC) {
12796 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12798 if(AOP_TYPE(right) == AOP_ACC) {
12799 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12801 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12808 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12811 pic16_freeAsmop (right,NULL,ic,FALSE);
12812 pic16_freeAsmop (result,NULL,ic,TRUE);
12815 /*-----------------------------------------------------------------*/
12816 /* genJumpTab - generates code for jump table */
12817 /*-----------------------------------------------------------------*/
12818 static void genJumpTab (iCode *ic)
12823 pCodeOp *jt_offs_hi;
12828 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12829 /* get the condition into accumulator */
12830 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12832 /* multiply by three */
12833 pic16_emitcode("add","a,acc");
12834 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12836 jtab = newiTempLabel(NULL);
12837 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12838 pic16_emitcode("jmp","@a+dptr");
12839 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12842 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12843 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12845 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12846 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12847 pic16_emitpLabel(jtab->key);
12851 jt_offs = pic16_popGetTempReg(0);
12852 jt_offs_hi = pic16_popGetTempReg(1);
12853 jt_label = pic16_popGetLabel (jtab->key);
12854 //fprintf (stderr, "Creating jump table...\n");
12856 // calculate offset into jump table (idx * sizeof (GOTO))
12857 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12858 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12859 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12860 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12861 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12862 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12863 pic16_emitpcode(POC_MOVWF , jt_offs);
12865 // prepare PCLATx (set to first entry in jump table)
12866 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12867 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12868 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12869 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12870 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12872 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12873 pic16_emitpcode(POC_ADDWF , jt_offs);
12874 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12875 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12877 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12879 // release temporaries and prepare jump into table (new PCL --> WREG)
12880 pic16_emitpcode(POC_MOVFW , jt_offs);
12881 pic16_popReleaseTempReg (jt_offs_hi, 1);
12882 pic16_popReleaseTempReg (jt_offs, 0);
12884 // jump into the table
12885 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12887 pic16_emitpLabelFORCE(jtab->key);
12890 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12891 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12893 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12894 /* now generate the jump labels */
12895 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12896 jtab = setNextItem(IC_JTLABELS(ic))) {
12897 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12901 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12905 /*-----------------------------------------------------------------*/
12906 /* genMixedOperation - gen code for operators between mixed types */
12907 /*-----------------------------------------------------------------*/
12909 TSD - Written for the PIC port - but this unfortunately is buggy.
12910 This routine is good in that it is able to efficiently promote
12911 types to different (larger) sizes. Unfortunately, the temporary
12912 variables that are optimized out by this routine are sometimes
12913 used in other places. So until I know how to really parse the
12914 iCode tree, I'm going to not be using this routine :(.
12916 static int genMixedOperation (iCode *ic)
12919 operand *result = IC_RESULT(ic);
12920 sym_link *ctype = operandType(IC_LEFT(ic));
12921 operand *right = IC_RIGHT(ic);
12927 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12929 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12935 nextright = IC_RIGHT(nextic);
12936 nextleft = IC_LEFT(nextic);
12937 nextresult = IC_RESULT(nextic);
12939 pic16_aopOp(right,ic,FALSE);
12940 pic16_aopOp(result,ic,FALSE);
12941 pic16_aopOp(nextright, nextic, FALSE);
12942 pic16_aopOp(nextleft, nextic, FALSE);
12943 pic16_aopOp(nextresult, nextic, FALSE);
12945 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12947 operand *t = right;
12951 pic16_emitcode(";remove right +","");
12953 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12955 operand *t = right;
12959 pic16_emitcode(";remove left +","");
12963 big = AOP_SIZE(nextleft);
12964 small = AOP_SIZE(nextright);
12966 switch(nextic->op) {
12969 pic16_emitcode(";optimize a +","");
12970 /* if unsigned or not an integral type */
12971 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12972 pic16_emitcode(";add a bit to something","");
12975 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12977 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12978 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12979 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12981 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12989 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12990 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12991 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12994 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12996 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12997 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12998 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12999 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13000 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13003 pic16_emitcode("rlf","known_zero,w");
13010 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13011 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13012 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13014 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13024 pic16_freeAsmop(right,NULL,ic,TRUE);
13025 pic16_freeAsmop(result,NULL,ic,TRUE);
13026 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13027 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13029 nextic->generated = 1;
13036 /*-----------------------------------------------------------------*/
13037 /* genCast - gen code for casting */
13038 /*-----------------------------------------------------------------*/
13039 static void genCast (iCode *ic)
13041 operand *result = IC_RESULT(ic);
13042 sym_link *ctype = operandType(IC_LEFT(ic));
13043 sym_link *rtype = operandType(IC_RIGHT(ic));
13044 sym_link *restype = operandType(IC_RESULT(ic));
13045 operand *right = IC_RIGHT(ic);
13051 /* if they are equivalent then do nothing */
13052 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13055 pic16_aopOp(result,ic,FALSE);
13056 pic16_aopOp(right,ic,FALSE) ;
13058 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13061 /* if the result is a bit */
13062 if (AOP_TYPE(result) == AOP_CRY) {
13064 /* if the right size is a literal then
13065 * we know what the value is */
13066 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13068 if (AOP_TYPE(right) == AOP_LIT) {
13069 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13070 pic16_popGet(AOP(result),0));
13072 if (((int) operandLitValue(right)))
13073 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13074 AOP(result)->aopu.aop_dir,
13075 AOP(result)->aopu.aop_dir);
13077 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13078 AOP(result)->aopu.aop_dir,
13079 AOP(result)->aopu.aop_dir);
13083 /* the right is also a bit variable */
13084 if (AOP_TYPE(right) == AOP_CRY) {
13086 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13088 pic16_emitcode("clrc","");
13089 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13090 AOP(right)->aopu.aop_dir,
13091 AOP(right)->aopu.aop_dir);
13092 pic16_aopPut(AOP(result),"c",0);
13096 /* we need to or */
13097 if (AOP_TYPE(right) == AOP_REG) {
13098 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13099 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13100 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13102 pic16_toBoolean(right);
13103 pic16_aopPut(AOP(result),"a",0);
13107 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13110 size = AOP_SIZE(result);
13112 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13114 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13115 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13116 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13119 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13124 if(IS_BITFIELD(getSpec(restype))
13125 && IS_BITFIELD(getSpec(rtype))) {
13126 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13129 /* port from pic14 to cope with generic pointers */
13130 if (PIC_IS_TAGGED(restype))
13132 operand *result = IC_RESULT(ic);
13133 //operand *left = IC_LEFT(ic);
13134 operand *right = IC_RIGHT(ic);
13137 /* copy common part */
13138 int max, size = AOP_SIZE(result);
13139 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13140 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13145 pic16_mov2w (AOP(right), size);
13146 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13149 /* upcast into generic pointer type? */
13150 if (IS_GENPTR(restype)
13151 && !PIC_IS_TAGGED(rtype)
13152 && (AOP_SIZE(result) > max))
13154 /* determine appropriate tag for right */
13155 if (PIC_IS_DATA_PTR(rtype))
13156 tag = GPTR_TAG_DATA;
13157 else if (IS_CODEPTR(rtype))
13158 tag = GPTR_TAG_CODE;
13159 else if (PIC_IS_DATA_PTR(ctype)) {
13160 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13161 tag = GPTR_TAG_DATA;
13162 } else if (IS_CODEPTR(ctype)) {
13163 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13164 tag = GPTR_TAG_CODE;
13165 } else if (IS_PTR(rtype)) {
13166 PERFORM_ONCE(weirdcast,
13167 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13169 tag = GPTR_TAG_DATA;
13171 PERFORM_ONCE(weirdcast,
13172 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13174 tag = GPTR_TAG_DATA;
13177 assert (AOP_SIZE(result) == 3);
13178 /* zero-extend address... */
13179 for (size = max; size < AOP_SIZE(result)-1; size++)
13180 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13181 /* ...and add tag */
13182 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13183 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13184 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13185 for (size = max; size < AOP_SIZE(result)-1; size++)
13186 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13187 /* add __code tag */
13188 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13189 } else if (AOP_SIZE(result) > max) {
13190 /* extend non-pointers */
13191 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13192 pic16_addSign(result, max, 0);
13197 /* if they are the same size : or less */
13198 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13200 /* if they are in the same place */
13201 if (pic16_sameRegs(AOP(right),AOP(result)))
13204 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13206 if (IS_PTR_CONST(rtype))
13208 if (IS_CODEPTR(rtype))
13210 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13213 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13215 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13217 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13220 if(AOP_TYPE(right) == AOP_IMMD) {
13221 pCodeOp *pcop0, *pcop1, *pcop2;
13222 symbol *sym = OP_SYMBOL( right );
13224 size = AOP_SIZE(result);
13226 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13228 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13230 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13233 pic16_emitpcode(POC_MOVLW, pcop0);
13234 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13235 pic16_emitpcode(POC_MOVLW, pcop1);
13236 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13237 pic16_emitpcode(POC_MOVLW, pcop2);
13238 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13241 pic16_emitpcode(POC_MOVLW, pcop0);
13242 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13243 pic16_emitpcode(POC_MOVLW, pcop1);
13244 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13246 pic16_emitpcode(POC_MOVLW, pcop0);
13247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13251 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13252 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13255 if(AOP_SIZE(result) < 2) {
13256 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13258 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13262 /* if they in different places then copy */
13263 size = AOP_SIZE(result);
13266 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13267 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13274 /* if the result is of type pointer */
13275 if (IS_PTR(ctype)) {
13277 sym_link *type = operandType(right);
13278 sym_link *etype = getSpec(type);
13280 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13282 /* pointer to generic pointer */
13283 if (IS_GENPTR(ctype)) {
13287 p_type = DCL_TYPE(type);
13289 /* we have to go by the storage class */
13290 p_type = PTR_TYPE(SPEC_OCLS(etype));
13292 /* if (SPEC_OCLS(etype)->codesp ) */
13293 /* p_type = CPOINTER ; */
13295 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13296 /* p_type = FPOINTER ; */
13298 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13299 /* p_type = PPOINTER; */
13301 /* if (SPEC_OCLS(etype) == idata ) */
13302 /* p_type = IPOINTER ; */
13304 /* p_type = POINTER ; */
13307 /* the first two bytes are known */
13308 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13309 size = GPTRSIZE - 1;
13312 if(offset < AOP_SIZE(right)) {
13313 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13314 pic16_mov2f(AOP(result), AOP(right), offset);
13316 if ((AOP_TYPE(right) == AOP_PCODE) &&
13317 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13318 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13322 pic16_aopPut(AOP(result),
13323 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13328 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13331 /* the last byte depending on type */
13336 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13340 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13344 pic16_emitcode(";BUG!? ","%d",__LINE__);
13349 if (GPTRSIZE > AOP_SIZE(right)) {
13350 // assume __data pointer... THIS MIGHT BE WRONG!
13351 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13353 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13358 /* this should never happen */
13359 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13360 "got unknown pointer type");
13363 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13369 /* just copy the pointers */
13370 size = AOP_SIZE(result);
13373 pic16_aopPut(AOP(result),
13374 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13383 /* so we now know that the size of destination is greater
13384 than the size of the source.
13385 Now, if the next iCode is an operator then we might be
13386 able to optimize the operation without performing a cast.
13388 if(genMixedOperation(ic))
13391 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13393 /* we move to result for the size of source */
13394 size = AOP_SIZE(right);
13399 pic16_mov2f(AOP(result), AOP(right), offset);
13403 /* now depending on the sign of the destination */
13404 size = AOP_SIZE(result) - AOP_SIZE(right);
13405 /* if unsigned or not an integral type */
13406 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13408 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13410 /* we need to extend the sign :( */
13413 /* Save one instruction of casting char to int */
13414 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13415 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13416 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13418 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13421 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13423 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13425 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13428 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13433 pic16_freeAsmop(right,NULL,ic,TRUE);
13434 pic16_freeAsmop(result,NULL,ic,TRUE);
13438 /*-----------------------------------------------------------------*/
13439 /* genDjnz - generate decrement & jump if not zero instrucion */
13440 /*-----------------------------------------------------------------*/
13441 static int genDjnz (iCode *ic, iCode *ifx)
13443 symbol *lbl, *lbl1;
13444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13449 /* if the if condition has a false label
13450 then we cannot save */
13454 /* if the minus is not of the form
13456 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13457 !IS_OP_LITERAL(IC_RIGHT(ic)))
13460 if (operandLitValue(IC_RIGHT(ic)) != 1)
13463 /* if the size of this greater than one then no
13465 if (getSize(operandType(IC_RESULT(ic))) > 1)
13468 /* otherwise we can save BIG */
13469 lbl = newiTempLabel(NULL);
13470 lbl1= newiTempLabel(NULL);
13472 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13474 if (IS_AOP_PREG(IC_RESULT(ic))) {
13475 pic16_emitcode("dec","%s",
13476 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13477 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13478 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13482 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13483 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13485 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13486 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13490 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13491 ifx->generated = 1;
13495 /*-----------------------------------------------------------------*/
13496 /* genReceive - generate code for a receive iCode */
13497 /*-----------------------------------------------------------------*/
13498 static void genReceive (iCode *ic)
13504 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13505 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13507 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13509 if (isOperandInFarSpace(IC_RESULT(ic))
13510 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13511 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13513 int size = getSize(operandType(IC_RESULT(ic)));
13514 int offset = pic16_fReturnSizePic - size;
13518 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13519 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13523 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13525 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13526 size = AOP_SIZE(IC_RESULT(ic));
13529 pic16_emitcode ("pop","acc");
13530 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13533 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13535 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13538 /* set pseudo stack pointer to where it should be - dw*/
13539 GpsuedoStkPtr = ic->parmBytes;
13541 /* setting GpsuedoStkPtr has side effects here: */
13542 /* FIXME: What's the correct size of the return(ed) value?
13543 * For now, assuming '4' as before... */
13544 assignResultValue(IC_RESULT(ic), 4, 0);
13547 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13550 /*-----------------------------------------------------------------*/
13551 /* genDummyRead - generate code for dummy read of volatiles */
13552 /*-----------------------------------------------------------------*/
13554 genDummyRead (iCode * ic)
13560 if (op && IS_SYMOP(op)) {
13561 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13562 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13565 pic16_aopOp (op, ic, FALSE);
13566 for (i=0; i < AOP_SIZE(op); i++) {
13567 // may need to protect this from the peepholer -- this is not nice but works...
13568 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13569 pic16_mov2w (AOP(op),i);
13570 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13572 pic16_freeAsmop (op, NULL, ic, TRUE);
13574 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13578 /*-----------------------------------------------------------------*/
13579 /* genpic16Code - generate code for pic16 based controllers */
13580 /*-----------------------------------------------------------------*/
13582 * At this point, ralloc.c has gone through the iCode and attempted
13583 * to optimize in a way suitable for a PIC. Now we've got to generate
13584 * PIC instructions that correspond to the iCode.
13586 * Once the instructions are generated, we'll pass through both the
13587 * peep hole optimizer and the pCode optimizer.
13588 *-----------------------------------------------------------------*/
13590 void genpic16Code (iCode *lic)
13595 lineHead = lineCurr = NULL;
13597 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13598 pic16_addpBlock(pb);
13601 /* if debug information required */
13602 if (options.debug && currFunc) {
13604 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13609 for (ic = lic ; ic ; ic = ic->next ) {
13611 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13612 if ( cln != ic->lineno ) {
13613 if ( options.debug ) {
13614 debugFile->writeCLine (ic);
13617 if(!options.noCcodeInAsm) {
13618 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13619 printCLine(ic->filename, ic->lineno)));
13625 if(options.iCodeInAsm) {
13628 /* insert here code to print iCode as comment */
13629 l = Safe_strdup(printILine(ic));
13630 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13633 /* if the result is marked as
13634 * spilt and rematerializable or code for
13635 * this has already been generated then
13637 if (resultRemat(ic) || ic->generated )
13640 /* depending on the operation */
13659 /* IPOP happens only when trying to restore a
13660 * spilt live range, if there is an ifx statement
13661 * following this pop then the if statement might
13662 * be using some of the registers being popped which
13663 * would destroy the contents of the register so
13664 * we need to check for this condition and handle it */
13666 && ic->next->op == IFX
13667 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13668 genIfx (ic->next,ic);
13686 genEndFunction (ic);
13702 pic16_genPlus (ic) ;
13706 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13707 pic16_genMinus (ic);
13723 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13727 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13733 /* note these two are xlated by algebraic equivalence
13734 * during parsing SDCC.y */
13735 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13736 "got '>=' or '<=' shouldn't have come here");
13740 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13752 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13756 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13760 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13784 genRightShift (ic);
13787 case GET_VALUE_AT_ADDRESS:
13792 if (POINTER_SET(ic))
13819 addSet(&_G.sendSet,ic);
13822 case DUMMY_READ_VOLATILE:
13832 /* now we are ready to call the
13833 peep hole optimizer */
13834 if (!options.nopeep)
13835 peepHole (&lineHead);
13837 /* now do the actual printing */
13838 printLine (lineHead, codeOutFile);
13841 DFPRINTF((stderr,"printing pBlock\n\n"));
13842 pic16_printpBlock(stdout,pb);