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@otenet.gr (2003,2004,2005)
10 Bug Fixes - Raphael Neider rneider@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"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
66 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
68 /* If you change these, you also have to update the library files
69 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
70 #define GPTR_TAG_DATA 0x80
71 #define GPTR_TAG_EEPROM 0x40
72 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
74 /* Wrapper to execute `code' at most once. */
75 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
77 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
79 void pic16_genMult8X8_8 (operand *, operand *,operand *);
80 void pic16_genMult16X16_16(operand *, operand *, operand *);
81 void pic16_genMult32X32_32(operand *, operand *, operand *);
82 pCode *pic16_AssembleLine(char *line, int peeps);
83 extern void pic16_printpBlock(FILE *of, pBlock *pb);
84 static asmop *newAsmop (short type);
85 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
86 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
87 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
88 static pCodeOp *pic16_popRegFromIdx(int rIdx);
90 //static int aopIdx (asmop *aop, int offset);
92 int pic16_labelOffset=0;
93 extern int pic16_debug_verbose;
94 #if !(USE_GENERIC_SIGNED_SHIFT)
95 static int optimized_for_speed = 0;
104 /* max_key keeps track of the largest label number used in
105 a function. This is then used to adjust the label offset
106 for the next function.
108 static int max_key=0;
109 static int GpsuedoStkPtr=0;
111 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
113 unsigned int pic16aopLiteral (value *val, int offset);
114 const char *pic16_AopType(short type);
115 static iCode *ifxForOp ( operand *op, iCode *ic );
117 void pic16_pushpCodeOp(pCodeOp *pcop);
118 void pic16_poppCodeOp(pCodeOp *pcop);
120 static bool is_LitOp(operand *op);
121 static bool is_LitAOp(asmop *aop);
124 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
126 /* set the following macro to 1 to enable passing the
127 * first byte of functions parameters via WREG */
128 #define USE_WREG_IN_FUNC_PARAMS 0
131 /* this is the down and dirty file with all kinds of
132 kludgy & hacky stuff. This is what it is all about
133 CODE GENERATION for a specific MCU . some of the
134 routines may be reusable, will have to see */
136 static char *zero = "#0x00";
137 static char *one = "#0x01";
138 //static char *spname = "sp";
142 * Function return value policy (MSB-->LSB):
144 * 16 bits -> PRODL:WREG
145 * 24 bits -> PRODH:PRODL:WREG
146 * 32 bits -> FSR0L:PRODH:PRODL:WREG
147 * >32 bits -> on stack, and FSR0 points to the beginning
152 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
153 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
154 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
155 static char **fReturn = fReturnpic16;
157 static char *accUse[] = {"WREG"};
159 //static short rbank = -1;
173 bitVect *fregsUsed; /* registers used in function */
175 set *sregsAllocSet; /* registers used to store stack variables */
176 int stack_lat; /* stack offset latency */
178 int useWreg; /* flag when WREG is used to pass function parameter */
181 extern int pic16_ptrRegReq ;
182 extern int pic16_nRegs;
183 extern FILE *codeOutFile;
184 //static void saverbank (int, iCode *,bool);
186 static lineNode *lineHead = NULL;
187 static lineNode *lineCurr = NULL;
189 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
190 0xE0, 0xC0, 0x80, 0x00};
191 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
192 0x07, 0x03, 0x01, 0x00};
196 /*-----------------------------------------------------------------*/
197 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
198 /* exponent of 2 is returned, otherwise -1 is */
200 /* note that this is similar to the function `powof2' in SDCCsymt */
204 /*-----------------------------------------------------------------*/
205 int pic16_my_powof2 (unsigned long num)
208 if( (num & (num-1)) == 0) {
221 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
223 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
225 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
226 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
227 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
228 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
229 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
230 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
231 ((result) ? AOP_SIZE(result) : 0));
234 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
237 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
239 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
240 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
241 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
242 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
243 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
244 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
248 void pic16_emitpcomment (char *fmt, ...)
251 char lb[INITIAL_INLINEASM];
252 unsigned char *lbp = lb;
257 vsprintf(lb+1,fmt,ap);
259 while (isspace(*lbp)) lbp++;
262 lineCurr = (lineCurr ?
263 connectLine(lineCurr,newLineNode(lb)) :
264 (lineHead = newLineNode(lb)));
265 lineCurr->isInline = _G.inLine;
266 lineCurr->isDebug = _G.debugLine;
268 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
271 // fprintf(stderr, "%s\n", lb);
274 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
277 char lb[INITIAL_INLINEASM];
278 unsigned char *lbp = lb;
280 if(!pic16_debug_verbose)
287 sprintf(lb,"%s\t",inst);
289 sprintf(lb,"%s",inst);
290 vsprintf(lb+(strlen(lb)),fmt,ap);
294 while (isspace(*lbp)) lbp++;
297 lineCurr = (lineCurr ?
298 connectLine(lineCurr,newLineNode(lb)) :
299 (lineHead = newLineNode(lb)));
300 lineCurr->isInline = _G.inLine;
301 lineCurr->isDebug = _G.debugLine;
303 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
306 // fprintf(stderr, "%s\n", lb);
311 void pic16_emitpLabel(int key)
313 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
316 void pic16_emitpLabelFORCE(int key)
318 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322 * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
327 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
329 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
335 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
337 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
343 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
349 #define pic16_emitcode DEBUGpic16_emitcode
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
357 char lb[INITIAL_INLINEASM];
358 unsigned char *lbp = lb;
364 sprintf(lb,"%s\t",inst);
366 sprintf(lb,"%s",inst);
367 vsprintf(lb+(strlen(lb)),fmt,ap);
371 while (isspace(*lbp)) lbp++;
374 lineCurr = (lineCurr ?
375 connectLine(lineCurr,newLineNode(lb)) :
376 (lineHead = newLineNode(lb)));
377 lineCurr->isInline = _G.inLine;
378 lineCurr->isDebug = _G.debugLine;
380 // VR fprintf(stderr, "lb = <%s>\n", lbp);
382 // if(pic16_debug_verbose)
383 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location */
392 /* with a debugger symbol */
393 /*-----------------------------------------------------------------*/
395 pic16_emitDebuggerSymbol (char * debugSym)
398 pic16_emitcode (";", "%s ==.", debugSym);
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
408 // bool r0iu = FALSE , r1iu = FALSE;
409 // bool r0ou = FALSE , r1ou = FALSE;
410 bool fsr0iu = FALSE, fsr0ou;
411 bool fsr2iu = FALSE, fsr2ou;
413 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
416 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
419 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
422 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
427 if(!fsr0iu && !fsr0ou) {
428 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429 (*aopp)->type = AOP_FSR0;
431 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
433 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
437 /* no usage of FSR2 */
438 if(!fsr2iu && !fsr2ou) {
439 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440 (*aopp)->type = AOP_FSR2;
442 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
446 /* now we know they both have usage */
447 /* if fsr0 not used in this instruction */
449 if (!_G.fsr0Pushed) {
450 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
455 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456 (*aopp)->type = AOP_FSR0;
458 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
460 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
464 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
469 /* the logic: if r0 & r1 used in the instruction
470 then we are in trouble otherwise */
472 /* first check if r0 & r1 are used by this
473 instruction, in which case we are in trouble */
474 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
480 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
483 /* if no usage of r0 then return it */
484 if (!r0iu && !r0ou) {
485 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486 (*aopp)->type = AOP_R0;
488 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491 /* if no usage of r1 then return it */
492 if (!r1iu && !r1ou) {
493 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494 (*aopp)->type = AOP_R1;
496 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
499 /* now we know they both have usage */
500 /* if r0 not used in this instruction */
502 /* push it if not already pushed */
504 //pic16_emitcode ("push","%s",
505 // pic16_regWithIdx(R0_IDX)->dname);
509 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510 (*aopp)->type = AOP_R0;
512 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
515 /* if r1 not used then */
518 /* push it if not already pushed */
520 //pic16_emitcode ("push","%s",
521 // pic16_regWithIdx(R1_IDX)->dname);
525 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526 (*aopp)->type = AOP_R1;
527 return pic16_regWithIdx(R1_IDX);
531 /* I said end of world but not quite end of world yet */
532 /* if this is a result then we can push it on the stack*/
534 (*aopp)->type = AOP_STK;
538 /* other wise this is true end of the world */
539 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540 "getFreePtr should never reach here");
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
552 aop = Safe_calloc(1,sizeof(asmop));
557 static void genSetDPTR(int n)
561 pic16_emitcode(";", "Select standard DPTR");
562 pic16_emitcode("mov", "dps, #0x00");
566 pic16_emitcode(";", "Select alternate DPTR");
567 pic16_emitcode("mov", "dps, #0x01");
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for */
573 /* generating code */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
579 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585 resIfx->condition = 1; /* assume that the ifx is true */
586 resIfx->generated = 0; /* indicate that the ifx has not been used */
589 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
592 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593 __FUNCTION__,__LINE__,resIfx->lbl->key);
598 resIfx->lbl = IC_TRUE(ifx);
600 resIfx->lbl = IC_FALSE(ifx);
601 resIfx->condition = 0;
606 DEBUGpic16_emitcode("; +++","ifx true is non-null");
608 DEBUGpic16_emitcode("; +++","ifx true is null");
610 DEBUGpic16_emitcode("; +++","ifx false is non-null");
612 DEBUGpic16_emitcode("; +++","ifx false is null");
616 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
626 return PTR_TYPE(SPEC_OCLS(etype));
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
636 symbol *sym=OP_SYMBOL(op);
638 memmap *space= SPEC_OCLS(sym->etype);
642 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
644 // sym = OP_SYMBOL(op);
646 /* if already has one */
648 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
653 /* if symbol was initially placed onStack then we must re-place it
654 * to direct memory, since pic16 does not have a specific stack */
656 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
664 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
666 sym->aop = aop = newAsmop (AOP_PAGED);
667 aop->aopu.aop_dir = sym->rname ;
668 aop->size = getSize(sym->type);
669 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670 pic16_allocDirReg( IC_LEFT(ic) );
678 /* assign depending on the storage class */
679 /* if it is on the stack or indirectly addressable */
680 /* space we need to assign either r0 or r1 to it */
681 if (sym->onStack) // || sym->iaccess)
686 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
689 /* acquire a temporary register -- it is saved in function */
691 sym->aop = aop = newAsmop(AOP_STA);
692 aop->aopu.stk.stk = sym->stack;
693 aop->size = getSize(sym->type);
696 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
701 for(i=0;i<aop->size;i++)
702 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
705 if(1 && ic->op == SEND) {
707 /* if SEND do the send here */
710 for(i=0;i<aop->size;i++) {
711 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
712 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
717 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
720 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
722 // we do not need to load the value if it is to be defined...
723 if (result) return aop;
726 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
729 for(i=0;i<aop->size;i++) {
731 /* initialise for stack access via frame pointer */
732 // operands on stack are accessible via "{FRAME POINTER} + index" with index
733 // starting at 2 for arguments and growing from 0 downwards for
734 // local variables (index == 0 is not assigned so we add one here)
736 int soffs = sym->stack;
742 if(1 && ic->op == SEND) {
743 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
744 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
745 pic16_popCopyReg( pic16_frame_plusw ),
746 pic16_popCopyReg(pic16_stack_postdec )));
748 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
749 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
750 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
756 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
763 /* now assign the address of the variable to
764 the pointer register */
765 if (aop->type != AOP_STK) {
769 pic16_emitcode("push","acc");
771 pic16_emitcode("mov","a,_bp");
772 pic16_emitcode("add","a,#0x%02x",
774 ((char)(sym->stack - _G.nRegsSaved )) :
775 ((char)sym->stack)) & 0xff);
776 pic16_emitcode("mov","%s,a",
777 aop->aopu.aop_ptr->name);
780 pic16_emitcode("pop","acc");
782 pic16_emitcode("mov","%s,#%s",
783 aop->aopu.aop_ptr->name,
785 aop->paged = space->paged;
787 aop->aopu.aop_stk = sym->stack;
795 if (sym->onStack && options.stack10bit)
797 /* It's on the 10 bit stack, which is located in
801 //DEBUGpic16_emitcode(";","%d",__LINE__);
804 pic16_emitcode("push","acc");
806 pic16_emitcode("mov","a,_bp");
807 pic16_emitcode("add","a,#0x%02x",
809 ((char)(sym->stack - _G.nRegsSaved )) :
810 ((char)sym->stack)) & 0xff);
813 pic16_emitcode ("mov","dpx1,#0x40");
814 pic16_emitcode ("mov","dph1,#0x00");
815 pic16_emitcode ("mov","dpl1, a");
819 pic16_emitcode("pop","acc");
821 sym->aop = aop = newAsmop(AOP_DPTR2);
822 aop->size = getSize(sym->type);
828 /* special case for a function */
829 if (IS_FUNC(sym->type)) {
830 sym->aop = aop = newAsmop(AOP_PCODE);
831 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
832 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
833 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
834 PCOI(aop->aopu.pcop)->index = 0;
835 aop->size = FPTRSIZE;
836 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
843 //DEBUGpic16_emitcode(";","%d",__LINE__);
844 /* if in bit space */
845 if (IN_BITSPACE(space)) {
846 sym->aop = aop = newAsmop (AOP_CRY);
847 aop->aopu.aop_dir = sym->rname ;
848 aop->size = getSize(sym->type);
849 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
852 /* if it is in direct space */
853 if (IN_DIRSPACE(space)) {
854 if(!strcmp(sym->rname, "_WREG")) {
855 sym->aop = aop = newAsmop (AOP_ACC);
856 aop->size = getSize(sym->type); /* should always be 1 */
857 assert(aop->size == 1);
858 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
861 sym->aop = aop = newAsmop (AOP_DIR);
862 aop->aopu.aop_dir = sym->rname ;
863 aop->size = getSize(sym->type);
864 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
865 pic16_allocDirReg( IC_LEFT(ic) );
870 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
871 sym->aop = aop = newAsmop (AOP_DIR);
872 aop->aopu.aop_dir = sym->rname ;
873 aop->size = getSize(sym->type);
874 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
875 pic16_allocDirReg( IC_LEFT(ic) );
880 /* only remaining is far space */
881 sym->aop = aop = newAsmop(AOP_PCODE);
883 /* change the next if to 1 to revert to good old immediate code */
884 if(IN_CODESPACE(space)) {
885 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
886 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
887 PCOI(aop->aopu.pcop)->index = 0;
889 /* try to allocate via direct register */
890 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
891 // aop->size = getSize( sym->type );
894 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
895 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
898 if(!pic16_allocDirReg (IC_LEFT(ic)))
902 if(IN_DIRSPACE( space ))
904 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
905 aop->size = FPTRSIZE;
906 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
907 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
908 else if(sym->onStack) {
911 if(SPEC_SCLS(sym->etype) == S_PDATA) {
912 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
913 aop->size = FPTRSIZE;
918 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
920 /* if it is in code space */
921 if (IN_CODESPACE(space))
927 /*-----------------------------------------------------------------*/
928 /* aopForRemat - rematerialzes an object */
929 /*-----------------------------------------------------------------*/
930 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
932 symbol *sym = OP_SYMBOL(op);
934 iCode *ic = NULL, *oldic;
935 asmop *aop = newAsmop(AOP_PCODE);
942 ic = sym->rematiCode;
944 if(IS_OP_POINTER(op)) {
945 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
948 // if(!result) /* fixme-vr */
952 // pic16_emitpcomment("ic: %s\n", printILine(ic));
955 val += (int) operandLitValue(IC_RIGHT(ic));
956 } else if (ic->op == '-') {
957 val -= (int) operandLitValue(IC_RIGHT(ic));
961 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
964 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
967 if(!op->isaddr)viaimmd++; else viaimmd=0;
969 /* set the following if to 1 to revert to good old immediate code */
970 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
973 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
975 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
978 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
980 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
983 PCOI(aop->aopu.pcop)->index = val;
985 aop->size = getSize( sym->type );
987 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
989 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
990 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
992 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
996 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
997 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
999 val, IS_PTR_CONST(operandType(op)));
1001 val, IS_CODEPTR(operandType(op)));
1004 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1006 pic16_allocDirReg (IC_LEFT(ic));
1008 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1015 static int aopIdx (asmop *aop, int offset)
1020 if(aop->type != AOP_REG)
1023 return aop->aopu.aop_reg[offset]->rIdx;
1028 /*-----------------------------------------------------------------*/
1029 /* regsInCommon - two operands have some registers in common */
1030 /*-----------------------------------------------------------------*/
1031 static bool regsInCommon (operand *op1, operand *op2)
1033 symbol *sym1, *sym2;
1036 /* if they have registers in common */
1037 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1040 sym1 = OP_SYMBOL(op1);
1041 sym2 = OP_SYMBOL(op2);
1043 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1046 for (i = 0 ; i < sym1->nRegs ; i++) {
1051 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1055 if (sym2->regs[j] == sym1->regs[i])
1063 /*-----------------------------------------------------------------*/
1064 /* operandsEqu - equivalent */
1065 /*-----------------------------------------------------------------*/
1066 static bool operandsEqu ( operand *op1, operand *op2)
1068 symbol *sym1, *sym2;
1070 /* if they not symbols */
1071 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1074 sym1 = OP_SYMBOL(op1);
1075 sym2 = OP_SYMBOL(op2);
1077 /* if both are itemps & one is spilt
1078 and the other is not then false */
1079 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1080 sym1->isspilt != sym2->isspilt )
1083 /* if they are the same */
1087 if (sym1->rname[0] && sym2->rname[0]
1088 && strcmp (sym1->rname, sym2->rname) == 0)
1092 /* if left is a tmp & right is not */
1093 if (IS_ITEMP(op1) &&
1096 (sym1->usl.spillLoc == sym2))
1099 if (IS_ITEMP(op2) &&
1103 (sym2->usl.spillLoc == sym1))
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_sameRegs - two asmops have the same registers */
1111 /*-----------------------------------------------------------------*/
1112 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1119 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1120 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1122 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1124 if (aop1->type != AOP_REG ||
1125 aop2->type != AOP_REG )
1128 /* This is a bit too restrictive if one is a subset of the other...
1129 if (aop1->size != aop2->size )
1133 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1134 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1136 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1137 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1144 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1146 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1147 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1149 if(aop1 == aop2)return TRUE;
1150 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1152 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_aopOp - allocates an asmop for an operand : */
1160 /*-----------------------------------------------------------------*/
1161 void pic16_aopOp (operand *op, iCode *ic, bool result)
1170 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1172 /* if this a literal */
1173 if (IS_OP_LITERAL(op)) {
1174 op->aop = aop = newAsmop(AOP_LIT);
1175 aop->aopu.aop_lit = op->operand.valOperand;
1176 aop->size = getSize(operandType(op));
1181 sym_link *type = operandType(op);
1183 if(IS_PTR_CONST(type))
1185 if(IS_CODEPTR(type))
1187 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1190 /* if already has a asmop then continue */
1194 /* if the underlying symbol has a aop */
1195 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1196 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1197 op->aop = OP_SYMBOL(op)->aop;
1201 /* if this is a true symbol */
1202 if (IS_TRUE_SYMOP(op)) {
1203 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1204 op->aop = aopForSym(ic, op, result);
1208 /* this is a temporary : this has
1214 e) can be a return use only */
1216 sym = OP_SYMBOL(op);
1218 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1219 /* if the type is a conditional */
1220 if (sym->regType == REG_CND) {
1221 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1226 /* if it is spilt then two situations
1228 b) has a spill location */
1229 if (sym->isspilt || sym->nRegs == 0) {
1231 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1232 DEBUGpic16_emitcode(";","%d",__LINE__);
1233 /* rematerialize it NOW */
1236 sym->aop = op->aop = aop = aopForRemat (op, result);
1237 // aop->size = getSize(sym->type);
1238 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1245 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1246 aop->size = getSize(sym->type);
1247 for ( i = 0 ; i < 1 ; i++ ) {
1248 aop->aopu.aop_str[i] = accUse[i];
1249 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1251 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1252 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1260 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1261 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1262 //pic16_allocDirReg (IC_LEFT(ic));
1263 aop->size = getSize(sym->type);
1268 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1269 aop->size = getSize(sym->type);
1270 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1271 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1273 DEBUGpic16_emitcode(";","%d",__LINE__);
1277 /* else spill location */
1278 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1279 /* force a new aop if sizes differ */
1280 sym->usl.spillLoc->aop = NULL;
1284 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1285 __FUNCTION__,__LINE__,
1286 sym->usl.spillLoc->rname,
1287 sym->rname, sym->usl.spillLoc->offset);
1290 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1291 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1295 sym->usl.spillLoc->offset, op);
1297 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1298 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1299 assert (getSize(sym->type) <= 1);
1300 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1302 aop->size = getSize(sym->type);
1308 sym_link *type = operandType(op);
1310 if(IS_PTR_CONST(type))
1312 if(IS_CODEPTR(type))
1314 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1317 /* must be in a register */
1318 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1319 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1320 aop->size = sym->nRegs;
1321 for ( i = 0 ; i < sym->nRegs ;i++)
1322 aop->aopu.aop_reg[i] = sym->regs[i];
1325 /*-----------------------------------------------------------------*/
1326 /* pic16_freeAsmop - free up the asmop given to an operand */
1327 /*----------------------------------------------------------------*/
1328 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1345 /* depending on the asmop type only three cases need work AOP_RO
1346 , AOP_R1 && AOP_STK */
1348 switch (aop->type) {
1350 if (_G.fsr0Pushed ) {
1352 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1353 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1354 // pic16_emitcode ("pop","ar0");
1358 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1362 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1368 pic16_emitcode ("pop","ar0");
1372 bitVectUnSetBit(ic->rUsed,R0_IDX);
1378 pic16_emitcode ("pop","ar1");
1382 bitVectUnSetBit(ic->rUsed,R1_IDX);
1389 /* we must store the result on stack */
1390 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1391 // operands on stack are accessible via "FSR2 + index" with index
1392 // starting at 2 for arguments and growing from 0 downwards for
1393 // local variables (index == 0 is not assigned so we add one here)
1394 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1399 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1400 for(i=0;i<aop->size;i++) {
1401 /* initialise for stack access via frame pointer */
1402 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1404 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1407 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1411 for(i=0;i<aop->size;i++) {
1412 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1414 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1415 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1426 int stk = aop->aopu.aop_stk + aop->size;
1427 bitVectUnSetBit(ic->rUsed,R0_IDX);
1428 bitVectUnSetBit(ic->rUsed,R1_IDX);
1430 getFreePtr(ic,&aop,FALSE);
1432 if (options.stack10bit)
1434 /* I'm not sure what to do here yet... */
1437 "*** Warning: probably generating bad code for "
1438 "10 bit stack mode.\n");
1442 pic16_emitcode ("mov","a,_bp");
1443 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1444 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1446 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1450 pic16_emitcode("pop","acc");
1451 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1453 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1456 pic16_freeAsmop(op,NULL,ic,TRUE);
1458 pic16_emitcode("pop","ar0");
1463 pic16_emitcode("pop","ar1");
1473 /* all other cases just dealloc */
1477 OP_SYMBOL(op)->aop = NULL;
1478 /* if the symbol has a spill */
1480 SPIL_LOC(op)->aop = NULL;
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_aopGet - for fetching value of the aop */
1487 /*-----------------------------------------------------------------*/
1488 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1493 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1495 /* offset is greater than size then zero */
1496 if (offset > (aop->size - 1) &&
1497 aop->type != AOP_LIT)
1500 /* depending on type */
1501 switch (aop->type) {
1505 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1506 rs = Safe_calloc(1, strlen(s)+1);
1511 /* if we need to increment it */
1512 while (offset > aop->coff)
1514 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1518 while (offset < aop->coff)
1520 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1526 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1527 return (dname ? "acc" : "a");
1529 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1530 rs = Safe_calloc (1, strlen (s) + 1);
1538 sprintf (s,"%s",aop->aopu.aop_immd);
1541 sprintf(s,"(%s >> %d)",
1546 aop->aopu.aop_immd);
1547 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1548 rs = Safe_calloc(1,strlen(s)+1);
1554 sprintf(s,"(%s + %d)",
1557 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1559 sprintf(s,"%s",aop->aopu.aop_dir);
1560 rs = Safe_calloc(1,strlen(s)+1);
1565 return aop->aopu.aop_reg[offset]->name;
1568 return aop->aopu.aop_dir;
1571 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1572 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1574 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1575 rs = Safe_strdup("WREG");
1579 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1580 rs = Safe_calloc(1,strlen(s)+1);
1585 aop->coff = offset ;
1587 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1590 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1591 aop->type = AOP_ACC;
1592 return Safe_strdup("_WREG");
1594 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1596 return aop->aopu.aop_str[offset];
1600 pCodeOp *pcop = aop->aopu.pcop;
1601 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1603 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1604 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1606 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1608 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1611 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1614 rs = Safe_calloc(1,strlen(s)+1);
1620 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1622 sprintf(s,"(%s + %d)",
1626 sprintf(s,"%s",aop->aopu.aop_dir);
1627 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1628 rs = Safe_calloc(1,strlen(s)+1);
1634 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1638 // pCodeOp *pcop = aop->aop
1643 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1644 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1645 "aopget got unsupported aop->type");
1651 /* lock has the following meaning: When allocating temporary registers
1652 * for stack variables storage, the value of the temporary register is
1653 * saved on stack. Its value is restored at the end. This procedure is
1654 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1655 * a possibility that before a call to pic16_aopOp, a temporary register
1656 * is allocated for a while and it is freed after some time, this will
1657 * mess the stack and values will not be restored properly. So use lock=1
1658 * to allocate temporary registers used internally by the programmer, and
1659 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1660 * to inform the compiler developer about a possible bug. This is an internal
1661 * feature for developing the compiler -- VR */
1663 int _TempReg_lock = 0;
1664 /*-----------------------------------------------------------------*/
1665 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1666 /*-----------------------------------------------------------------*/
1667 pCodeOp *pic16_popGetTempReg(int lock)
1672 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1674 // werror(W_POSSBUG2, __FILE__, __LINE__);
1677 _TempReg_lock += lock;
1687 /* this code might seem better but it does the *same* job with
1688 * the old code, it all depends on ralloc.c to get a free/unused
1692 while(i < pic16_nRegs) {
1693 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1694 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1695 if((!rr || (rr && rr->isFree))
1696 && !bitVectBitValue(cfunc->regsUsed, i)) {
1697 pcop = pic16_newpCodeOpReg( i );
1698 PCOR(pcop)->r->wasUsed = 1;
1699 PCOR(pcop)->r->isFree = 0;
1706 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1710 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1711 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1712 PCOR(pcop)->r->wasUsed=1;
1713 PCOR(pcop)->r->isFree=0;
1715 /* push value on stack */
1716 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1727 /* is not part of f, but don't save if */
1729 /*-----------------------------------------------------------------*/
1730 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1736 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1739 // werror(W_POSSBUG2, __FILE__, __LINE__);
1742 _TempReg_lock += lock;
1747 i = bitVectFirstBit(f);
1750 /* bypass registers that are used by function */
1751 if(!bitVectBitValue(f, i)) {
1753 /* bypass registers that are already allocated for stack access */
1754 if(!bitVectBitValue(v, i)) {
1756 // debugf("getting register rIdx = %d\n", i);
1757 /* ok, get the operand */
1758 pcop = pic16_newpCodeOpReg( i );
1760 /* should never by NULL */
1761 assert( pcop != NULL );
1765 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1768 PCOR(pcop)->r->wasUsed=1;
1769 PCOR(pcop)->r->isFree=0;
1775 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1777 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1778 /* already used in previous steps, break */
1785 /* caller takes care of the following */
1786 // bitVectSetBit(v, i);
1789 /* push value on stack */
1790 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1791 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1807 /*-----------------------------------------------------------------*/
1808 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1809 /*-----------------------------------------------------------------*/
1810 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1814 _TempReg_lock -= lock;
1816 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1817 PCOR(pcop)->r->isFree = 1;
1819 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLabel(int key)
1828 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1833 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1836 /*-----------------------------------------------------------------*/
1837 /* pic16_popCopyReg - copy a pcode operator */
1838 /*-----------------------------------------------------------------*/
1839 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1843 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1844 memcpy (pcor, pc, sizeof (pCodeOpReg));
1845 pcor->r->wasUsed = 1;
1847 //pcor->pcop.type = pc->pcop.type;
1849 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1850 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1852 pcor->pcop.name = NULL;
1855 //pcor->rIdx = pc->rIdx;
1856 //pcor->r->wasUsed=1;
1857 //pcor->instance = pc->instance;
1859 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popGetLit - asm operator to pcode operator conversion */
1866 /*-----------------------------------------------------------------*/
1867 pCodeOp *pic16_popGetLit(int lit)
1869 return pic16_newpCodeOpLit(lit);
1872 /*-----------------------------------------------------------------*/
1873 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1874 /*-----------------------------------------------------------------*/
1875 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1877 return pic16_newpCodeOpLit2(lit, arg2);
1881 /*-----------------------------------------------------------------*/
1882 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1883 /*-----------------------------------------------------------------*/
1884 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1886 return pic16_newpCodeOpImmd(name, offset,index, 0);
1890 /*-----------------------------------------------------------------*/
1891 /* pic16_popGet - asm operator to pcode operator conversion */
1892 /*-----------------------------------------------------------------*/
1893 pCodeOp *pic16_popGetWithString(char *str)
1899 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1903 pcop = pic16_newpCodeOp(str,PO_STR);
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popRegFromString - */
1910 /*-----------------------------------------------------------------*/
1911 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1914 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1915 pcop->type = PO_DIR;
1917 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1918 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1923 pcop->name = Safe_calloc(1,strlen(str)+1);
1924 strcpy(pcop->name,str);
1926 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1928 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1929 // PCOR(pcop)->r->wasUsed = 1;
1931 /* make sure that register doesn't exist,
1932 * and operand isn't NULL
1933 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1934 if((PCOR(pcop)->r == NULL)
1936 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1937 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1938 // __FUNCTION__, __LINE__, str, size, offset);
1940 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1941 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1944 PCOR(pcop)->instance = offset;
1949 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1953 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1954 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1956 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1957 PCOR(pcop)->rIdx = rIdx;
1958 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1960 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1962 PCOR(pcop)->r->isFree = 0;
1963 PCOR(pcop)->r->wasUsed = 1;
1965 pcop->type = PCOR(pcop)->r->pc_type;
1970 /*---------------------------------------------------------------------------------*/
1971 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1973 /*---------------------------------------------------------------------------------*/
1974 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1979 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1981 /* comment the following check, so errors to throw up */
1982 // if(!pcop2)return NULL;
1984 temp = pic16_popGet(aop_dst, offset);
1985 pcop2->pcop2 = temp;
1992 /*--------------------------------------------------------------------------------.-*/
1993 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1994 /* VR 030601 , adapted by Hans Dorn */
1995 /*--------------------------------------------------------------------------------.-*/
1996 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2000 pcop2 = (pCodeOpReg2 *)src;
2008 /*---------------------------------------------------------------------------------*/
2009 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2010 /* movff instruction */
2011 /*---------------------------------------------------------------------------------*/
2012 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2017 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2018 pcop2->pcop2 = pic16_popCopyReg(dst);
2020 /* the pCodeOp may be already allocated */
2021 pcop2 = (pCodeOpReg2 *)(src);
2022 pcop2->pcop2 = (pCodeOp *)(dst);
2029 /*-----------------------------------------------------------------*/
2030 /* pic16_popGet - asm operator to pcode operator conversion */
2031 /*-----------------------------------------------------------------*/
2032 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2034 // char *s = buffer ;
2039 /* offset is greater than
2042 // if (offset > (aop->size - 1) &&
2043 // aop->type != AOP_LIT)
2044 // return NULL; //zero;
2046 /* depending on type */
2047 switch (aop->type) {
2052 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2053 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2059 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2060 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2061 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2062 PCOR(pcop)->r->wasUsed = 1;
2063 PCOR(pcop)->r->isFree = 0;
2065 PCOR(pcop)->instance = offset;
2066 pcop->type = PCOR(pcop)->r->pc_type;
2070 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2071 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2074 /* pCodeOp is already allocated from aopForSym */
2075 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2076 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2081 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2083 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2085 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2087 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2088 PCOR(pcop)->rIdx = rIdx;
2089 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2090 PCOR(pcop)->r->wasUsed=1;
2091 PCOR(pcop)->r->isFree=0;
2093 PCOR(pcop)->instance = offset;
2094 pcop->type = PCOR(pcop)->r->pc_type;
2095 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2099 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2100 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2106 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2107 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2111 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2112 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2118 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2119 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2121 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2123 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2124 // pcop->type = PO_GPR_REGISTER;
2125 PCOR(pcop)->rIdx = rIdx;
2126 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2127 PCOR(pcop)->r->wasUsed=1;
2128 PCOR(pcop)->r->isFree=0;
2130 PCOR(pcop)->instance = offset;
2131 pcop->type = PCOR(pcop)->r->pc_type;
2133 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2134 // rs = aop->aopu.aop_reg[offset]->name;
2135 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2140 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2142 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2143 PCOR(pcop)->instance = offset;
2144 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2145 //if(PCOR(pcop)->r == NULL)
2146 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2150 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2151 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2154 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2155 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2158 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2159 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2160 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2161 pcop->type = PCOR(pcop)->r->pc_type;
2162 pcop->name = PCOR(pcop)->r->name;
2168 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2170 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2171 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2172 switch( aop->aopu.pcop->type ) {
2173 case PO_DIR: PCOR(pcop)->instance += offset; break;
2174 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2179 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2180 assert( 0 ); /* should never reach here */;
2185 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2186 "pic16_popGet got unsupported aop->type");
2189 /*-----------------------------------------------------------------*/
2190 /* pic16_aopPut - puts a string for a aop */
2191 /*-----------------------------------------------------------------*/
2192 void pic16_aopPut (asmop *aop, char *s, int offset)
2199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2201 if (aop->size && offset > ( aop->size - 1)) {
2202 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2203 "pic16_aopPut got offset > aop->size");
2207 /* will assign value to value */
2208 /* depending on where it is ofcourse */
2209 switch (aop->type) {
2212 sprintf(d,"(%s + %d)",
2213 aop->aopu.aop_dir,offset);
2214 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2217 sprintf(d,"%s",aop->aopu.aop_dir);
2220 DEBUGpic16_emitcode(";","%d",__LINE__);
2222 pic16_emitcode("movf","%s,w",s);
2223 pic16_emitcode("movwf","%s",d);
2226 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2227 if(offset >= aop->size) {
2228 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2231 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2234 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2241 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2242 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2245 strcmp(s,"r0") == 0 ||
2246 strcmp(s,"r1") == 0 ||
2247 strcmp(s,"r2") == 0 ||
2248 strcmp(s,"r3") == 0 ||
2249 strcmp(s,"r4") == 0 ||
2250 strcmp(s,"r5") == 0 ||
2251 strcmp(s,"r6") == 0 ||
2252 strcmp(s,"r7") == 0 )
2253 pic16_emitcode("mov","%s,%s ; %d",
2254 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2258 if(strcmp(s,"W")==0 )
2259 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2261 pic16_emitcode("movwf","%s",
2262 aop->aopu.aop_reg[offset]->name);
2264 if(strcmp(s,zero)==0) {
2265 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2267 } else if(strcmp(s,"W")==0) {
2268 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2269 pcop->type = PO_GPR_REGISTER;
2271 PCOR(pcop)->rIdx = -1;
2272 PCOR(pcop)->r = NULL;
2274 DEBUGpic16_emitcode(";","%d",__LINE__);
2275 pcop->name = Safe_strdup(s);
2276 pic16_emitpcode(POC_MOVFW,pcop);
2277 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2278 } else if(strcmp(s,one)==0) {
2279 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2280 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2282 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2290 if (aop->type == AOP_DPTR2)
2296 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2297 "pic16_aopPut writting to code space");
2301 while (offset > aop->coff) {
2303 pic16_emitcode ("inc","dptr");
2306 while (offset < aop->coff) {
2308 pic16_emitcode("lcall","__decdptr");
2313 /* if not in accumulater */
2316 pic16_emitcode ("movx","@dptr,a");
2318 if (aop->type == AOP_DPTR2)
2326 while (offset > aop->coff) {
2328 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2330 while (offset < aop->coff) {
2332 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2338 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2343 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2345 if (strcmp(s,"r0") == 0 ||
2346 strcmp(s,"r1") == 0 ||
2347 strcmp(s,"r2") == 0 ||
2348 strcmp(s,"r3") == 0 ||
2349 strcmp(s,"r4") == 0 ||
2350 strcmp(s,"r5") == 0 ||
2351 strcmp(s,"r6") == 0 ||
2352 strcmp(s,"r7") == 0 ) {
2354 sprintf(buffer,"a%s",s);
2355 pic16_emitcode("mov","@%s,%s",
2356 aop->aopu.aop_ptr->name,buffer);
2358 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2363 if (strcmp(s,"a") == 0)
2364 pic16_emitcode("push","acc");
2366 pic16_emitcode("push","%s",s);
2371 /* if bit variable */
2372 if (!aop->aopu.aop_dir) {
2373 pic16_emitcode("clr","a");
2374 pic16_emitcode("rlc","a");
2377 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2380 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2383 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2385 lbl = newiTempLabel(NULL);
2387 if (strcmp(s,"a")) {
2390 pic16_emitcode("clr","c");
2391 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2392 pic16_emitcode("cpl","c");
2393 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2394 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2401 if (strcmp(aop->aopu.aop_str[offset],s))
2402 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2407 if (!offset && (strcmp(s,"acc") == 0))
2410 if (strcmp(aop->aopu.aop_str[offset],s))
2411 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2415 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2416 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2417 // "pic16_aopPut got unsupported aop->type");
2423 /*-----------------------------------------------------------------*/
2424 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2425 /*-----------------------------------------------------------------*/
2426 void pic16_mov2w (asmop *aop, int offset)
2428 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2431 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2433 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2436 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2438 if(is_LitAOp(src)) {
2439 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2440 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2442 if(pic16_sameRegsOfs(src, dst, offset))return;
2443 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2444 pic16_popGet(dst, offset)));
2448 static void pic16_movLit2f(pCodeOp *pc, int lit)
2450 if (0 == (lit & 0x00ff))
2452 pic16_emitpcode (POC_CLRF, pc);
2453 } else if (0xff == (lit & 0x00ff))
2455 pic16_emitpcode (POC_SETF, pc);
2457 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2458 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2462 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2464 if(is_LitAOp(src)) {
2465 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2466 pic16_emitpcode(POC_MOVWF, dst);
2468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2472 void pic16_testStackOverflow(void)
2474 #define GSTACK_TEST_NAME "_gstack_test"
2476 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2481 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2482 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2483 // strcpy(sym->rname, GSTACK_TEST_NAME);
2484 checkAddSym(&externs, sym);
2489 /* push pcop into stack */
2490 void pic16_pushpCodeOp(pCodeOp *pcop)
2492 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2494 if(pic16_options.gstack)
2495 pic16_testStackOverflow();
2499 /* pop pcop from stack */
2500 void pic16_poppCodeOp(pCodeOp *pcop)
2502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2503 if(pic16_options.gstack)
2504 pic16_testStackOverflow();
2508 /*-----------------------------------------------------------------*/
2509 /* pushw - pushes wreg to stack */
2510 /*-----------------------------------------------------------------*/
2513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2514 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2515 if(pic16_options.gstack)
2516 pic16_testStackOverflow();
2520 /*-----------------------------------------------------------------*/
2521 /* pushaop - pushes aop to stack */
2522 /*-----------------------------------------------------------------*/
2523 void pushaop(asmop *aop, int offset)
2525 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2527 if(_G.resDirect)return;
2529 if(is_LitAOp(aop)) {
2530 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2531 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2533 pic16_emitpcode(POC_MOVFF,
2534 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2537 if(pic16_options.gstack)
2538 pic16_testStackOverflow();
2541 /*-----------------------------------------------------------------*/
2542 /* popaop - pops aop from stack */
2543 /*-----------------------------------------------------------------*/
2544 void popaop(asmop *aop, int offset)
2546 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2547 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2548 if(pic16_options.gstack)
2549 pic16_testStackOverflow();
2552 void popaopidx(asmop *aop, int offset, int index)
2556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2558 if(STACK_MODEL_LARGE)ofs++;
2560 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2561 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2562 if(pic16_options.gstack)
2563 pic16_testStackOverflow();
2566 #if !(USE_GENERIC_SIGNED_SHIFT)
2567 /*-----------------------------------------------------------------*/
2568 /* reAdjustPreg - points a register back to where it should */
2569 /*-----------------------------------------------------------------*/
2570 static void reAdjustPreg (asmop *aop)
2574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2576 if ((size = aop->size) <= 1)
2579 switch (aop->type) {
2583 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2587 if (aop->type == AOP_DPTR2)
2593 pic16_emitcode("lcall","__decdptr");
2596 if (aop->type == AOP_DPTR2)
2608 /*-----------------------------------------------------------------*/
2609 /* opIsGptr: returns non-zero if the passed operand is */
2610 /* a generic pointer type. */
2611 /*-----------------------------------------------------------------*/
2612 static int opIsGptr(operand *op)
2614 sym_link *type = operandType(op);
2616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2617 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2625 /*-----------------------------------------------------------------*/
2626 /* pic16_getDataSize - get the operand data size */
2627 /*-----------------------------------------------------------------*/
2628 int pic16_getDataSize(operand *op)
2630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2633 return AOP_SIZE(op);
2635 // tsd- in the pic port, the genptr size is 1, so this code here
2636 // fails. ( in the 8051 port, the size was 4).
2639 size = AOP_SIZE(op);
2640 if (size == GPTRSIZE)
2642 sym_link *type = operandType(op);
2643 if (IS_GENPTR(type))
2645 /* generic pointer; arithmetic operations
2646 * should ignore the high byte (pointer type).
2649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2656 /*-----------------------------------------------------------------*/
2657 /* pic16_outAcc - output Acc */
2658 /*-----------------------------------------------------------------*/
2659 void pic16_outAcc(operand *result)
2662 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2663 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2666 size = pic16_getDataSize(result);
2668 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2671 /* unsigned or positive */
2673 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outBitC - output a bit C */
2680 /* Move to result the value of Carry flag -- VR */
2681 /*-----------------------------------------------------------------*/
2682 void pic16_outBitC(operand *result)
2686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2688 /* if the result is bit */
2689 if (AOP_TYPE(result) == AOP_CRY) {
2690 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2691 pic16_aopPut(AOP(result),"c",0);
2694 i = AOP_SIZE(result);
2696 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2698 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2702 /*-----------------------------------------------------------------*/
2703 /* pic16_outBitOp - output a bit from Op */
2704 /* Move to result the value of set/clr op -- VR */
2705 /*-----------------------------------------------------------------*/
2706 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2712 /* if the result is bit */
2713 if (AOP_TYPE(result) == AOP_CRY) {
2714 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2715 pic16_aopPut(AOP(result),"c",0);
2718 i = AOP_SIZE(result);
2720 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2722 pic16_emitpcode(POC_RRCF, pcop);
2723 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2727 /*-----------------------------------------------------------------*/
2728 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2729 /*-----------------------------------------------------------------*/
2730 void pic16_toBoolean(operand *oper)
2732 int size = AOP_SIZE(oper) - 1;
2735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2737 if ( AOP_TYPE(oper) != AOP_ACC) {
2738 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2745 /*-----------------------------------------------------------------*/
2746 /* genUminusFloat - unary minus for floating points */
2747 /*-----------------------------------------------------------------*/
2748 static void genUminusFloat(operand *op,operand *result)
2750 int size ,offset =0 ;
2753 /* for this we just need to flip the
2754 first it then copy the rest in place */
2755 size = AOP_SIZE(op);
2756 assert( size == AOP_SIZE(result) );
2759 pic16_mov2f(AOP(result), AOP(op), offset);
2763 /* toggle the MSB's highest bit */
2764 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2767 /*-----------------------------------------------------------------*/
2768 /* genUminus - unary minus code generation */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminus (iCode *ic)
2773 sym_link *optype, *rtype;
2780 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2781 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2783 /* if both in bit space then special case */
2784 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2785 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2787 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2788 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2789 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2793 optype = operandType(IC_LEFT(ic));
2794 rtype = operandType(IC_RESULT(ic));
2797 /* if float then do float stuff */
2798 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2799 if(IS_FIXED(optype))
2800 debugf("implement fixed16x16 type\n", 0);
2802 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2806 /* otherwise subtract from zero by taking the 2's complement */
2807 size = AOP_SIZE(IC_LEFT(ic));
2808 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2809 label = newiTempLabel ( NULL );
2811 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2812 for (i=size-1; i > 0; i--) {
2813 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2815 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2816 for (i=1; i < size; i++) {
2817 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2818 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2821 for (i=size-1; i >= 0; i--) {
2822 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2823 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2826 for (i=0; i < size-2; i++) {
2827 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2828 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2830 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2832 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2835 pic16_emitpLabel (label->key);
2838 /* release the aops */
2839 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2840 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2844 /*-----------------------------------------------------------------*/
2845 /* saveRegisters - will look for a call and save the registers */
2846 /*-----------------------------------------------------------------*/
2847 static void saveRegisters(iCode *lic)
2854 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2856 for (ic = lic ; ic ; ic = ic->next)
2857 if (ic->op == CALL || ic->op == PCALL)
2861 fprintf(stderr,"found parameter push with no function call\n");
2865 /* if the registers have been saved already then
2867 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2870 /* find the registers in use at this time
2871 and push them away to safety */
2872 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2876 if (options.useXstack) {
2877 if (bitVectBitValue(rsave,R0_IDX))
2878 pic16_emitcode("mov","b,r0");
2879 pic16_emitcode("mov","r0,%s",spname);
2880 for (i = 0 ; i < pic16_nRegs ; i++) {
2881 if (bitVectBitValue(rsave,i)) {
2883 pic16_emitcode("mov","a,b");
2885 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2886 pic16_emitcode("movx","@r0,a");
2887 pic16_emitcode("inc","r0");
2890 pic16_emitcode("mov","%s,r0",spname);
2891 if (bitVectBitValue(rsave,R0_IDX))
2892 pic16_emitcode("mov","r0,b");
2894 //for (i = 0 ; i < pic16_nRegs ; i++) {
2895 // if (bitVectBitValue(rsave,i))
2896 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2899 dtype = operandType(IC_LEFT(ic));
2900 if (currFunc && dtype &&
2901 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2902 IFFUNC_ISISR(currFunc->type) &&
2905 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2908 /*-----------------------------------------------------------------*/
2909 /* unsaveRegisters - pop the pushed registers */
2910 /*-----------------------------------------------------------------*/
2911 static void unsaveRegisters (iCode *ic)
2916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2917 /* find the registers in use at this time
2918 and push them away to safety */
2919 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2922 if (options.useXstack) {
2923 pic16_emitcode("mov","r0,%s",spname);
2924 for (i = pic16_nRegs ; i >= 0 ; i--) {
2925 if (bitVectBitValue(rsave,i)) {
2926 pic16_emitcode("dec","r0");
2927 pic16_emitcode("movx","a,@r0");
2929 pic16_emitcode("mov","b,a");
2931 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2935 pic16_emitcode("mov","%s,r0",spname);
2936 if (bitVectBitValue(rsave,R0_IDX))
2937 pic16_emitcode("mov","r0,b");
2939 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2940 // if (bitVectBitValue(rsave,i))
2941 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2948 /*-----------------------------------------------------------------*/
2950 /*-----------------------------------------------------------------*/
2951 static void pushSide(operand * oper, int size)
2954 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2956 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2957 if (AOP_TYPE(oper) != AOP_REG &&
2958 AOP_TYPE(oper) != AOP_DIR &&
2960 pic16_emitcode("mov","a,%s",l);
2961 pic16_emitcode("push","acc");
2963 pic16_emitcode("push","%s",l);
2968 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2970 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2971 pic16_emitpcode(POC_MOVFW, src);
2972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2974 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2975 src, pic16_popGet(AOP(op), offset)));
2980 /*-----------------------------------------------------------------*/
2981 /* assignResultValue - assign results to oper, rescall==1 is */
2982 /* called from genCall() or genPcall() */
2983 /*-----------------------------------------------------------------*/
2984 static void assignResultValue(operand * oper, int rescall)
2986 int size = AOP_SIZE(oper);
2990 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2991 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2994 /* assign result from a call/pcall function() */
2996 /* function results are stored in a special order,
2997 * see top of file with Function return policy, or manual */
3000 /* 8-bits, result in WREG */
3001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3004 /* 16-bits, result in PRODL:WREG */
3005 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3009 /* 24-bits, result in PRODH:PRODL:WREG */
3010 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3014 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3015 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3019 /* >32-bits, result on stack, and FSR0 points to beginning.
3020 * Fix stack when done */
3022 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3024 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3025 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3027 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3033 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3034 if(STACK_MODEL_LARGE) {
3036 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3040 int areg = 0; /* matching argument register */
3042 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3043 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3046 /* its called from genReceive (probably) -- VR */
3047 /* I hope this code will not be called from somewhere else in the future!
3048 * We manually set the pseudo stack pointer in genReceive. - dw
3050 if(!GpsuedoStkPtr && _G.useWreg) {
3051 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3053 /* The last byte in the assignment is in W */
3054 if(areg <= GpsuedoStkPtr) {
3056 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3058 // debugf("receive from WREG\n", 0);
3060 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3063 _G.stack_lat = AOP_SIZE(oper)-1;
3068 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3069 // debugf("receive from STACK\n", 0);
3076 /*-----------------------------------------------------------------*/
3077 /* genIpush - generate code for pushing this gets a little complex */
3078 /*-----------------------------------------------------------------*/
3079 static void genIpush (iCode *ic)
3081 // int size, offset=0;
3084 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3087 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3089 /* send to stack as normal */
3090 addSet(&_G.sendSet,ic);
3091 // addSetHead(&_G.sendSet,ic);
3092 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3097 int size, offset = 0 ;
3101 /* if this is not a parm push : ie. it is spill push
3102 and spill push is always done on the local stack */
3103 if (!ic->parmPush) {
3105 /* and the item is spilt then do nothing */
3106 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3109 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3110 size = AOP_SIZE(IC_LEFT(ic));
3111 /* push it on the stack */
3113 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3118 pic16_emitcode("push","%s",l);
3123 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3127 /*-----------------------------------------------------------------*/
3128 /* genIpop - recover the registers: can happen only for spilling */
3129 /*-----------------------------------------------------------------*/
3130 static void genIpop (iCode *ic)
3133 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3138 /* if the temp was not pushed then */
3139 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3142 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3143 size = AOP_SIZE(IC_LEFT(ic));
3146 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3149 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3154 /*-----------------------------------------------------------------*/
3155 /* unsaverbank - restores the resgister bank from stack */
3156 /*-----------------------------------------------------------------*/
3157 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3159 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3165 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3167 if (options.useXstack) {
3169 r = getFreePtr(ic,&aop,FALSE);
3172 pic16_emitcode("mov","%s,_spx",r->name);
3173 pic16_emitcode("movx","a,@%s",r->name);
3174 pic16_emitcode("mov","psw,a");
3175 pic16_emitcode("dec","%s",r->name);
3178 pic16_emitcode ("pop","psw");
3181 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3182 if (options.useXstack) {
3183 pic16_emitcode("movx","a,@%s",r->name);
3184 //pic16_emitcode("mov","(%s+%d),a",
3185 // regspic16[i].base,8*bank+regspic16[i].offset);
3186 pic16_emitcode("dec","%s",r->name);
3189 pic16_emitcode("pop",""); //"(%s+%d)",
3190 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3193 if (options.useXstack) {
3195 pic16_emitcode("mov","_spx,%s",r->name);
3196 pic16_freeAsmop(NULL,aop,ic,TRUE);
3202 /*-----------------------------------------------------------------*/
3203 /* saverbank - saves an entire register bank on the stack */
3204 /*-----------------------------------------------------------------*/
3205 static void saverbank (int bank, iCode *ic, bool pushPsw)
3207 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3214 if (options.useXstack) {
3217 r = getFreePtr(ic,&aop,FALSE);
3218 pic16_emitcode("mov","%s,_spx",r->name);
3222 for (i = 0 ; i < pic16_nRegs ;i++) {
3223 if (options.useXstack) {
3224 pic16_emitcode("inc","%s",r->name);
3225 //pic16_emitcode("mov","a,(%s+%d)",
3226 // regspic16[i].base,8*bank+regspic16[i].offset);
3227 pic16_emitcode("movx","@%s,a",r->name);
3229 pic16_emitcode("push","");// "(%s+%d)",
3230 //regspic16[i].base,8*bank+regspic16[i].offset);
3234 if (options.useXstack) {
3235 pic16_emitcode("mov","a,psw");
3236 pic16_emitcode("movx","@%s,a",r->name);
3237 pic16_emitcode("inc","%s",r->name);
3238 pic16_emitcode("mov","_spx,%s",r->name);
3239 pic16_freeAsmop (NULL,aop,ic,TRUE);
3242 pic16_emitcode("push","psw");
3244 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3252 static int wparamCmp(void *p1, void *p2)
3254 return (!strcmp((char *)p1, (char *)p2));
3257 int inWparamList(char *s)
3259 return isinSetWith(wparamList, s, wparamCmp);
3263 /*-----------------------------------------------------------------*/
3264 /* genCall - generates a call statement */
3265 /*-----------------------------------------------------------------*/
3266 static void genCall (iCode *ic)
3276 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3277 /* if caller saves & we have not saved then */
3278 // if (!ic->regsSaved)
3279 // saveRegisters(ic);
3281 /* initialise stackParms for IPUSH pushes */
3282 // stackParms = psuedoStkPtr;
3283 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3284 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3285 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3288 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3291 /* if send set is not empty the assign */
3294 int psuedoStkPtr=-1;
3295 int firstTimeThruLoop = 1;
3298 /* reverse sendSet if function is not reentrant */
3299 if(!IFFUNC_ISREENT(ftype))
3300 _G.sendSet = reverseSet(_G.sendSet);
3302 /* First figure how many parameters are getting passed */
3306 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3310 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3311 size = AOP_SIZE(IC_LEFT(sic));
3315 /* pass the last byte through WREG */
3319 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3320 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3321 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3323 if(!firstTimeThruLoop) {
3324 /* If this is not the first time we've been through the loop
3325 * then we need to save the parameter in a temporary
3326 * register. The last byte of the last parameter is
3330 // --psuedoStkPtr; // sanity check
3334 firstTimeThruLoop=0;
3336 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3341 /* all arguments are passed via stack */
3345 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3349 // pushaop(AOP(IC_LEFT(sic)), size);
3350 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3357 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3361 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3362 pushw(); /* save last parameter to stack if functions has varargs */
3366 } else use_wreg = 0;
3368 _G.stackRegSet = _G.sendSet;
3373 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3377 /* if we need to assign a result value */
3378 if ((IS_ITEMP(IC_RESULT(ic))
3379 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3380 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3381 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3384 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3387 assignResultValue(IC_RESULT(ic), 1);
3389 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3390 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3392 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3395 if(!stackParms && ic->parmBytes) {
3396 stackParms = ic->parmBytes;
3399 stackParms -= use_wreg;
3402 if(stackParms == 1) {
3403 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3405 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3406 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3408 if(STACK_MODEL_LARGE) {
3410 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3415 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3418 /* adjust the stack for parameters if required */
3419 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3422 /* if register bank was saved then pop them */
3424 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3426 /* if we hade saved some registers then unsave them */
3427 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3428 unsaveRegisters (ic);
3434 /*-----------------------------------------------------------------*/
3435 /* genPcall - generates a call by pointer statement */
3436 /* new version, created from genCall - HJD */
3437 /*-----------------------------------------------------------------*/
3438 static void genPcall (iCode *ic)
3442 symbol *retlbl = newiTempLabel(NULL);
3443 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3447 fntype = operandType( IC_LEFT(ic) )->next;
3449 /* if send set is not empty the assign */
3452 int psuedoStkPtr=-1;
3454 /* reverse sendSet if function is not reentrant */
3455 if(!IFFUNC_ISREENT(fntype))
3456 _G.sendSet = reverseSet(_G.sendSet);
3460 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3463 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3464 size = AOP_SIZE(IC_LEFT(sic));
3467 /* all parameters are passed via stack, since WREG is clobbered
3468 * by the calling sequence */
3470 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3471 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3472 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3474 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3478 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3481 _G.stackRegSet = _G.sendSet;
3485 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3487 // push return address
3488 // push $ on return stack, then replace with retlbl
3490 /* Thanks to Thorsten Klose for pointing out that the following
3491 * snippet should be interrupt safe */
3492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3493 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3495 pic16_emitpcodeNULLop(POC_PUSH);
3497 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3498 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3499 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3500 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3501 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3502 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3505 /* restore interrupt control register */
3506 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3507 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3509 /* make the call by writing the pointer into pc */
3510 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3511 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3513 // note: MOVFF to PCL not allowed
3514 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3515 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3518 /* return address is here: (X) */
3519 pic16_emitpLabelFORCE(retlbl->key);
3521 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3524 /* if we need assign a result value */
3525 if ((IS_ITEMP(IC_RESULT(ic))
3526 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3527 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3528 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3531 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3534 assignResultValue(IC_RESULT(ic), 1);
3536 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3537 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3539 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3542 // stackParms -= use_wreg;
3545 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3546 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3547 if(STACK_MODEL_LARGE) {
3549 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3554 /*-----------------------------------------------------------------*/
3555 /* resultRemat - result is rematerializable */
3556 /*-----------------------------------------------------------------*/
3557 static int resultRemat (iCode *ic)
3559 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3560 if (SKIP_IC(ic) || ic->op == IFX)
3563 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3564 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3565 if (sym->remat && !POINTER_SET(ic))
3572 #if defined(__BORLANDC__) || defined(_MSC_VER)
3573 #define STRCASECMP stricmp
3575 #define STRCASECMP strcasecmp
3579 /*-----------------------------------------------------------------*/
3580 /* inExcludeList - return 1 if the string is in exclude Reg list */
3581 /*-----------------------------------------------------------------*/
3582 static bool inExcludeList(char *s)
3584 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 if (options.excludeRegs[i] &&
3589 STRCASECMP(options.excludeRegs[i],"none") == 0)
3592 for ( i = 0 ; options.excludeRegs[i]; i++) {
3593 if (options.excludeRegs[i] &&
3594 STRCASECMP(s,options.excludeRegs[i]) == 0)
3601 /*-----------------------------------------------------------------*/
3602 /* genFunction - generated code for function entry */
3603 /*-----------------------------------------------------------------*/
3604 static void genFunction (iCode *ic)
3610 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3612 pic16_labelOffset += (max_key+4);
3617 ftype = operandType(IC_LEFT(ic));
3618 sym = OP_SYMBOL(IC_LEFT(ic));
3620 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3621 /* create an absolute section at the interrupt vector:
3622 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3627 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3629 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3630 sprintf(asymname, "ivec_%s", sym->name);
3632 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3634 /* when an interrupt is declared as naked, do not emit the special
3635 * wrapper segment at vector address. The user should take care for
3636 * this instead. -- VR */
3638 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3639 asym = newSymbol(asymname, 0);
3640 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3641 pic16_addpBlock( apb );
3643 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3644 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3645 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3646 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3647 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3649 /* mark the end of this tiny function */
3650 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3652 sprintf(asymname, "%s", sym->rname);
3658 abSym = Safe_calloc(1, sizeof(absSym));
3659 strcpy(abSym->name, asymname);
3661 switch( FUNC_INTNO(sym->type) ) {
3662 case 0: abSym->address = 0x000000; break;
3663 case 1: abSym->address = 0x000008; break;
3664 case 2: abSym->address = 0x000018; break;
3667 // fprintf(stderr, "no interrupt number is given\n");
3668 abSym->address = -1; break;
3671 /* relocate interrupt vectors if needed */
3672 if(abSym->address != -1)
3673 abSym->address += pic16_options.ivt_loc;
3675 addSet(&absSymSet, abSym);
3679 /* create the function header */
3680 pic16_emitcode(";","-----------------------------------------");
3681 pic16_emitcode(";"," function %s",sym->name);
3682 pic16_emitcode(";","-----------------------------------------");
3684 pic16_emitcode("","%s:",sym->rname);
3685 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3690 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3691 if(!strcmp(ab->name, sym->rname)) {
3692 pic16_pBlockConvert2Absolute(pb);
3698 if(IFFUNC_ISNAKED(ftype)) {
3699 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3703 /* if critical function then turn interrupts off */
3704 if (IFFUNC_ISCRITICAL(ftype)) {
3705 //pic16_emitcode("clr","ea");
3708 currFunc = sym; /* update the currFunc symbol */
3709 _G.fregsUsed = sym->regsUsed;
3710 _G.sregsAlloc = newBitVect(128);
3713 /* if this is an interrupt service routine then
3714 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3715 if (IFFUNC_ISISR(sym->type)) {
3716 _G.usefastretfie = 1; /* use shadow registers by default */
3718 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3719 if(!FUNC_ISSHADOWREGS(sym->type)) {
3720 /* do not save WREG,STATUS,BSR for high priority interrupts
3721 * because they are stored in the hardware shadow registers already */
3722 _G.usefastretfie = 0;
3723 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3724 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3725 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3728 /* these should really be optimized somehow, because not all
3729 * interrupt handlers modify them */
3730 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3731 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3732 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3733 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3735 // pic16_pBlockConvert2ISR(pb);
3738 /* emit code to setup stack frame if user enabled,
3739 * and function is not main() */
3741 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3742 if(strcmp(sym->name, "main")) {
3744 || !options.ommitFramePtr
3746 || IFFUNC_ARGS(sym->type)
3747 || FUNC_HASSTACKPARM(sym->etype)
3749 /* setup the stack frame */
3750 if(STACK_MODEL_LARGE)
3751 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3752 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3754 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3755 if(STACK_MODEL_LARGE)
3756 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3760 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3763 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3765 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3766 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3768 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3771 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3772 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3779 /* if callee-save to be used for this function
3780 * then save the registers being used in this function */
3781 // if (IFFUNC_CALLEESAVES(sym->type))
3782 if(strcmp(sym->name, "main")) {
3785 /* if any registers used */
3786 if (sym->regsUsed) {
3787 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3790 /* save the registers used */
3791 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3792 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3793 if (bitVectBitValue(sym->regsUsed,i)) {
3795 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3797 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3800 if(!pic16_regWithIdx(i)->wasUsed) {
3801 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3802 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3803 pic16_regWithIdx(i)->wasUsed = 1;
3810 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3811 for(i=0;i<sym->regsUsed->size;i++) {
3812 if(bitVectBitValue(sym->regsUsed, i)) {
3817 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3820 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3825 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3826 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3829 /*-----------------------------------------------------------------*/
3830 /* genEndFunction - generates epilogue for functions */
3831 /*-----------------------------------------------------------------*/
3832 static void genEndFunction (iCode *ic)
3834 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3838 if(IFFUNC_ISNAKED(sym->type)) {
3839 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3845 /* add code for ISCRITICAL */
3846 if(IFFUNC_ISCRITICAL(sym->type)) {
3847 /* if critical function, turn on interrupts */
3849 /* TODO: add code here -- VR */
3852 // sym->regsUsed = _G.fregsUsed;
3854 /* now we need to restore the registers */
3855 /* if any registers used */
3857 /* first restore registers that might be used for stack access */
3858 if(_G.sregsAllocSet) {
3861 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3862 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3863 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3867 if (strcmp(sym->name, "main") && sym->regsUsed) {
3870 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3871 /* restore registers used */
3872 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3873 for ( i = sym->regsUsed->size; i >= 0; i--) {
3874 if (bitVectBitValue(sym->regsUsed,i)) {
3875 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3879 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3884 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3886 if (sym->stack == 1) {
3887 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3888 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3890 // we have to add more than one...
3891 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3892 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3893 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3895 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3897 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3901 if(strcmp(sym->name, "main")) {
3903 || !options.ommitFramePtr
3905 || IFFUNC_ARGS(sym->type)
3906 || FUNC_HASSTACKPARM(sym->etype)
3908 /* restore stack frame */
3909 if(STACK_MODEL_LARGE)
3910 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3911 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3917 if (IFFUNC_ISISR(sym->type)) {
3918 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3919 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3920 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3921 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3923 if(!FUNC_ISSHADOWREGS(sym->type)) {
3924 /* do not restore interrupt vector for WREG,STATUS,BSR
3925 * for high priority interrupt, see genFunction */
3926 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3928 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3930 // _G.interruptvector = 0; /* sanity check */
3933 /* if debug then send end of function */
3934 /* if (options.debug && currFunc) */
3936 debugFile->writeEndFunction (currFunc, ic, 1);
3939 if(_G.usefastretfie)
3940 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3942 pic16_emitpcodeNULLop(POC_RETFIE);
3944 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3946 _G.usefastretfie = 0;
3950 if (IFFUNC_ISCRITICAL(sym->type)) {
3951 pic16_emitcode("setb","ea");
3954 /* if debug then send end of function */
3956 debugFile->writeEndFunction (currFunc, ic, 1);
3959 /* insert code to restore stack frame, if user enabled it
3960 * and function is not main() */
3963 pic16_emitpcodeNULLop(POC_RETURN);
3965 /* Mark the end of a function */
3966 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3970 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3972 unsigned long lit=1;
3977 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3978 if(AOP_TYPE(op) == AOP_LIT) {
3979 if(!IS_FLOAT(operandType( op ))) {
3980 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3983 unsigned long lit_int;
3987 /* take care if literal is a float */
3988 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3994 pic16_movLit2f(dest, lit);
3996 if(dest->type == PO_WREG && (offset == 0)) {
3997 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4000 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4004 /*-----------------------------------------------------------------*/
4005 /* genRet - generate code for return statement */
4006 /*-----------------------------------------------------------------*/
4007 static void genRet (iCode *ic)
4013 /* if we have no return value then
4014 * just generate the "ret" */
4019 /* we have something to return then
4020 * move the return value into place */
4021 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4022 size = AOP_SIZE(IC_LEFT(ic));
4026 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4029 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4032 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4034 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4037 /* >32-bits, setup stack and FSR0 */
4039 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4040 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4042 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4044 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4049 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4050 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4052 if(STACK_MODEL_LARGE) {
4053 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4054 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4056 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4061 /* old code, left here for reference -- VR */
4065 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4067 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4068 pic16_emitpcomment("push %s",l);
4071 DEBUGpic16_emitcode(";", "%d", __LINE__);
4072 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4073 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4075 if (strcmp(fReturn[offset],l)) {
4076 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4077 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4078 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4080 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4084 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4094 if (strcmp(fReturn[pushed],"a"))
4095 pic16_emitcode("pop",fReturn[pushed]);
4097 pic16_emitcode("pop","acc");
4103 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4106 /* generate a jump to the return label
4107 * if the next is not the return statement */
4108 if (!(ic->next && ic->next->op == LABEL
4109 && IC_LABEL(ic->next) == returnLabel)) {
4111 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4112 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4116 /*-----------------------------------------------------------------*/
4117 /* genLabel - generates a label */
4118 /*-----------------------------------------------------------------*/
4119 static void genLabel (iCode *ic)
4123 /* special case never generate */
4124 if (IC_LABEL(ic) == entryLabel)
4127 pic16_emitpLabel(IC_LABEL(ic)->key);
4128 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4131 /*-----------------------------------------------------------------*/
4132 /* genGoto - generates a goto */
4133 /*-----------------------------------------------------------------*/
4135 static void genGoto (iCode *ic)
4138 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4139 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4143 /*-----------------------------------------------------------------*/
4144 /* genMultbits :- multiplication of bits */
4145 /*-----------------------------------------------------------------*/
4146 static void genMultbits (operand *left,
4152 if(!pic16_sameRegs(AOP(result),AOP(right)))
4153 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4155 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4156 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4157 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4162 /*-----------------------------------------------------------------*/
4163 /* genMultOneByte : 8 bit multiplication & division */
4164 /*-----------------------------------------------------------------*/
4165 static void genMultOneByte (operand *left,
4171 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4172 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4174 /* (if two literals, the value is computed before) */
4175 /* if one literal, literal on the right */
4176 if (AOP_TYPE(left) == AOP_LIT){
4182 /* size is already checked in genMult == 1 */
4183 // size = AOP_SIZE(result);
4185 if (AOP_TYPE(right) == AOP_LIT){
4186 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4187 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4188 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4189 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4191 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4192 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4193 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4194 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4197 pic16_genMult8X8_8 (left, right,result);
4200 /*-----------------------------------------------------------------*/
4201 /* genMultOneWord : 16 bit multiplication */
4202 /*-----------------------------------------------------------------*/
4203 static void genMultOneWord (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 checked already == 2 */
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_genMult16X16_16(left, right,result);
4237 /*-----------------------------------------------------------------*/
4238 /* genMultOneLong : 32 bit multiplication */
4239 /*-----------------------------------------------------------------*/
4240 static void genMultOneLong (operand *left,
4245 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4246 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4248 /* (if two literals, the value is computed before)
4249 * if one literal, literal on the right */
4250 if (AOP_TYPE(left) == AOP_LIT){
4256 /* size is checked already == 4 */
4257 // size = AOP_SIZE(result);
4259 if (AOP_TYPE(right) == AOP_LIT) {
4260 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4261 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4262 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4263 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4265 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4266 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4267 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4268 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4271 pic16_genMult32X32_32(left, right,result);
4276 /*-----------------------------------------------------------------*/
4277 /* genMult - generates code for multiplication */
4278 /*-----------------------------------------------------------------*/
4279 static void genMult (iCode *ic)
4281 operand *left = IC_LEFT(ic);
4282 operand *right = IC_RIGHT(ic);
4283 operand *result= IC_RESULT(ic);
4286 /* assign the amsops */
4287 pic16_aopOp (left,ic,FALSE);
4288 pic16_aopOp (right,ic,FALSE);
4289 pic16_aopOp (result,ic,TRUE);
4291 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4293 /* special cases first *
4295 if (AOP_TYPE(left) == AOP_CRY
4296 && AOP_TYPE(right)== AOP_CRY) {
4297 genMultbits(left,right,result);
4301 /* if both are of size == 1 */
4302 if(AOP_SIZE(left) == 1
4303 && AOP_SIZE(right) == 1) {
4304 genMultOneByte(left,right,result);
4308 /* if both are of size == 2 */
4309 if(AOP_SIZE(left) == 2
4310 && AOP_SIZE(right) == 2) {
4311 genMultOneWord(left, right, result);
4315 /* if both are of size == 4 */
4316 if(AOP_SIZE(left) == 4
4317 && AOP_SIZE(right) == 4) {
4318 genMultOneLong(left, right, result);
4322 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4325 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4326 /* should have been converted to function call */
4330 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4331 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4332 pic16_freeAsmop(result,NULL,ic,TRUE);
4335 /*-----------------------------------------------------------------*/
4336 /* genDivbits :- division of bits */
4337 /*-----------------------------------------------------------------*/
4338 static void genDivbits (operand *left,
4345 /* the result must be bit */
4346 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4347 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4351 pic16_emitcode("div","ab");
4352 pic16_emitcode("rrc","a");
4353 pic16_aopPut(AOP(result),"c",0);
4356 /*-----------------------------------------------------------------*/
4357 /* genDivOneByte : 8 bit division */
4358 /*-----------------------------------------------------------------*/
4359 static void genDivOneByte (operand *left,
4363 sym_link *opetype = operandType(result);
4368 /* result = divident / divisor
4369 * - divident may be a register or a literal,
4370 * - divisor may be a register or a literal,
4371 * so there are 3 cases (literal / literal is optimized
4372 * by the front-end) to handle.
4373 * In addition we must handle signed and unsigned, which
4374 * result in 6 final different cases -- VR */
4378 size = AOP_SIZE(result) - 1;
4380 /* signed or unsigned */
4381 if (SPEC_USIGN(opetype)) {
4382 pCodeOp *pct1, /* count */
4385 symbol *label1, *label2, *label3;;
4388 /* unsigned is easy */
4390 pct1 = pic16_popGetTempReg(1);
4391 pct2 = pic16_popGetTempReg(1);
4392 pct3 = pic16_popGetTempReg(1);
4394 label1 = newiTempLabel(NULL);
4395 label2 = newiTempLabel(NULL);
4396 label3 = newiTempLabel(NULL);
4398 /* the following algorithm is extracted from divuint.c */
4400 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4401 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4403 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4405 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4407 pic16_emitpLabel(label1->key);
4410 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4414 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4418 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4420 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4421 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4423 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4424 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4425 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4427 pic16_emitpLabel( label3->key );
4428 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4429 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4433 pic16_emitpLabel(label2->key);
4434 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4435 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4436 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4438 /* result is in wreg */
4439 if(AOP_TYPE(result) != AOP_ACC)
4440 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4442 pic16_popReleaseTempReg( pct3, 1);
4443 pic16_popReleaseTempReg( pct2, 1);
4444 pic16_popReleaseTempReg( pct1, 1);
4449 /* signed is a little bit more difficult */
4451 /* save the signs of the operands */
4452 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4454 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4455 pic16_emitcode("push","acc"); /* save it on the stack */
4457 /* now sign adjust for both left & right */
4458 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4460 lbl = newiTempLabel(NULL);
4461 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4462 pic16_emitcode("cpl","a");
4463 pic16_emitcode("inc","a");
4464 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4465 pic16_emitcode("mov","b,a");
4467 /* sign adjust left side */
4468 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4471 lbl = newiTempLabel(NULL);
4472 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4473 pic16_emitcode("cpl","a");
4474 pic16_emitcode("inc","a");
4475 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4477 /* now the division */
4478 pic16_emitcode("div","ab");
4479 /* we are interested in the lower order
4481 pic16_emitcode("mov","b,a");
4482 lbl = newiTempLabel(NULL);
4483 pic16_emitcode("pop","acc");
4484 /* if there was an over flow we don't
4485 adjust the sign of the result */
4486 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4487 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4489 pic16_emitcode("clr","a");
4490 pic16_emitcode("subb","a,b");
4491 pic16_emitcode("mov","b,a");
4492 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4494 /* now we are done */
4495 pic16_aopPut(AOP(result),"b",0);
4497 pic16_emitcode("mov","c,b.7");
4498 pic16_emitcode("subb","a,acc");
4501 pic16_aopPut(AOP(result),"a",offset++);
4505 /*-----------------------------------------------------------------*/
4506 /* genDiv - generates code for division */
4507 /*-----------------------------------------------------------------*/
4508 static void genDiv (iCode *ic)
4510 operand *left = IC_LEFT(ic);
4511 operand *right = IC_RIGHT(ic);
4512 operand *result= IC_RESULT(ic);
4515 /* Division is a very lengthy algorithm, so it is better
4516 * to call support routines than inlining algorithm.
4517 * Division functions written here just in case someone
4518 * wants to inline and not use the support libraries -- VR */
4522 /* assign the amsops */
4523 pic16_aopOp (left,ic,FALSE);
4524 pic16_aopOp (right,ic,FALSE);
4525 pic16_aopOp (result,ic,TRUE);
4527 /* special cases first */
4529 if (AOP_TYPE(left) == AOP_CRY &&
4530 AOP_TYPE(right)== AOP_CRY) {
4531 genDivbits(left,right,result);
4535 /* if both are of size == 1 */
4536 if (AOP_SIZE(left) == 1 &&
4537 AOP_SIZE(right) == 1 ) {
4538 genDivOneByte(left,right,result);
4542 /* should have been converted to function call */
4545 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4546 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4547 pic16_freeAsmop(result,NULL,ic,TRUE);
4550 /*-----------------------------------------------------------------*/
4551 /* genModbits :- modulus of bits */
4552 /*-----------------------------------------------------------------*/
4553 static void genModbits (operand *left,
4561 werror(W_POSSBUG2, __FILE__, __LINE__);
4562 /* the result must be bit */
4563 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4564 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4568 pic16_emitcode("div","ab");
4569 pic16_emitcode("mov","a,b");
4570 pic16_emitcode("rrc","a");
4571 pic16_aopPut(AOP(result),"c",0);
4574 /*-----------------------------------------------------------------*/
4575 /* genModOneByte : 8 bit modulus */
4576 /*-----------------------------------------------------------------*/
4577 static void genModOneByte (operand *left,
4581 sym_link *opetype = operandType(result);
4586 werror(W_POSSBUG2, __FILE__, __LINE__);
4588 /* signed or unsigned */
4589 if (SPEC_USIGN(opetype)) {
4590 /* unsigned is easy */
4591 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4592 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4594 pic16_emitcode("div","ab");
4595 pic16_aopPut(AOP(result),"b",0);
4599 /* signed is a little bit more difficult */
4601 /* save the signs of the operands */
4602 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4605 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4606 pic16_emitcode("push","acc"); /* save it on the stack */
4608 /* now sign adjust for both left & right */
4609 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4612 lbl = newiTempLabel(NULL);
4613 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4614 pic16_emitcode("cpl","a");
4615 pic16_emitcode("inc","a");
4616 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4617 pic16_emitcode("mov","b,a");
4619 /* sign adjust left side */
4620 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4623 lbl = newiTempLabel(NULL);
4624 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4625 pic16_emitcode("cpl","a");
4626 pic16_emitcode("inc","a");
4627 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4629 /* now the multiplication */
4630 pic16_emitcode("div","ab");
4631 /* we are interested in the lower order
4633 lbl = newiTempLabel(NULL);
4634 pic16_emitcode("pop","acc");
4635 /* if there was an over flow we don't
4636 adjust the sign of the result */
4637 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4638 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4640 pic16_emitcode("clr","a");
4641 pic16_emitcode("subb","a,b");
4642 pic16_emitcode("mov","b,a");
4643 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4645 /* now we are done */
4646 pic16_aopPut(AOP(result),"b",0);
4650 /*-----------------------------------------------------------------*/
4651 /* genMod - generates code for division */
4652 /*-----------------------------------------------------------------*/
4653 static void genMod (iCode *ic)
4655 operand *left = IC_LEFT(ic);
4656 operand *right = IC_RIGHT(ic);
4657 operand *result= IC_RESULT(ic);
4661 /* assign the amsops */
4662 pic16_aopOp (left,ic,FALSE);
4663 pic16_aopOp (right,ic,FALSE);
4664 pic16_aopOp (result,ic,TRUE);
4666 /* special cases first */
4668 if (AOP_TYPE(left) == AOP_CRY &&
4669 AOP_TYPE(right)== AOP_CRY) {
4670 genModbits(left,right,result);
4674 /* if both are of size == 1 */
4675 if (AOP_SIZE(left) == 1 &&
4676 AOP_SIZE(right) == 1 ) {
4677 genModOneByte(left,right,result);
4681 /* should have been converted to function call */
4685 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4686 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4687 pic16_freeAsmop(result,NULL,ic,TRUE);
4690 /*-----------------------------------------------------------------*/
4691 /* genIfxJump :- will create a jump depending on the ifx */
4692 /*-----------------------------------------------------------------*/
4694 note: May need to add parameter to indicate when a variable is in bit space.
4696 static void genIfxJump (iCode *ic, char *jval)
4700 /* if true label then we jump if condition
4702 if ( IC_TRUE(ic) ) {
4704 if(strcmp(jval,"a") == 0)
4706 else if (strcmp(jval,"c") == 0)
4709 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4710 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4713 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4714 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4718 /* false label is present */
4719 if(strcmp(jval,"a") == 0)
4721 else if (strcmp(jval,"c") == 0)
4724 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4725 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4728 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4729 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4734 /* mark the icode as generated */
4738 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4742 /* if true label then we jump if condition
4744 if ( IC_TRUE(ic) ) {
4745 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4746 pic16_emitpcode(POC_BTFSC, jop);
4748 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4749 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4752 /* false label is present */
4753 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4754 pic16_emitpcode(POC_BTFSS, jop);
4756 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4757 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4761 /* mark the icode as generated */
4768 /*-----------------------------------------------------------------*/
4770 /*-----------------------------------------------------------------*/
4771 static void genSkip(iCode *ifx,int status_bit)
4773 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4777 if ( IC_TRUE(ifx) ) {
4778 switch(status_bit) {
4793 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4794 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4798 switch(status_bit) {
4812 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4813 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4820 /*-----------------------------------------------------------------*/
4822 /*-----------------------------------------------------------------*/
4823 static void genSkipc(resolvedIfx *rifx)
4825 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4835 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4836 rifx->generated = 1;
4839 #if !(USE_SIMPLE_GENCMP)
4840 /*-----------------------------------------------------------------*/
4842 /*-----------------------------------------------------------------*/
4843 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4845 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4850 if( (rifx->condition ^ invert_condition) & 1)
4855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4856 rifx->generated = 1;
4861 /*-----------------------------------------------------------------*/
4863 /*-----------------------------------------------------------------*/
4864 static void genSkipz(iCode *ifx, int condition)
4875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4877 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4880 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4882 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4887 #if !(USE_SIMPLE_GENCMP)
4888 /*-----------------------------------------------------------------*/
4890 /*-----------------------------------------------------------------*/
4891 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4897 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4899 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4902 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4903 rifx->generated = 1;
4908 /*-----------------------------------------------------------------*/
4909 /* genChkZeroes :- greater or less than comparison */
4910 /* For each byte in a literal that is zero, inclusive or the */
4911 /* the corresponding byte in the operand with W */
4912 /* returns true if any of the bytes are zero */
4913 /*-----------------------------------------------------------------*/
4914 static int genChkZeroes(operand *op, int lit, int size)
4921 i = (lit >> (size*8)) & 0xff;
4925 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4927 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4937 /*-----------------------------------------------------------------*/
4938 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4939 /* aop (if it's NOT a literal) or from lit (if */
4940 /* aop is a literal) */
4941 /*-----------------------------------------------------------------*/
4942 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4943 if (aop->type == AOP_LIT) {
4944 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4946 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4950 /*-----------------------------------------------------------------*/
4951 /* genCmp :- greater or less than comparison */
4952 /*-----------------------------------------------------------------*/
4954 #if USE_SIMPLE_GENCMP /* { */
4956 /* genCmp performs a left < right comparison, stores
4957 * the outcome in result (if != NULL) and generates
4958 * control flow code for the ifx (if != NULL).
4960 * This version leaves in sequences like
4961 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4962 * which should be optmized by the peephole
4963 * optimizer - RN 2005-01-01 */
4964 static void genCmp (operand *left,operand *right,
4965 operand *result, iCode *ifx, int sign)
4978 assert (left && right);
4979 assert (AOP_SIZE(left) == AOP_SIZE(right));
4981 size = AOP_SIZE(right) - 1;
4982 mask = (0x100UL << (size*8)) - 1;
4983 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4988 resolveIfx (&rIfx, ifx);
4990 /* handle for special cases */
4991 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4994 /**********************************************************************
4995 * handle bits - bit compares are promoted to int compares seemingly! *
4996 **********************************************************************/
4998 // THIS IS COMPLETELY UNTESTED!
4999 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5000 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5001 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5002 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5005 // 1 < {0,1} is false --> clear C by skipping the next instruction
5006 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5007 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5008 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5009 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5010 emitCLRC; // only skipped for left=0 && right=1
5012 goto correct_result_in_carry;
5016 /*************************************************
5017 * make sure that left is register (or the like) *
5018 *************************************************/
5019 if (!isAOP_REGlike(left)) {
5020 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5021 assert (isAOP_LIT(left));
5022 assert (isAOP_REGlike(right));
5023 // swap left and right
5024 // left < right <==> right > left <==> (right >= left + 1)
5025 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5027 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5028 // MAXVALUE < right? always false
5029 if (performedLt) emitCLRC; else emitSETC;
5030 goto correct_result_in_carry;
5033 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5034 // that's why we handled it above.
5041 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5042 } else if (isAOP_LIT(right)) {
5043 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5046 assert (isAOP_REGlike(left)); // left must be register or the like
5047 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5049 /*************************************************
5050 * special cases go here *
5051 *************************************************/
5053 if (isAOP_LIT(right)) {
5055 // unsigned comparison to a literal
5056 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5058 // unsigned left < 0? always false
5059 if (performedLt) emitCLRC; else emitSETC;
5060 goto correct_result_in_carry;
5063 // signed comparison to a literal
5064 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5065 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5066 // signed left < 0x80000000? always false
5067 if (performedLt) emitCLRC; else emitSETC;
5068 goto correct_result_in_carry;
5069 } else if (lit == 0) {
5070 // compare left < 0; set CARRY if SIGNBIT(left) is set
5071 if (performedLt) emitSETC; else emitCLRC;
5072 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5073 if (performedLt) emitCLRC; else emitSETC;
5074 goto correct_result_in_carry;
5077 } // right is literal
5079 /*************************************************
5080 * perform a general case comparison *
5081 * make sure we get CARRY==1 <==> left >= right *
5082 *************************************************/
5083 // compare most significant bytes
5084 //DEBUGpc ("comparing bytes at offset %d", size);
5086 // unsigned comparison
5087 mov2w_regOrLit (AOP(right), lit, size);
5088 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5090 // signed comparison
5091 // (add 2^n to both operands then perform an unsigned comparison)
5092 if (isAOP_LIT(right)) {
5093 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5094 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5096 if (litbyte == 0x80) {
5097 // left >= 0x80 -- always true, but more bytes to come
5098 pic16_mov2w (AOP(left), size);
5099 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5102 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5103 pic16_mov2w (AOP(left), size);
5104 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5105 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5108 /* using PRODL as a temporary register here */
5109 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5110 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5111 pic16_mov2w (AOP(left), size);
5112 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5113 pic16_emitpcode (POC_MOVWF, pctemp);
5114 pic16_mov2w (AOP(right), size);
5115 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5116 pic16_emitpcode (POC_SUBFW, pctemp);
5117 //pic16_popReleaseTempReg(pctemp, 1);
5121 // compare remaining bytes (treat as unsigned case from above)
5122 templbl = newiTempLabel ( NULL );
5125 //DEBUGpc ("comparing bytes at offset %d", offs);
5126 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5127 mov2w_regOrLit (AOP(right), lit, offs);
5128 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5130 pic16_emitpLabel (templbl->key);
5131 goto result_in_carry;
5135 /****************************************************
5136 * now CARRY contains the result of the comparison: *
5137 * SUBWF sets CARRY iff *
5138 * F-W >= 0 <==> F >= W <==> !(F < W) *
5139 * (F=left, W=right) *
5140 ****************************************************/
5143 if (result && AOP_TYPE(result) != AOP_CRY) {
5144 // value will be stored
5147 // value wil only be used in the following genSkipc()
5148 rIfx.condition ^= 1;
5152 correct_result_in_carry:
5154 // assign result to variable (if neccessary)
5155 if (result && AOP_TYPE(result) != AOP_CRY) {
5156 //DEBUGpc ("assign result");
5157 size = AOP_SIZE(result);
5159 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5161 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5164 // perform conditional jump
5166 //DEBUGpc ("generate control flow");
5175 static void genCmp (operand *left,operand *right,
5176 operand *result, iCode *ifx, int sign)
5178 int size; //, offset = 0 ;
5179 unsigned long lit = 0L,i = 0;
5180 resolvedIfx rFalseIfx;
5181 // resolvedIfx rTrueIfx;
5183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5186 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5187 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5193 resolveIfx(&rFalseIfx,ifx);
5194 truelbl = newiTempLabel(NULL);
5195 size = max(AOP_SIZE(left),AOP_SIZE(right));
5197 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5201 /* if literal is on the right then swap with left */
5202 if ((AOP_TYPE(right) == AOP_LIT)) {
5203 operand *tmp = right ;
5204 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5205 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5208 lit = (lit - 1) & mask;
5211 rFalseIfx.condition ^= 1;
5214 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5215 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5219 //if(IC_TRUE(ifx) == NULL)
5220 /* if left & right are bit variables */
5221 if (AOP_TYPE(left) == AOP_CRY &&
5222 AOP_TYPE(right) == AOP_CRY ) {
5223 assert (0 && "bit variables used in genCmp");
5224 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5225 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5227 /* subtract right from left if at the
5228 end the carry flag is set then we know that
5229 left is greater than right */
5231 symbol *lbl = newiTempLabel(NULL);
5234 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5235 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5239 if(AOP_TYPE(right) == AOP_LIT) {
5241 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5243 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5250 genSkipCond(&rFalseIfx,left,size-1,7);
5252 /* no need to compare to 0...*/
5253 /* NOTE: this is a de-generate compare that most certainly
5254 * creates some dead code. */
5255 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5257 if(ifx) ifx->generated = 1;
5264 //i = (lit >> (size*8)) & 0xff;
5265 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5267 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5269 i = ((0-lit) & 0xff);
5272 /* lit is 0x7f, all signed chars are less than
5273 * this except for 0x7f itself */
5274 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5275 genSkipz2(&rFalseIfx,0);
5277 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5278 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5279 genSkipc(&rFalseIfx);
5284 genSkipz2(&rFalseIfx,1);
5286 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5287 genSkipc(&rFalseIfx);
5291 if(ifx) ifx->generated = 1;
5295 /* chars are out of the way. now do ints and longs */
5298 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5305 genSkipCond(&rFalseIfx,left,size,7);
5306 if(ifx) ifx->generated = 1;
5311 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5313 //rFalseIfx.condition ^= 1;
5314 //genSkipCond(&rFalseIfx,left,size,7);
5315 //rFalseIfx.condition ^= 1;
5317 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5318 if(rFalseIfx.condition)
5319 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5321 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5323 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5324 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5325 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5328 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5330 if(rFalseIfx.condition) {
5332 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5338 genSkipc(&rFalseIfx);
5339 pic16_emitpLabel(truelbl->key);
5340 if(ifx) ifx->generated = 1;
5347 if( (lit & 0xff) == 0) {
5348 /* lower byte is zero */
5349 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5350 i = ((lit >> 8) & 0xff) ^0x80;
5351 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5352 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5353 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5354 genSkipc(&rFalseIfx);
5357 if(ifx) ifx->generated = 1;
5362 /* Special cases for signed longs */
5363 if( (lit & 0xffffff) == 0) {
5364 /* lower byte is zero */
5365 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5366 i = ((lit >> 8*3) & 0xff) ^0x80;
5367 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5368 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5369 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5370 genSkipc(&rFalseIfx);
5373 if(ifx) ifx->generated = 1;
5381 if(lit & (0x80 << (size*8))) {
5382 /* lit is negative */
5383 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5385 //genSkipCond(&rFalseIfx,left,size,7);
5387 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5389 if(rFalseIfx.condition)
5390 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5392 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5396 /* lit is positive */
5397 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5398 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5399 if(rFalseIfx.condition)
5400 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5402 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5407 This works, but is only good for ints.
5408 It also requires a "known zero" register.
5409 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5410 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5411 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5412 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5413 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5414 genSkipc(&rFalseIfx);
5416 pic16_emitpLabel(truelbl->key);
5417 if(ifx) ifx->generated = 1;
5421 /* There are no more special cases, so perform a general compare */
5423 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5424 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5428 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5430 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5432 //rFalseIfx.condition ^= 1;
5433 genSkipc(&rFalseIfx);
5435 pic16_emitpLabel(truelbl->key);
5437 if(ifx) ifx->generated = 1;
5444 /* sign is out of the way. So now do an unsigned compare */
5445 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5448 /* General case - compare to an unsigned literal on the right.*/
5450 i = (lit >> (size*8)) & 0xff;
5451 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5452 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5454 i = (lit >> (size*8)) & 0xff;
5457 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5459 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5461 /* this byte of the lit is zero,
5462 *if it's not the last then OR in the variable */
5464 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5469 pic16_emitpLabel(lbl->key);
5470 // pic16_emitpLabel(truelbl->key);
5471 //if(emitFinalCheck)
5472 genSkipc(&rFalseIfx);
5474 pic16_emitpLabel(truelbl->key);
5476 if(ifx) ifx->generated = 1;
5483 if(AOP_TYPE(left) == AOP_LIT) {
5484 //symbol *lbl = newiTempLabel(NULL);
5486 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5489 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5492 if((lit == 0) && (sign == 0)){
5495 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5497 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5499 genSkipz2(&rFalseIfx,0);
5500 if(ifx) ifx->generated = 1;
5507 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5508 /* degenerate compare can never be true */
5509 if(rFalseIfx.condition == 0)
5510 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5512 if(ifx) ifx->generated = 1;
5517 /* signed comparisons to a literal byte */
5519 int lp1 = (lit+1) & 0xff;
5521 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5524 rFalseIfx.condition ^= 1;
5525 genSkipCond(&rFalseIfx,right,0,7);
5528 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5529 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5530 genSkipz2(&rFalseIfx,1);
5533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5534 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5535 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5536 rFalseIfx.condition ^= 1;
5537 genSkipc(&rFalseIfx);
5541 /* unsigned comparisons to a literal byte */
5543 switch(lit & 0xff ) {
5545 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5546 genSkipz2(&rFalseIfx,0);
5549 rFalseIfx.condition ^= 1;
5550 genSkipCond(&rFalseIfx,right,0,7);
5554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5555 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5557 rFalseIfx.condition ^= 1;
5558 if (AOP_TYPE(result) == AOP_CRY)
5559 genSkipc(&rFalseIfx);
5561 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5562 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5568 if(ifx) ifx->generated = 1;
5569 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5575 /* Size is greater than 1 */
5583 /* this means lit = 0xffffffff, or -1 */
5586 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5587 rFalseIfx.condition ^= 1;
5588 genSkipCond(&rFalseIfx,right,size,7);
5589 if(ifx) ifx->generated = 1;
5591 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5600 if(rFalseIfx.condition) {
5601 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5602 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5605 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5607 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5611 if(rFalseIfx.condition) {
5612 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5613 pic16_emitpLabel(truelbl->key);
5615 rFalseIfx.condition ^= 1;
5616 genSkipCond(&rFalseIfx,right,s,7);
5619 if(ifx) ifx->generated = 1;
5621 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5627 if((size == 1) && (0 == (lp1&0xff))) {
5628 /* lower byte of signed word is zero */
5629 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5630 i = ((lp1 >> 8) & 0xff) ^0x80;
5631 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5632 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5633 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5635 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5637 if(ifx) ifx->generated = 1;
5640 rFalseIfx.condition ^= 1;
5641 genSkipc(&rFalseIfx);
5642 if(ifx) ifx->generated = 1;
5648 if(lit & (0x80 << (size*8))) {
5649 /* Lit is less than zero */
5650 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5651 //rFalseIfx.condition ^= 1;
5652 //genSkipCond(&rFalseIfx,left,size,7);
5653 //rFalseIfx.condition ^= 1;
5654 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5655 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5657 if(rFalseIfx.condition)
5658 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5660 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5664 /* Lit is greater than or equal to zero */
5665 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5666 //rFalseIfx.condition ^= 1;
5667 //genSkipCond(&rFalseIfx,right,size,7);
5668 //rFalseIfx.condition ^= 1;
5670 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5671 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5673 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5674 if(rFalseIfx.condition)
5675 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5677 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5681 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5682 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5686 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5688 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5690 rFalseIfx.condition ^= 1;
5691 //rFalseIfx.condition = 1;
5692 genSkipc(&rFalseIfx);
5694 pic16_emitpLabel(truelbl->key);
5696 if(ifx) ifx->generated = 1;
5699 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5706 /* compare word or long to an unsigned literal on the right.*/
5711 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5714 break; /* handled above */
5717 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5719 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5720 genSkipz2(&rFalseIfx,0);
5724 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5726 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5729 if(rFalseIfx.condition)
5730 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5732 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5735 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5736 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5738 rFalseIfx.condition ^= 1;
5739 genSkipc(&rFalseIfx);
5742 pic16_emitpLabel(truelbl->key);
5744 if(ifx) ifx->generated = 1;
5746 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5754 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5755 i = (lit >> (size*8)) & 0xff;
5757 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5761 i = (lit >> (size*8)) & 0xff;
5764 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5766 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5768 /* this byte of the lit is zero,
5769 * if it's not the last then OR in the variable */
5771 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5776 pic16_emitpLabel(lbl->key);
5778 rFalseIfx.condition ^= 1;
5780 genSkipc(&rFalseIfx);
5784 pic16_emitpLabel(truelbl->key);
5785 if(ifx) ifx->generated = 1;
5787 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5793 /* Compare two variables */
5795 DEBUGpic16_emitcode(";sign","%d",sign);
5799 /* Sigh. thus sucks... */
5803 pctemp = pic16_popGetTempReg(1);
5804 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5805 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5806 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5807 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5808 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5809 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5810 pic16_popReleaseTempReg(pctemp, 1);
5812 /* Signed char comparison */
5813 /* Special thanks to Nikolai Golovchenko for this snippet */
5814 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5815 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5816 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5817 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5818 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5819 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5821 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5822 genSkipc(&rFalseIfx);
5824 if(ifx) ifx->generated = 1;
5826 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5834 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5835 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5839 /* The rest of the bytes of a multi-byte compare */
5843 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5846 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5847 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5852 pic16_emitpLabel(lbl->key);
5854 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5855 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5856 (AOP_TYPE(result) == AOP_REG)) {
5857 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5860 genSkipc(&rFalseIfx);
5862 //genSkipc(&rFalseIfx);
5863 if(ifx) ifx->generated = 1;
5866 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5874 if ((AOP_TYPE(result) != AOP_CRY)
5875 && AOP_SIZE(result)) {
5876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5878 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5880 pic16_outBitC(result);
5882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5883 /* if the result is used in the next
5884 ifx conditional branch then generate
5885 code a little differently */
5887 genIfxJump (ifx,"c");
5889 pic16_outBitC(result);
5890 /* leave the result in acc */
5895 #elif 0 /* VR version of genCmp() */ /* } else { */
5897 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5898 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5899 operand *result, int offset, int invert_op)
5903 /* check condition, > or < ?? */
5904 if(rIfx->condition != 0)invert_op ^= 1;
5906 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5908 if(!ifx)invert_op ^= 1;
5910 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5911 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5914 if(!invert_op)return POC_CPFSGT;
5915 else return POC_CPFSLT;
5918 static int compareAopfirstpass=1;
5920 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5921 operand *oper, int offset, operand *result,
5922 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5928 /* invert if there is a result to be loaded, in order to fit,
5929 * SETC/CLRC sequence */
5930 if(AOP_SIZE(result))invert_op ^= 1;
5932 // if(sign && !offset)invert_op ^= 1;
5934 // if(sign)invert_op ^= 1;
5936 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5938 if(AOP_SIZE(result) && compareAopfirstpass) {
5941 pic16_emitpcode(POC_SETF, pcop2);
5946 pic16_emitpcode(POC_CLRF, pcop2);
5952 compareAopfirstpass = 0;
5954 /* there is a bug when comparing operands with size > 1,
5955 * because higher bytes can be equal and test should be performed
5956 * to the next lower byte, current algorithm, considers operands
5957 * inequal in these cases! -- VR 20041107 */
5961 pic16_emitpcode(op, pcop);
5963 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5966 if((!sign || !offset) && AOP_SIZE(result)) {
5969 pic16_emitpcode(POC_CLRF, pcop2);
5974 pic16_emitpcode(POC_SETF, pcop2);
5979 /* don't emit final branch (offset == 0) */
5983 pic16_emitpcode(POC_RRCF, pcop2);
5985 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5988 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5989 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5990 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5992 truelbl = newiTempLabel( NULL );
5993 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5994 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5995 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5997 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5998 pic16_emitpLabel(truelbl->key);
6000 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6005 static void genCmp (operand *left, operand *right,
6006 operand *result, iCode *ifx, int sign)
6010 resolvedIfx rFalseIfx;
6011 symbol *falselbl, *tlbl;
6015 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6017 resolveIfx(&rFalseIfx, ifx);
6018 size = max(AOP_SIZE(left), AOP_SIZE(right));
6020 /* if left & right are bit variables */
6021 if(AOP_TYPE(left) == AOP_CRY
6022 && AOP_TYPE(right) == AOP_CRY ) {
6024 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6025 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6027 werror(W_POSSBUG2, __FILE__, __LINE__);
6031 /* if literal is on the right then swap with left */
6032 if((AOP_TYPE(right) == AOP_LIT)) {
6033 operand *tmp = right ;
6034 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6036 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6038 // lit = (lit - 1) & mask;
6041 rFalseIfx.condition ^= 1; /* reverse compare */
6043 if ((AOP_TYPE(left) == AOP_LIT)) {
6044 /* float compares are handled by support functions */
6045 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6048 /* actual comparing algorithm */
6049 // size = AOP_SIZE( right );
6051 falselbl = newiTempLabel( NULL );
6052 if(AOP_TYPE(left) == AOP_LIT) {
6053 /* compare to literal */
6054 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6057 pCodeOp *pct, *pct2;
6060 /* signed compare */
6061 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6063 /* using PRODL:PRODH as a temporary register here */
6064 pct = pic16_popCopyReg(&pic16_pc_prodl);
6065 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6066 tlbl = newiTempLabel( NULL );
6068 /* first compare signs:
6069 * a. if both are positive, compare just like unsigned
6070 * b. if both are negative, invert cmpop, compare just like unsigned
6071 * c. if different signs, determine the result directly */
6077 tlbl1 = newiTempLabel( NULL );
6078 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6082 /* literal is zero or positive:
6083 * a. if carry is zero, too, continue compare,
6084 * b. if carry is set, then continue depending on cmpop ^ condition:
6085 * 1. '<' return false (literal < variable),
6086 * 2. '>' return true (literal > variable) */
6087 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6088 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6091 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6092 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6096 /* literal is negative:
6097 * a. if carry is set, too, continue compare,
6098 * b. if carry is zero, then continue depending on cmpop ^ condition:
6099 * 1. '<' return true (literal < variable),
6100 * 2. '>' return false (literal > variable) */
6101 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6102 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6104 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6105 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6110 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6112 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6113 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6118 pic16_emitpLabel( tlbl1->key );
6121 compareAopfirstpass=1;
6122 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6123 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6124 // pic16_emitpcode(POC_MOVWF, pct);
6126 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6127 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6128 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6129 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6133 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6134 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6135 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6136 // pic16_emitpcode(POC_MOVWF, pct);
6138 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6139 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6140 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6141 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6142 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6145 if(ifx)ifx->generated = 1;
6147 if(AOP_SIZE(result)) {
6148 pic16_emitpLabel(tlbl->key);
6149 pic16_emitpLabel(falselbl->key);
6150 pic16_outBitOp( result, pct2 );
6152 pic16_emitpLabel(tlbl->key);
6156 /* unsigned compare */
6157 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6159 compareAopfirstpass=1;
6162 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6163 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6166 if(ifx)ifx->generated = 1;
6168 if(AOP_SIZE(result)) {
6169 pic16_emitpLabel(falselbl->key);
6170 pic16_outBitC( result );
6175 /* compare registers */
6176 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6180 pCodeOp *pct, *pct2;
6182 /* signed compare */
6183 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6185 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6186 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6187 tlbl = newiTempLabel( NULL );
6189 compareAopfirstpass=1;
6192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6193 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6194 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6195 pic16_emitpcode(POC_MOVWF, pct);
6197 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6198 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6199 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6201 /* WREG already holds left + 0x80 */
6202 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6205 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6206 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6207 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6208 pic16_emitpcode(POC_MOVWF, pct);
6210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6211 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214 /* WREG already holds left + 0x80 */
6215 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6216 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6219 if(ifx)ifx->generated = 1;
6221 if(AOP_SIZE(result)) {
6222 pic16_emitpLabel(tlbl->key);
6223 pic16_emitpLabel(falselbl->key);
6224 pic16_outBitOp( result, pct2 );
6226 pic16_emitpLabel(tlbl->key);
6230 /* unsigned compare */
6231 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6233 compareAopfirstpass=1;
6236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6237 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6241 if(ifx)ifx->generated = 1;
6242 if(AOP_SIZE(result)) {
6244 pic16_emitpLabel(falselbl->key);
6245 pic16_outBitC( result );
6256 /*-----------------------------------------------------------------*/
6257 /* genCmpGt :- greater than comparison */
6258 /*-----------------------------------------------------------------*/
6259 static void genCmpGt (iCode *ic, iCode *ifx)
6261 operand *left, *right, *result;
6262 sym_link *letype , *retype;
6268 right= IC_RIGHT(ic);
6269 result = IC_RESULT(ic);
6271 letype = getSpec(operandType(left));
6272 retype =getSpec(operandType(right));
6273 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6274 /* assign the amsops */
6275 pic16_aopOp (left,ic,FALSE);
6276 pic16_aopOp (right,ic,FALSE);
6277 pic16_aopOp (result,ic,TRUE);
6279 genCmp(right, left, result, ifx, sign);
6281 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6282 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6283 pic16_freeAsmop(result,NULL,ic,TRUE);
6286 /*-----------------------------------------------------------------*/
6287 /* genCmpLt - less than comparisons */
6288 /*-----------------------------------------------------------------*/
6289 static void genCmpLt (iCode *ic, iCode *ifx)
6291 operand *left, *right, *result;
6292 sym_link *letype , *retype;
6298 right= IC_RIGHT(ic);
6299 result = IC_RESULT(ic);
6301 letype = getSpec(operandType(left));
6302 retype =getSpec(operandType(right));
6303 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6305 /* assign the amsops */
6306 pic16_aopOp (left,ic,FALSE);
6307 pic16_aopOp (right,ic,FALSE);
6308 pic16_aopOp (result,ic,TRUE);
6310 genCmp(left, right, result, ifx, sign);
6312 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6313 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6314 pic16_freeAsmop(result,NULL,ic,TRUE);
6319 // FIXME reenable literal optimisation when the pic16 port is stable
6321 /*-----------------------------------------------------------------*/
6322 /* genc16bit2lit - compare a 16 bit value to a literal */
6323 /*-----------------------------------------------------------------*/
6324 static void genc16bit2lit(operand *op, int lit, int offset)
6328 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6329 if( (lit&0xff) == 0)
6334 switch( BYTEofLONG(lit,i)) {
6336 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6339 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6342 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6345 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6346 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6351 switch( BYTEofLONG(lit,i)) {
6353 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6357 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6364 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6366 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6375 /*-----------------------------------------------------------------*/
6376 /* gencjneshort - compare and jump if not equal */
6377 /*-----------------------------------------------------------------*/
6378 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6380 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6382 int res_offset = 0; /* the result may be a different size then left or right */
6383 int res_size = AOP_SIZE(result);
6385 symbol *lbl, *lbl_done;
6387 unsigned long lit = 0L;
6388 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6390 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6391 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6393 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6394 resolveIfx(&rIfx,ifx);
6395 lbl = newiTempLabel(NULL);
6396 lbl_done = newiTempLabel(NULL);
6399 /* if the left side is a literal or
6400 if the right is in a pointer register and left
6402 if ((AOP_TYPE(left) == AOP_LIT) ||
6403 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6408 if(AOP_TYPE(right) == AOP_LIT)
6409 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6411 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6412 preserve_result = 1;
6414 if(result && !preserve_result)
6417 for(i = 0; i < AOP_SIZE(result); i++)
6418 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6422 /* if the right side is a literal then anything goes */
6423 if (AOP_TYPE(right) == AOP_LIT &&
6424 AOP_TYPE(left) != AOP_DIR ) {
6427 genc16bit2lit(left, lit, 0);
6429 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6435 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6436 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6438 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6444 if(res_offset < res_size-1)
6452 /* if the right side is in a register or in direct space or
6453 if the left is a pointer register & right is not */
6454 else if (AOP_TYPE(right) == AOP_REG ||
6455 AOP_TYPE(right) == AOP_DIR ||
6456 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6457 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6458 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6459 int lbl_key = lbl->key;
6462 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6463 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6465 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6466 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6467 __FUNCTION__,__LINE__);
6471 /* switch(size) { */
6473 /* genc16bit2lit(left, lit, 0); */
6475 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6480 if((AOP_TYPE(left) == AOP_DIR) &&
6481 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6483 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6484 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6486 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6488 switch (lit & 0xff) {
6490 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6493 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6494 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6495 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6499 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6500 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6501 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6502 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6506 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6507 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6512 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6515 if(AOP_TYPE(result) == AOP_CRY) {
6516 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6521 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6523 /* fix me. probably need to check result size too */
6524 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6529 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6530 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6537 if(res_offset < res_size-1)
6542 } else if(AOP_TYPE(right) == AOP_REG &&
6543 AOP_TYPE(left) != AOP_DIR){
6546 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6547 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6548 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6553 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6555 if(res_offset < res_size-1)
6560 /* right is a pointer reg need both a & b */
6562 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6564 pic16_emitcode("mov","b,%s",l);
6565 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6566 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6571 if(result && preserve_result)
6574 for(i = 0; i < AOP_SIZE(result); i++)
6575 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6578 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6580 if(result && preserve_result)
6581 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6584 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6586 pic16_emitpLabel(lbl->key);
6588 if(result && preserve_result)
6591 for(i = 0; i < AOP_SIZE(result); i++)
6592 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6594 pic16_emitpLabel(lbl_done->key);
6597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6605 /*-----------------------------------------------------------------*/
6606 /* gencjne - compare and jump if not equal */
6607 /*-----------------------------------------------------------------*/
6608 static void gencjne(operand *left, operand *right, iCode *ifx)
6610 symbol *tlbl = newiTempLabel(NULL);
6612 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6613 gencjneshort(left, right, lbl);
6615 pic16_emitcode("mov","a,%s",one);
6616 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6617 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6618 pic16_emitcode("clr","a");
6619 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6621 pic16_emitpLabel(lbl->key);
6622 pic16_emitpLabel(tlbl->key);
6628 /*-----------------------------------------------------------------*/
6629 /* is_LitOp - check if operand has to be treated as literal */
6630 /*-----------------------------------------------------------------*/
6631 static bool is_LitOp(operand *op)
6633 return ((AOP_TYPE(op) == AOP_LIT)
6634 || ( (AOP_TYPE(op) == AOP_PCODE)
6635 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6636 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6639 /*-----------------------------------------------------------------*/
6640 /* is_LitAOp - check if operand has to be treated as literal */
6641 /*-----------------------------------------------------------------*/
6642 static bool is_LitAOp(asmop *aop)
6644 return ((aop->type == AOP_LIT)
6645 || ( (aop->type == AOP_PCODE)
6646 && ( (aop->aopu.pcop->type == PO_LITERAL)
6647 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6652 /*-----------------------------------------------------------------*/
6653 /* genCmpEq - generates code for equal to */
6654 /*-----------------------------------------------------------------*/
6655 static void genCmpEq (iCode *ic, iCode *ifx)
6657 operand *left, *right, *result;
6658 symbol *falselbl = newiTempLabel(NULL);
6659 symbol *donelbl = newiTempLabel(NULL);
6661 int preserve_result = 0;
6662 int generate_result = 0;
6664 unsigned long lit = -1;
6668 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6669 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6670 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6672 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6674 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6676 werror(W_POSSBUG2, __FILE__, __LINE__);
6677 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6678 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6682 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6684 operand *tmp = right ;
6689 if (AOP_TYPE(right) == AOP_LIT) {
6690 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6693 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6694 preserve_result = 1;
6696 if(result && AOP_SIZE(result))
6697 generate_result = 1;
6699 if(generate_result && !preserve_result)
6701 for(i = 0; i < AOP_SIZE(result); i++)
6702 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6705 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6706 for(i=0; i < AOP_SIZE(left); i++)
6708 if(AOP_TYPE(left) != AOP_ACC)
6711 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6713 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6715 if(is_LitOp(right)) {
6716 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6717 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6720 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6722 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6727 if(generate_result && preserve_result)
6729 for(i = 0; i < AOP_SIZE(result); i++)
6730 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6734 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6736 if(generate_result && preserve_result)
6737 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6739 if(ifx && IC_TRUE(ifx))
6740 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6742 if(ifx && IC_FALSE(ifx))
6743 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6745 pic16_emitpLabel(falselbl->key);
6749 if(ifx && IC_FALSE(ifx))
6750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6752 if(generate_result && preserve_result)
6754 for(i = 0; i < AOP_SIZE(result); i++)
6755 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6758 pic16_emitpLabel(donelbl->key);
6764 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6765 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6766 pic16_freeAsmop(result,NULL,ic,TRUE);
6772 // old version kept for reference
6774 /*-----------------------------------------------------------------*/
6775 /* genCmpEq - generates code for equal to */
6776 /*-----------------------------------------------------------------*/
6777 static void genCmpEq (iCode *ic, iCode *ifx)
6779 operand *left, *right, *result;
6780 unsigned long lit = 0L;
6782 symbol *falselbl = newiTempLabel(NULL);
6785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6788 DEBUGpic16_emitcode ("; ifx is non-null","");
6790 DEBUGpic16_emitcode ("; ifx is null","");
6792 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6793 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6794 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6796 size = max(AOP_SIZE(left),AOP_SIZE(right));
6798 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6800 /* if literal, literal on the right or
6801 if the right is in a pointer register and left
6803 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6804 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6805 operand *tmp = right ;
6811 if(ifx && !AOP_SIZE(result)){
6813 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6814 /* if they are both bit variables */
6815 if (AOP_TYPE(left) == AOP_CRY &&
6816 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6817 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6818 if(AOP_TYPE(right) == AOP_LIT){
6819 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6821 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6822 pic16_emitcode("cpl","c");
6823 } else if(lit == 1L) {
6824 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6826 pic16_emitcode("clr","c");
6828 /* AOP_TYPE(right) == AOP_CRY */
6830 symbol *lbl = newiTempLabel(NULL);
6831 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6833 pic16_emitcode("cpl","c");
6834 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6836 /* if true label then we jump if condition
6838 tlbl = newiTempLabel(NULL);
6839 if ( IC_TRUE(ifx) ) {
6840 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6841 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6843 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6844 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6846 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6849 /* left and right are both bit variables, result is carry */
6852 resolveIfx(&rIfx,ifx);
6854 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6855 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6856 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6857 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6862 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6864 /* They're not both bit variables. Is the right a literal? */
6865 if(AOP_TYPE(right) == AOP_LIT) {
6866 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6871 switch(lit & 0xff) {
6873 if ( IC_TRUE(ifx) ) {
6874 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6876 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6878 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6879 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6883 if ( IC_TRUE(ifx) ) {
6884 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6886 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6888 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6893 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6895 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6900 /* end of size == 1 */
6904 genc16bit2lit(left,lit,offset);
6907 /* end of size == 2 */
6912 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6913 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6914 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6915 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6918 /* search for patterns that can be optimized */
6920 genc16bit2lit(left,lit,0);
6924 emitSKPZ; // if hi word unequal
6926 emitSKPNZ; // if hi word equal
6928 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6929 genc16bit2lit(left,lit,2);
6932 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6933 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6937 pic16_emitpLabel(falselbl->key);
6946 } else if(AOP_TYPE(right) == AOP_CRY ) {
6947 /* we know the left is not a bit, but that the right is */
6948 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6949 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6950 pic16_popGet(AOP(right),offset));
6951 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6953 /* if the two are equal, then W will be 0 and the Z bit is set
6954 * we could test Z now, or go ahead and check the high order bytes if
6955 * the variable we're comparing is larger than a byte. */
6958 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6960 if ( IC_TRUE(ifx) ) {
6962 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6963 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6966 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6967 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6971 /* They're both variables that are larger than bits */
6974 tlbl = newiTempLabel(NULL);
6977 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6978 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6980 if ( IC_TRUE(ifx) ) {
6984 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6986 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6987 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6991 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6994 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6995 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7000 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7002 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7003 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7007 if(s>1 && IC_TRUE(ifx)) {
7008 pic16_emitpLabel(tlbl->key);
7009 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7013 /* mark the icode as generated */
7018 /* if they are both bit variables */
7019 if (AOP_TYPE(left) == AOP_CRY &&
7020 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7021 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7022 if(AOP_TYPE(right) == AOP_LIT){
7023 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7025 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7026 pic16_emitcode("cpl","c");
7027 } else if(lit == 1L) {
7028 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7030 pic16_emitcode("clr","c");
7032 /* AOP_TYPE(right) == AOP_CRY */
7034 symbol *lbl = newiTempLabel(NULL);
7035 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7037 pic16_emitcode("cpl","c");
7038 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7041 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7042 pic16_outBitC(result);
7046 genIfxJump (ifx,"c");
7049 /* if the result is used in an arithmetic operation
7050 then put the result in place */
7051 pic16_outBitC(result);
7054 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7055 gencjne(left,right,result,ifx);
7058 gencjne(left,right,newiTempLabel(NULL));
7060 if(IC_TRUE(ifx)->key)
7061 gencjne(left,right,IC_TRUE(ifx)->key);
7063 gencjne(left,right,IC_FALSE(ifx)->key);
7067 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7068 pic16_aopPut(AOP(result),"a",0);
7073 genIfxJump (ifx,"a");
7077 /* if the result is used in an arithmetic operation
7078 then put the result in place */
7080 if (AOP_TYPE(result) != AOP_CRY)
7081 pic16_outAcc(result);
7083 /* leave the result in acc */
7087 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7088 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7089 pic16_freeAsmop(result,NULL,ic,TRUE);
7093 /*-----------------------------------------------------------------*/
7094 /* ifxForOp - returns the icode containing the ifx for operand */
7095 /*-----------------------------------------------------------------*/
7096 static iCode *ifxForOp ( operand *op, iCode *ic )
7100 /* if true symbol then needs to be assigned */
7101 if (IS_TRUE_SYMOP(op))
7104 /* if this has register type condition and
7105 the next instruction is ifx with the same operand
7106 and live to of the operand is upto the ifx only then */
7108 && ic->next->op == IFX
7109 && IC_COND(ic->next)->key == op->key
7110 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7112 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7118 ic->next->op == IFX &&
7119 IC_COND(ic->next)->key == op->key) {
7120 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7125 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7127 ic->next->op == IFX)
7128 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7131 ic->next->op == IFX &&
7132 IC_COND(ic->next)->key == op->key) {
7133 DEBUGpic16_emitcode ("; "," key is okay");
7134 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7135 OP_SYMBOL(op)->liveTo,
7140 /* the code below is completely untested
7141 * it just allows ulong2fs.c compile -- VR */
7144 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7145 __FILE__, __FUNCTION__, __LINE__);
7147 /* if this has register type condition and
7148 the next instruction is ifx with the same operand
7149 and live to of the operand is upto the ifx only then */
7151 ic->next->op == IFX &&
7152 IC_COND(ic->next)->key == op->key &&
7153 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7157 ic->next->op == IFX &&
7158 IC_COND(ic->next)->key == op->key) {
7159 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7163 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7164 __FILE__, __FUNCTION__, __LINE__);
7166 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7171 /*-----------------------------------------------------------------*/
7172 /* genAndOp - for && operation */
7173 /*-----------------------------------------------------------------*/
7174 static void genAndOp (iCode *ic)
7176 operand *left,*right, *result;
7181 /* note here that && operations that are in an
7182 if statement are taken away by backPatchLabels
7183 only those used in arthmetic operations remain */
7184 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7185 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7186 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7188 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7190 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7191 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7192 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7194 /* if both are bit variables */
7195 /* if (AOP_TYPE(left) == AOP_CRY && */
7196 /* AOP_TYPE(right) == AOP_CRY ) { */
7197 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7198 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7199 /* pic16_outBitC(result); */
7201 /* tlbl = newiTempLabel(NULL); */
7202 /* pic16_toBoolean(left); */
7203 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7204 /* pic16_toBoolean(right); */
7205 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7206 /* pic16_outBitAcc(result); */
7209 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7210 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7211 pic16_freeAsmop(result,NULL,ic,TRUE);
7215 /*-----------------------------------------------------------------*/
7216 /* genOrOp - for || operation */
7217 /*-----------------------------------------------------------------*/
7220 modified this code, but it doesn't appear to ever get called
7223 static void genOrOp (iCode *ic)
7225 operand *left,*right, *result;
7230 /* note here that || operations that are in an
7231 if statement are taken away by backPatchLabels
7232 only those used in arthmetic operations remain */
7233 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7234 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7235 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7237 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7239 /* if both are bit variables */
7240 if (AOP_TYPE(left) == AOP_CRY &&
7241 AOP_TYPE(right) == AOP_CRY ) {
7242 pic16_emitcode("clrc","");
7243 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7244 AOP(left)->aopu.aop_dir,
7245 AOP(left)->aopu.aop_dir);
7246 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7247 AOP(right)->aopu.aop_dir,
7248 AOP(right)->aopu.aop_dir);
7249 pic16_emitcode("setc","");
7252 tlbl = newiTempLabel(NULL);
7253 pic16_toBoolean(left);
7255 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7256 pic16_toBoolean(right);
7257 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7259 pic16_outBitAcc(result);
7262 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7263 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7264 pic16_freeAsmop(result,NULL,ic,TRUE);
7267 /*-----------------------------------------------------------------*/
7268 /* isLiteralBit - test if lit == 2^n */
7269 /*-----------------------------------------------------------------*/
7270 static int isLiteralBit(unsigned long lit)
7272 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7273 0x100L,0x200L,0x400L,0x800L,
7274 0x1000L,0x2000L,0x4000L,0x8000L,
7275 0x10000L,0x20000L,0x40000L,0x80000L,
7276 0x100000L,0x200000L,0x400000L,0x800000L,
7277 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7278 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7281 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7282 for(idx = 0; idx < 32; idx++)
7288 /*-----------------------------------------------------------------*/
7289 /* continueIfTrue - */
7290 /*-----------------------------------------------------------------*/
7291 static void continueIfTrue (iCode *ic)
7295 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7299 /*-----------------------------------------------------------------*/
7301 /*-----------------------------------------------------------------*/
7302 static void jumpIfTrue (iCode *ic)
7306 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7310 /*-----------------------------------------------------------------*/
7311 /* jmpTrueOrFalse - */
7312 /*-----------------------------------------------------------------*/
7313 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7315 // ugly but optimized by peephole
7318 symbol *nlbl = newiTempLabel(NULL);
7319 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7320 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7321 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7322 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7324 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7325 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7330 /*-----------------------------------------------------------------*/
7331 /* genAnd - code for and */
7332 /*-----------------------------------------------------------------*/
7333 static void genAnd (iCode *ic, iCode *ifx)
7335 operand *left, *right, *result;
7337 unsigned long lit = 0L;
7343 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7344 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7345 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7347 resolveIfx(&rIfx,ifx);
7349 /* if left is a literal & right is not then exchange them */
7350 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7351 AOP_NEEDSACC(left)) {
7352 operand *tmp = right ;
7357 /* if result = right then exchange them */
7358 if(pic16_sameRegs(AOP(result),AOP(right))){
7359 operand *tmp = right ;
7364 /* if right is bit then exchange them */
7365 if (AOP_TYPE(right) == AOP_CRY &&
7366 AOP_TYPE(left) != AOP_CRY){
7367 operand *tmp = right ;
7371 if(AOP_TYPE(right) == AOP_LIT)
7372 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7374 size = AOP_SIZE(result);
7376 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7379 // result = bit & yy;
7380 if (AOP_TYPE(left) == AOP_CRY){
7381 // c = bit & literal;
7382 if(AOP_TYPE(right) == AOP_LIT){
7384 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7387 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7390 if(size && (AOP_TYPE(result) == AOP_CRY)){
7391 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7394 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7398 pic16_emitcode("clr","c");
7401 if (AOP_TYPE(right) == AOP_CRY){
7403 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7404 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7407 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7409 pic16_emitcode("rrc","a");
7410 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7416 pic16_outBitC(result);
7418 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7419 genIfxJump(ifx, "c");
7423 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7424 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7425 if((AOP_TYPE(right) == AOP_LIT) &&
7426 (AOP_TYPE(result) == AOP_CRY) &&
7427 (AOP_TYPE(left) != AOP_CRY)){
7428 int posbit = isLiteralBit(lit);
7432 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7435 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7441 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7444 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7445 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7448 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7449 size = AOP_SIZE(left);
7452 int bp = posbit, ofs=0;
7459 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7460 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7464 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7465 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7467 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7474 symbol *tlbl = newiTempLabel(NULL);
7475 int sizel = AOP_SIZE(left);
7481 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7483 /* patch provided by Aaron Colwell */
7484 if((posbit = isLiteralBit(bytelit)) != 0) {
7485 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7486 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7487 (posbit-1),0, PO_GPR_REGISTER));
7489 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7490 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7492 if (bytelit == 0xff) {
7493 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7494 * a peephole could optimize it out -- VR */
7495 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7497 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7498 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7501 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7502 pic16_popGetLabel(tlbl->key));
7506 /* old code, left here for reference -- VR 09/2004 */
7507 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7509 if((posbit = isLiteralBit(bytelit)) != 0)
7510 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7512 if(bytelit != 0x0FFL)
7513 pic16_emitcode("anl","a,%s",
7514 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7515 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7521 // bit = left & literal
7524 pic16_emitpLabel(tlbl->key);
7526 // if(left & literal)
7529 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7532 pic16_emitpLabel(tlbl->key);
7537 pic16_outBitC(result);
7541 /* if left is same as result */
7542 if(pic16_sameRegs(AOP(result),AOP(left))){
7544 for(;size--; offset++,lit>>=8) {
7545 if(AOP_TYPE(right) == AOP_LIT){
7546 switch(lit & 0xff) {
7548 /* and'ing with 0 has clears the result */
7549 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7550 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7553 /* and'ing with 0xff is a nop when the result and left are the same */
7558 int p = pic16_my_powof2( (~lit) & 0xff );
7560 /* only one bit is set in the literal, so use a bcf instruction */
7561 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7562 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7565 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7566 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7567 if(know_W != (lit&0xff))
7568 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7570 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7575 if (AOP_TYPE(left) == AOP_ACC) {
7576 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7578 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7579 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7586 // left & result in different registers
7587 if(AOP_TYPE(result) == AOP_CRY){
7589 // if(size), result in bit
7590 // if(!size && ifx), conditional oper: if(left & right)
7591 symbol *tlbl = newiTempLabel(NULL);
7592 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7594 pic16_emitcode("setb","c");
7596 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7597 pic16_emitcode("anl","a,%s",
7598 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7599 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7604 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7605 pic16_outBitC(result);
7607 jmpTrueOrFalse(ifx, tlbl);
7609 for(;(size--);offset++) {
7611 // result = left & right
7612 if(AOP_TYPE(right) == AOP_LIT){
7613 int t = (lit >> (offset*8)) & 0x0FFL;
7616 pic16_emitcode("clrf","%s",
7617 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7618 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7621 pic16_emitcode("movf","%s,w",
7622 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7623 pic16_emitcode("movwf","%s",
7624 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7625 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7626 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7629 pic16_emitcode("movlw","0x%x",t);
7630 pic16_emitcode("andwf","%s,w",
7631 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7632 pic16_emitcode("movwf","%s",
7633 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7635 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7636 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7637 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7642 if (AOP_TYPE(left) == AOP_ACC) {
7643 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7644 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7646 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7647 pic16_emitcode("andwf","%s,w",
7648 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7649 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7650 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7652 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7653 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7659 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7660 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7661 pic16_freeAsmop(result,NULL,ic,TRUE);
7664 /*-----------------------------------------------------------------*/
7665 /* genOr - code for or */
7666 /*-----------------------------------------------------------------*/
7667 static void genOr (iCode *ic, iCode *ifx)
7669 operand *left, *right, *result;
7671 unsigned long lit = 0L;
7673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7675 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7676 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7677 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7679 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7681 /* if left is a literal & right is not then exchange them */
7682 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7683 AOP_NEEDSACC(left)) {
7684 operand *tmp = right ;
7689 /* if result = right then exchange them */
7690 if(pic16_sameRegs(AOP(result),AOP(right))){
7691 operand *tmp = right ;
7696 /* if right is bit then exchange them */
7697 if (AOP_TYPE(right) == AOP_CRY &&
7698 AOP_TYPE(left) != AOP_CRY){
7699 operand *tmp = right ;
7704 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7706 if(AOP_TYPE(right) == AOP_LIT)
7707 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7709 size = AOP_SIZE(result);
7713 if (AOP_TYPE(left) == AOP_CRY){
7714 if(AOP_TYPE(right) == AOP_LIT){
7715 // c = bit & literal;
7717 // lit != 0 => result = 1
7718 if(AOP_TYPE(result) == AOP_CRY){
7720 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7721 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7722 // AOP(result)->aopu.aop_dir,
7723 // AOP(result)->aopu.aop_dir);
7725 continueIfTrue(ifx);
7729 // lit == 0 => result = left
7730 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7732 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7735 if (AOP_TYPE(right) == AOP_CRY){
7736 if(pic16_sameRegs(AOP(result),AOP(left))){
7738 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7739 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7740 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7742 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7743 AOP(result)->aopu.aop_dir,
7744 AOP(result)->aopu.aop_dir);
7745 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7746 AOP(right)->aopu.aop_dir,
7747 AOP(right)->aopu.aop_dir);
7748 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7749 AOP(result)->aopu.aop_dir,
7750 AOP(result)->aopu.aop_dir);
7752 if( AOP_TYPE(result) == AOP_ACC) {
7753 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7754 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7755 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7756 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7760 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7761 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7762 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7763 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7765 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7766 AOP(result)->aopu.aop_dir,
7767 AOP(result)->aopu.aop_dir);
7768 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7769 AOP(right)->aopu.aop_dir,
7770 AOP(right)->aopu.aop_dir);
7771 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7772 AOP(left)->aopu.aop_dir,
7773 AOP(left)->aopu.aop_dir);
7774 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7775 AOP(result)->aopu.aop_dir,
7776 AOP(result)->aopu.aop_dir);
7781 symbol *tlbl = newiTempLabel(NULL);
7782 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7785 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7786 if( AOP_TYPE(right) == AOP_ACC) {
7787 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7789 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7790 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7795 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7796 pic16_emitcode(";XXX setb","c");
7797 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7798 AOP(left)->aopu.aop_dir,tlbl->key+100);
7799 pic16_toBoolean(right);
7800 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7801 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7802 jmpTrueOrFalse(ifx, tlbl);
7806 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7813 pic16_outBitC(result);
7815 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7816 genIfxJump(ifx, "c");
7820 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7821 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7822 if((AOP_TYPE(right) == AOP_LIT) &&
7823 (AOP_TYPE(result) == AOP_CRY) &&
7824 (AOP_TYPE(left) != AOP_CRY)){
7826 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7829 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7831 continueIfTrue(ifx);
7834 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7835 // lit = 0, result = boolean(left)
7837 pic16_emitcode(";XXX setb","c");
7838 pic16_toBoolean(right);
7840 symbol *tlbl = newiTempLabel(NULL);
7841 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7843 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7845 genIfxJump (ifx,"a");
7849 pic16_outBitC(result);
7853 /* if left is same as result */
7854 if(pic16_sameRegs(AOP(result),AOP(left))){
7856 for(;size--; offset++,lit>>=8) {
7857 if(AOP_TYPE(right) == AOP_LIT){
7858 if((lit & 0xff) == 0)
7859 /* or'ing with 0 has no effect */
7862 int p = pic16_my_powof2(lit & 0xff);
7864 /* only one bit is set in the literal, so use a bsf instruction */
7865 pic16_emitpcode(POC_BSF,
7866 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7868 if(know_W != (lit & 0xff))
7869 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7870 know_W = lit & 0xff;
7871 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7876 if (AOP_TYPE(left) == AOP_ACC) {
7877 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7878 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7880 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7881 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7883 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7884 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890 // left & result in different registers
7891 if(AOP_TYPE(result) == AOP_CRY){
7893 // if(size), result in bit
7894 // if(!size && ifx), conditional oper: if(left | right)
7895 symbol *tlbl = newiTempLabel(NULL);
7896 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7897 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7901 pic16_emitcode(";XXX setb","c");
7903 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904 pic16_emitcode(";XXX orl","a,%s",
7905 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7906 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7911 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7912 pic16_outBitC(result);
7914 jmpTrueOrFalse(ifx, tlbl);
7915 } else for(;(size--);offset++){
7917 // result = left & right
7918 if(AOP_TYPE(right) == AOP_LIT){
7919 int t = (lit >> (offset*8)) & 0x0FFL;
7922 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7925 // pic16_emitcode("movf","%s,w",
7926 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7927 // pic16_emitcode("movwf","%s",
7928 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7931 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7932 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7935 // pic16_emitcode("movlw","0x%x",t);
7936 // pic16_emitcode("iorwf","%s,w",
7937 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7938 // pic16_emitcode("movwf","%s",
7939 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7945 // faster than result <- left, anl result,right
7946 // and better if result is SFR
7947 if (AOP_TYPE(left) == AOP_ACC) {
7948 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7949 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7951 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7952 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7954 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7955 // pic16_emitcode("iorwf","%s,w",
7956 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7959 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7964 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7965 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7966 pic16_freeAsmop(result,NULL,ic,TRUE);
7969 /*-----------------------------------------------------------------*/
7970 /* genXor - code for xclusive or */
7971 /*-----------------------------------------------------------------*/
7972 static void genXor (iCode *ic, iCode *ifx)
7974 operand *left, *right, *result;
7976 unsigned long lit = 0L;
7978 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7980 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7981 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7982 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7984 /* if left is a literal & right is not ||
7985 if left needs acc & right does not */
7986 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7987 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7988 operand *tmp = right ;
7993 /* if result = right then exchange them */
7994 if(pic16_sameRegs(AOP(result),AOP(right))){
7995 operand *tmp = right ;
8000 /* if right is bit then exchange them */
8001 if (AOP_TYPE(right) == AOP_CRY &&
8002 AOP_TYPE(left) != AOP_CRY){
8003 operand *tmp = right ;
8007 if(AOP_TYPE(right) == AOP_LIT)
8008 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8010 size = AOP_SIZE(result);
8014 if (AOP_TYPE(left) == AOP_CRY){
8015 if(AOP_TYPE(right) == AOP_LIT){
8016 // c = bit & literal;
8018 // lit>>1 != 0 => result = 1
8019 if(AOP_TYPE(result) == AOP_CRY){
8021 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8022 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8024 continueIfTrue(ifx);
8027 pic16_emitcode("setb","c");
8031 // lit == 0, result = left
8032 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8034 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8036 // lit == 1, result = not(left)
8037 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8038 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8039 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8040 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8043 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8044 pic16_emitcode("cpl","c");
8051 symbol *tlbl = newiTempLabel(NULL);
8052 if (AOP_TYPE(right) == AOP_CRY){
8054 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8057 int sizer = AOP_SIZE(right);
8059 // if val>>1 != 0, result = 1
8060 pic16_emitcode("setb","c");
8062 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8064 // test the msb of the lsb
8065 pic16_emitcode("anl","a,#0xfe");
8066 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8070 pic16_emitcode("rrc","a");
8072 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8073 pic16_emitcode("cpl","c");
8074 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8079 pic16_outBitC(result);
8081 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8082 genIfxJump(ifx, "c");
8086 if(pic16_sameRegs(AOP(result),AOP(left))){
8087 /* if left is same as result */
8088 for(;size--; offset++) {
8089 if(AOP_TYPE(right) == AOP_LIT){
8090 int t = (lit >> (offset*8)) & 0x0FFL;
8094 if (IS_AOP_PREG(left)) {
8095 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8096 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8097 pic16_aopPut(AOP(result),"a",offset);
8099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8100 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8101 pic16_emitcode("xrl","%s,%s",
8102 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8103 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8106 if (AOP_TYPE(left) == AOP_ACC)
8107 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8109 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8110 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8112 if (IS_AOP_PREG(left)) {
8113 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8114 pic16_aopPut(AOP(result),"a",offset);
8116 pic16_emitcode("xrl","%s,a",
8117 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8123 // left & result in different registers
8124 if(AOP_TYPE(result) == AOP_CRY){
8126 // if(size), result in bit
8127 // if(!size && ifx), conditional oper: if(left ^ right)
8128 symbol *tlbl = newiTempLabel(NULL);
8129 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8131 pic16_emitcode("setb","c");
8133 if((AOP_TYPE(right) == AOP_LIT) &&
8134 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8135 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8137 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8138 pic16_emitcode("xrl","a,%s",
8139 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8141 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8146 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8147 pic16_outBitC(result);
8149 jmpTrueOrFalse(ifx, tlbl);
8150 } else for(;(size--);offset++){
8152 // result = left & right
8153 if(AOP_TYPE(right) == AOP_LIT){
8154 int t = (lit >> (offset*8)) & 0x0FFL;
8157 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8158 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8159 pic16_emitcode("movf","%s,w",
8160 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8161 pic16_emitcode("movwf","%s",
8162 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8165 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8167 pic16_emitcode("comf","%s,w",
8168 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8169 pic16_emitcode("movwf","%s",
8170 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8173 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8174 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8175 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8176 pic16_emitcode("movlw","0x%x",t);
8177 pic16_emitcode("xorwf","%s,w",
8178 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179 pic16_emitcode("movwf","%s",
8180 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8186 // faster than result <- left, anl result,right
8187 // and better if result is SFR
8188 if (AOP_TYPE(left) == AOP_ACC) {
8189 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8190 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8192 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8193 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8194 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8195 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8197 if ( AOP_TYPE(result) != AOP_ACC){
8198 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8199 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8205 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8206 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8207 pic16_freeAsmop(result,NULL,ic,TRUE);
8210 /*-----------------------------------------------------------------*/
8211 /* genInline - write the inline code out */
8212 /*-----------------------------------------------------------------*/
8213 static void genInline (iCode *ic)
8215 char *buffer, *bp, *bp1;
8217 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8219 _G.inLine += (!options.asmpeep);
8221 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8222 strcpy(buffer,IC_INLINE(ic));
8224 while((bp1=strstr(bp, "\\n"))) {
8232 /* This is an experimental code for #pragma inline
8233 and is temporarily disabled for 2.5.0 release */
8241 cbuf = Safe_strdup(buffer);
8242 cblen = strlen(buffer)+1;
8243 memset(cbuf, 0, cblen);
8248 if(*bp != '%')*bp1++ = *bp++;
8254 if(i>elementsInSet(asmInlineMap))break;
8257 s = indexSet(asmInlineMap, i);
8258 DEBUGpc("searching symbol s = `%s'", s);
8259 sym = findSym(SymbolTab, NULL, s);
8262 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8264 strcat(bp1, sym->rname);
8270 if(strlen(bp1) > cblen - 16) {
8271 int i = strlen(cbuf);
8273 cbuf = realloc(cbuf, cblen);
8274 memset(cbuf+i, 0, 50);
8280 buffer = Safe_strdup( cbuf );
8287 /* emit each line as a code */
8293 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8301 /* print label, use this special format with NULL directive
8302 * to denote that the argument should not be indented with tab */
8303 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8306 /* advance to end of line (prevent splitting of comments at ':' */
8307 while (*bp && *bp != '\n') {
8315 if ((bp1 != bp) && *bp1)
8316 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8321 _G.inLine -= (!options.asmpeep);
8324 /*-----------------------------------------------------------------*/
8325 /* genRRC - rotate right with carry */
8326 /*-----------------------------------------------------------------*/
8327 static void genRRC (iCode *ic)
8329 operand *left , *result ;
8330 int size, offset = 0, same;
8332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8334 /* rotate right with carry */
8336 result=IC_RESULT(ic);
8337 pic16_aopOp (left,ic,FALSE);
8338 pic16_aopOp (result,ic,TRUE);
8340 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8342 same = pic16_sameRegs(AOP(result),AOP(left));
8344 size = AOP_SIZE(result);
8346 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8348 /* get the lsb and put it into the carry */
8349 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8356 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8358 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8359 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8365 pic16_freeAsmop(left,NULL,ic,TRUE);
8366 pic16_freeAsmop(result,NULL,ic,TRUE);
8369 /*-----------------------------------------------------------------*/
8370 /* genRLC - generate code for rotate left with carry */
8371 /*-----------------------------------------------------------------*/
8372 static void genRLC (iCode *ic)
8374 operand *left , *result ;
8375 int size, offset = 0;
8378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8379 /* rotate right with carry */
8381 result=IC_RESULT(ic);
8382 pic16_aopOp (left,ic,FALSE);
8383 pic16_aopOp (result,ic,TRUE);
8385 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8387 same = pic16_sameRegs(AOP(result),AOP(left));
8389 /* move it to the result */
8390 size = AOP_SIZE(result);
8392 /* get the msb and put it into the carry */
8393 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8400 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8402 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8403 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8410 pic16_freeAsmop(left,NULL,ic,TRUE);
8411 pic16_freeAsmop(result,NULL,ic,TRUE);
8415 /* gpasm can get the highest order bit with HIGH/UPPER
8416 * so the following probably is not needed -- VR */
8418 /*-----------------------------------------------------------------*/
8419 /* genGetHbit - generates code get highest order bit */
8420 /*-----------------------------------------------------------------*/
8421 static void genGetHbit (iCode *ic)
8423 operand *left, *result;
8425 result=IC_RESULT(ic);
8426 pic16_aopOp (left,ic,FALSE);
8427 pic16_aopOp (result,ic,FALSE);
8429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8430 /* get the highest order byte into a */
8431 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8432 if(AOP_TYPE(result) == AOP_CRY){
8433 pic16_emitcode("rlc","a");
8434 pic16_outBitC(result);
8437 pic16_emitcode("rl","a");
8438 pic16_emitcode("anl","a,#0x01");
8439 pic16_outAcc(result);
8443 pic16_freeAsmop(left,NULL,ic,TRUE);
8444 pic16_freeAsmop(result,NULL,ic,TRUE);
8448 /*-----------------------------------------------------------------*/
8449 /* AccRol - rotate left accumulator by known count */
8450 /*-----------------------------------------------------------------*/
8451 static void AccRol (int shCount)
8453 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8454 shCount &= 0x0007; // shCount : 0..7
8459 pic16_emitcode("rl","a");
8462 pic16_emitcode("rl","a");
8463 pic16_emitcode("rl","a");
8466 pic16_emitcode("swap","a");
8467 pic16_emitcode("rr","a");
8470 pic16_emitcode("swap","a");
8473 pic16_emitcode("swap","a");
8474 pic16_emitcode("rl","a");
8477 pic16_emitcode("rr","a");
8478 pic16_emitcode("rr","a");
8481 pic16_emitcode("rr","a");
8487 /*-----------------------------------------------------------------*/
8488 /* AccLsh - left shift accumulator by known count */
8489 /*-----------------------------------------------------------------*/
8490 static void AccLsh (int shCount, int doMask)
8492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8498 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8501 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8506 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8509 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8513 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 /* no masking is required in genPackBits */
8525 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8529 /*-----------------------------------------------------------------*/
8530 /* AccRsh - right shift accumulator by known count */
8531 /*-----------------------------------------------------------------*/
8532 static void AccRsh (int shCount, int andmask)
8534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8539 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8542 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8546 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8547 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8550 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8553 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8568 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8572 /*-----------------------------------------------------------------*/
8573 /* AccSRsh - signed right shift accumulator by known count */
8574 /*-----------------------------------------------------------------*/
8575 static void AccSRsh (int shCount)
8578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8581 pic16_emitcode("mov","c,acc.7");
8582 pic16_emitcode("rrc","a");
8583 } else if(shCount == 2){
8584 pic16_emitcode("mov","c,acc.7");
8585 pic16_emitcode("rrc","a");
8586 pic16_emitcode("mov","c,acc.7");
8587 pic16_emitcode("rrc","a");
8589 tlbl = newiTempLabel(NULL);
8590 /* rotate right accumulator */
8591 AccRol(8 - shCount);
8592 /* and kill the higher order bits */
8593 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8594 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8595 pic16_emitcode("orl","a,#0x%02x",
8596 (unsigned char)~SRMask[shCount]);
8597 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8603 /*-----------------------------------------------------------------*/
8604 /* shiftR1Left2Result - shift right one byte from left to result */
8605 /*-----------------------------------------------------------------*/
8606 static void shiftR1Left2ResultSigned (operand *left, int offl,
8607 operand *result, int offr,
8612 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8614 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8618 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8620 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8622 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8623 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8629 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8631 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8633 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8634 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8636 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8637 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8643 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8645 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8646 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8649 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8650 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8653 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8654 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8656 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8660 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8661 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8662 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8663 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8664 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8668 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8670 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8671 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8674 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8675 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8683 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8684 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8685 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8686 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8691 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8693 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8700 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8702 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8714 /*-----------------------------------------------------------------*/
8715 /* shiftR1Left2Result - shift right one byte from left to result */
8716 /*-----------------------------------------------------------------*/
8717 static void shiftR1Left2Result (operand *left, int offl,
8718 operand *result, int offr,
8719 int shCount, int sign)
8723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8725 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8727 /* Copy the msb into the carry if signed. */
8729 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8739 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8741 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8748 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8750 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8754 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8761 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8765 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8766 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8773 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8774 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8779 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8788 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8789 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8797 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8798 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8807 /*-----------------------------------------------------------------*/
8808 /* shiftL1Left2Result - shift left one byte from left to result */
8809 /*-----------------------------------------------------------------*/
8810 static void shiftL1Left2Result (operand *left, int offl,
8811 operand *result, int offr, int shCount)
8816 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8818 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8819 DEBUGpic16_emitcode ("; ***","same = %d",same);
8820 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8822 /* shift left accumulator */
8823 //AccLsh(shCount, 1); // don't comment out just yet...
8824 // pic16_aopPut(AOP(result),"a",offr);
8828 /* Shift left 1 bit position */
8829 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8831 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8833 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8834 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8838 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8839 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8840 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8841 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8844 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8845 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8846 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8848 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8851 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8852 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8853 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8857 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8858 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8859 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8863 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8864 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8870 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8875 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8880 /*-----------------------------------------------------------------*/
8881 /* movLeft2Result - move byte from left to result */
8882 /*-----------------------------------------------------------------*/
8883 static void movLeft2Result (operand *left, int offl,
8884 operand *result, int offr)
8887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8888 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8889 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8891 if (*l == '@' && (IS_AOP_PREG(result))) {
8892 pic16_emitcode("mov","a,%s",l);
8893 pic16_aopPut(AOP(result),"a",offr);
8895 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8896 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8901 /*-----------------------------------------------------------------*/
8902 /* shiftL2Left2Result - shift left two bytes from left to result */
8903 /*-----------------------------------------------------------------*/
8904 static void shiftL2Left2Result (operand *left, int offl,
8905 operand *result, int offr, int shCount)
8907 int same = pic16_sameRegs(AOP(result), AOP(left));
8910 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8912 if (same && (offl != offr)) { // shift bytes
8915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8916 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8918 } else { // just treat as different later on
8931 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8932 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8937 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8944 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8945 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8946 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8952 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8958 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8962 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8963 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8972 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8983 /* note, use a mov/add for the shift since the mov has a
8984 chance of getting optimized out */
8985 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8986 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8987 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8993 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9000 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9001 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9003 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9005 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9006 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9011 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9017 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9018 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9024 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9025 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9033 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9034 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9040 /*-----------------------------------------------------------------*/
9041 /* shiftR2Left2Result - shift right two bytes from left to result */
9042 /*-----------------------------------------------------------------*/
9043 static void shiftR2Left2Result (operand *left, int offl,
9044 operand *result, int offr,
9045 int shCount, int sign)
9047 int same = pic16_sameRegs(AOP(result), AOP(left));
9049 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9051 if (same && (offl != offr)) { // shift right bytes
9054 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9055 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9057 } else { // just treat as different later on
9069 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9074 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9075 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9077 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9078 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9079 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9080 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9085 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9096 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9097 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9100 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9101 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9103 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9106 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9107 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9110 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9111 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9112 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9113 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9117 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9118 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9123 pic16_emitpcode(POC_BTFSC,
9124 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9125 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9133 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9136 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9138 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9139 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9141 pic16_emitpcode(POC_BTFSC,
9142 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9143 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9145 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9146 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9148 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9150 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9151 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9152 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9153 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9154 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9156 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9159 pic16_emitpcode(POC_BTFSC,
9160 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9161 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9163 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9164 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9171 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9172 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9177 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9179 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9184 /*-----------------------------------------------------------------*/
9185 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9186 /*-----------------------------------------------------------------*/
9187 static void shiftLLeftOrResult (operand *left, int offl,
9188 operand *result, int offr, int shCount)
9190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9192 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9193 /* shift left accumulator */
9195 /* or with result */
9196 /* back to result */
9197 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9200 /*-----------------------------------------------------------------*/
9201 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9202 /*-----------------------------------------------------------------*/
9203 static void shiftRLeftOrResult (operand *left, int offl,
9204 operand *result, int offr, int shCount)
9206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9209 /* shift right accumulator */
9211 /* or with result */
9212 /* back to result */
9213 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9216 /*-----------------------------------------------------------------*/
9217 /* genlshOne - left shift a one byte quantity by known count */
9218 /*-----------------------------------------------------------------*/
9219 static void genlshOne (operand *result, operand *left, int shCount)
9221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9222 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9225 /*-----------------------------------------------------------------*/
9226 /* genlshTwo - left shift two bytes by known amount != 0 */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshTwo (operand *result,operand *left, int shCount)
9232 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9233 size = pic16_getDataSize(result);
9235 /* if shCount >= 8 */
9241 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9243 movLeft2Result(left, LSB, result, MSB16);
9245 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9248 /* 1 <= shCount <= 7 */
9251 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9253 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9257 /*-----------------------------------------------------------------*/
9258 /* shiftLLong - shift left one long from left to result */
9259 /* offr = LSB or MSB16 */
9260 /*-----------------------------------------------------------------*/
9261 static void shiftLLong (operand *left, operand *result, int offr )
9263 int size = AOP_SIZE(result);
9264 int same = pic16_sameRegs(AOP(left),AOP(result));
9267 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9269 if (same && (offr == MSB16)) { //shift one byte
9270 for(i=size-1;i>=MSB16;i--) {
9271 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9272 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9275 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9278 if (size > LSB+offr ){
9280 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9282 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9283 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9287 if(size > MSB16+offr){
9289 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9291 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9296 if(size > MSB24+offr){
9298 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9300 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9305 if(size > MSB32+offr){
9307 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9309 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9314 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9318 /*-----------------------------------------------------------------*/
9319 /* genlshFour - shift four byte by a known amount != 0 */
9320 /*-----------------------------------------------------------------*/
9321 static void genlshFour (operand *result, operand *left, int shCount)
9325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9326 size = AOP_SIZE(result);
9328 /* if shifting more that 3 bytes */
9329 if (shCount >= 24 ) {
9332 /* lowest order of left goes to the highest
9333 order of the destination */
9334 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9336 movLeft2Result(left, LSB, result, MSB32);
9338 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9339 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9340 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9345 /* more than two bytes */
9346 else if ( shCount >= 16 ) {
9347 /* lower order two bytes goes to higher order two bytes */
9349 /* if some more remaining */
9351 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9353 movLeft2Result(left, MSB16, result, MSB32);
9354 movLeft2Result(left, LSB, result, MSB24);
9356 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9357 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9361 /* if more than 1 byte */
9362 else if ( shCount >= 8 ) {
9363 /* lower order three bytes goes to higher order three bytes */
9367 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9369 movLeft2Result(left, LSB, result, MSB16);
9371 else{ /* size = 4 */
9373 movLeft2Result(left, MSB24, result, MSB32);
9374 movLeft2Result(left, MSB16, result, MSB24);
9375 movLeft2Result(left, LSB, result, MSB16);
9376 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9378 else if(shCount == 1)
9379 shiftLLong(left, result, MSB16);
9381 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9382 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9383 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9384 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9389 /* 1 <= shCount <= 7 */
9390 else if(shCount <= 3)
9392 shiftLLong(left, result, LSB);
9393 while(--shCount >= 1)
9394 shiftLLong(result, result, LSB);
9396 /* 3 <= shCount <= 7, optimize */
9398 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9399 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9400 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9404 /*-----------------------------------------------------------------*/
9405 /* genLeftShiftLiteral - left shifting by known count */
9406 /*-----------------------------------------------------------------*/
9407 void pic16_genLeftShiftLiteral (operand *left,
9412 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9416 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9417 pic16_freeAsmop(right,NULL,ic,TRUE);
9419 pic16_aopOp(left,ic,FALSE);
9420 pic16_aopOp(result,ic,TRUE);
9422 size = getSize(operandType(result));
9425 pic16_emitcode("; shift left ","result %d, left %d",size,
9429 /* I suppose that the left size >= result size */
9432 movLeft2Result(left, size, result, size);
9436 else if(shCount >= (size * 8))
9438 pic16_aopPut(AOP(result),zero,size);
9442 genlshOne (result,left,shCount);
9447 genlshTwo (result,left,shCount);
9451 genlshFour (result,left,shCount);
9455 pic16_freeAsmop(left,NULL,ic,TRUE);
9456 pic16_freeAsmop(result,NULL,ic,TRUE);
9459 /*-----------------------------------------------------------------*
9460 * genMultiAsm - repeat assembly instruction for size of register.
9461 * if endian == 1, then the high byte (i.e base address + size of
9462 * register) is used first else the low byte is used first;
9463 *-----------------------------------------------------------------*/
9464 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9482 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9488 #if !(USE_GENERIC_SIGNED_SHIFT)
9489 /*-----------------------------------------------------------------*/
9490 /* genLeftShift - generates code for left shifting */
9491 /*-----------------------------------------------------------------*/
9492 static void genLeftShift (iCode *ic)
9494 operand *left,*right, *result;
9497 symbol *tlbl , *tlbl1;
9500 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9502 right = IC_RIGHT(ic);
9504 result = IC_RESULT(ic);
9506 pic16_aopOp(right,ic,FALSE);
9508 /* if the shift count is known then do it
9509 as efficiently as possible */
9510 if (AOP_TYPE(right) == AOP_LIT) {
9511 pic16_genLeftShiftLiteral (left,right,result,ic);
9515 /* shift count is unknown then we have to form
9516 * a loop. Get the loop count in WREG : Note: we take
9517 * only the lower order byte since shifting
9518 * more than 32 bits make no sense anyway, ( the
9519 * largest size of an object can be only 32 bits ) */
9521 pic16_aopOp(left,ic,FALSE);
9522 pic16_aopOp(result,ic,FALSE);
9524 /* now move the left to the result if they are not the
9525 * same, and if size > 1,
9526 * and if right is not same to result (!!!) -- VR */
9527 if (!pic16_sameRegs(AOP(left),AOP(result))
9528 && (AOP_SIZE(result) > 1)) {
9530 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9532 size = AOP_SIZE(result);
9537 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9538 if (*l == '@' && (IS_AOP_PREG(result))) {
9540 pic16_emitcode("mov","a,%s",l);
9541 pic16_aopPut(AOP(result),"a",offset);
9545 /* we don't know if left is a literal or a register, take care -- VR */
9546 pic16_mov2f(AOP(result), AOP(left), offset);
9552 size = AOP_SIZE(result);
9554 /* if it is only one byte then */
9556 if(optimized_for_speed) {
9557 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9558 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9559 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9560 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9561 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9562 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9563 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9564 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9565 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9566 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9567 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9568 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9573 tlbl = newiTempLabel(NULL);
9576 /* this is already done, why change it? */
9577 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9578 pic16_mov2f(AOP(result), AOP(left), 0);
9582 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9583 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9584 pic16_emitpLabel(tlbl->key);
9585 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9586 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9588 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9593 if (pic16_sameRegs(AOP(left),AOP(result))) {
9595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9597 tlbl = newiTempLabel(NULL);
9598 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9599 genMultiAsm(POC_RRCF, result, size,1);
9600 pic16_emitpLabel(tlbl->key);
9601 genMultiAsm(POC_RLCF, result, size,0);
9602 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9604 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9608 //tlbl = newiTempLabel(NULL);
9610 //tlbl1 = newiTempLabel(NULL);
9612 //reAdjustPreg(AOP(result));
9614 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9615 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9616 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9618 //pic16_emitcode("add","a,acc");
9619 //pic16_aopPut(AOP(result),"a",offset++);
9621 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9623 // pic16_emitcode("rlc","a");
9624 // pic16_aopPut(AOP(result),"a",offset++);
9626 //reAdjustPreg(AOP(result));
9628 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9629 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9632 tlbl = newiTempLabel(NULL);
9633 tlbl1= newiTempLabel(NULL);
9635 size = AOP_SIZE(result);
9638 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9640 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9642 /* offset should be 0, 1 or 3 */
9644 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9646 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9648 pic16_emitpcode(POC_MOVWF, pctemp);
9651 pic16_emitpLabel(tlbl->key);
9654 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9656 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9658 pic16_emitpcode(POC_DECFSZ, pctemp);
9659 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9660 pic16_emitpLabel(tlbl1->key);
9662 pic16_popReleaseTempReg(pctemp,1);
9666 pic16_freeAsmop (right,NULL,ic,TRUE);
9667 pic16_freeAsmop(left,NULL,ic,TRUE);
9668 pic16_freeAsmop(result,NULL,ic,TRUE);
9674 #error old code (left here for reference)
9675 /*-----------------------------------------------------------------*/
9676 /* genLeftShift - generates code for left shifting */
9677 /*-----------------------------------------------------------------*/
9678 static void genLeftShift (iCode *ic)
9680 operand *left,*right, *result;
9683 symbol *tlbl , *tlbl1;
9686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9688 right = IC_RIGHT(ic);
9690 result = IC_RESULT(ic);
9692 pic16_aopOp(right,ic,FALSE);
9694 /* if the shift count is known then do it
9695 as efficiently as possible */
9696 if (AOP_TYPE(right) == AOP_LIT) {
9697 pic16_genLeftShiftLiteral (left,right,result,ic);
9701 /* shift count is unknown then we have to form
9702 a loop get the loop count in B : Note: we take
9703 only the lower order byte since shifting
9704 more that 32 bits make no sense anyway, ( the
9705 largest size of an object can be only 32 bits ) */
9708 pic16_aopOp(left,ic,FALSE);
9709 pic16_aopOp(result,ic,FALSE);
9711 /* now move the left to the result if they are not the
9713 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9714 AOP_SIZE(result) > 1) {
9716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9718 size = AOP_SIZE(result);
9721 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9722 if (*l == '@' && (IS_AOP_PREG(result))) {
9724 pic16_emitcode("mov","a,%s",l);
9725 pic16_aopPut(AOP(result),"a",offset);
9728 /* we don't know if left is a literal or a register, take care -- VR */
9729 pic16_mov2f(AOP(result), AOP(left), offset);
9735 size = AOP_SIZE(result);
9737 /* if it is only one byte then */
9739 if(optimized_for_speed) {
9740 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9741 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9742 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9743 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9744 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9745 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9746 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9747 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9748 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9749 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9750 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9751 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9754 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9756 tlbl = newiTempLabel(NULL);
9757 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9758 pic16_mov2f(AOP(result), AOP(left), 0);
9760 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9761 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9764 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9765 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9766 pic16_emitpLabel(tlbl->key);
9767 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9768 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9775 if (pic16_sameRegs(AOP(left),AOP(result))) {
9777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9779 tlbl = newiTempLabel(NULL);
9780 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9781 genMultiAsm(POC_RRCF, result, size,1);
9782 pic16_emitpLabel(tlbl->key);
9783 genMultiAsm(POC_RLCF, result, size,0);
9784 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9786 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9790 //tlbl = newiTempLabel(NULL);
9792 //tlbl1 = newiTempLabel(NULL);
9794 //reAdjustPreg(AOP(result));
9796 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9797 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9798 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9800 //pic16_emitcode("add","a,acc");
9801 //pic16_aopPut(AOP(result),"a",offset++);
9803 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9805 // pic16_emitcode("rlc","a");
9806 // pic16_aopPut(AOP(result),"a",offset++);
9808 //reAdjustPreg(AOP(result));
9810 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9811 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9814 tlbl = newiTempLabel(NULL);
9815 tlbl1= newiTempLabel(NULL);
9817 size = AOP_SIZE(result);
9820 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9824 /* offset should be 0, 1 or 3 */
9826 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9828 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9830 pic16_emitpcode(POC_MOVWF, pctemp);
9833 pic16_emitpLabel(tlbl->key);
9836 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9838 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9840 pic16_emitpcode(POC_DECFSZ, pctemp);
9841 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9842 pic16_emitpLabel(tlbl1->key);
9844 pic16_popReleaseTempReg(pctemp,1);
9848 pic16_freeAsmop (right,NULL,ic,TRUE);
9849 pic16_freeAsmop(left,NULL,ic,TRUE);
9850 pic16_freeAsmop(result,NULL,ic,TRUE);
9854 /*-----------------------------------------------------------------*/
9855 /* genrshOne - right shift a one byte quantity by known count */
9856 /*-----------------------------------------------------------------*/
9857 static void genrshOne (operand *result, operand *left,
9858 int shCount, int sign)
9860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9861 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9864 /*-----------------------------------------------------------------*/
9865 /* genrshTwo - right shift two bytes by known amount != 0 */
9866 /*-----------------------------------------------------------------*/
9867 static void genrshTwo (operand *result,operand *left,
9868 int shCount, int sign)
9870 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9871 /* if shCount >= 8 */
9875 shiftR1Left2Result(left, MSB16, result, LSB,
9878 movLeft2Result(left, MSB16, result, LSB);
9880 pic16_addSign (result, 1, sign);
9883 /* 1 <= shCount <= 7 */
9885 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9888 /*-----------------------------------------------------------------*/
9889 /* shiftRLong - shift right one long from left to result */
9890 /* offl = LSB or MSB16 */
9891 /*-----------------------------------------------------------------*/
9892 static void shiftRLong (operand *left, int offl,
9893 operand *result, int sign)
9895 int size = AOP_SIZE(result);
9896 int same = pic16_sameRegs(AOP(left),AOP(result));
9898 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9900 if (same && (offl == MSB16)) { //shift one byte right
9901 for(i=MSB16;i<size;i++) {
9902 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9903 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9908 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9914 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9916 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9921 /* add sign of "a" */
9922 pic16_addSign(result, MSB32, sign);
9926 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9928 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9933 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9935 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9940 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9943 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9949 /*-----------------------------------------------------------------*/
9950 /* genrshFour - shift four byte by a known amount != 0 */
9951 /*-----------------------------------------------------------------*/
9952 static void genrshFour (operand *result, operand *left,
9953 int shCount, int sign)
9955 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9956 /* if shifting more that 3 bytes */
9957 if(shCount >= 24 ) {
9960 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9962 movLeft2Result(left, MSB32, result, LSB);
9964 pic16_addSign(result, MSB16, sign);
9966 else if(shCount >= 16){
9969 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9971 movLeft2Result(left, MSB24, result, LSB);
9972 movLeft2Result(left, MSB32, result, MSB16);
9974 pic16_addSign(result, MSB24, sign);
9976 else if(shCount >= 8){
9979 shiftRLong(left, MSB16, result, sign);
9980 else if(shCount == 0){
9981 movLeft2Result(left, MSB16, result, LSB);
9982 movLeft2Result(left, MSB24, result, MSB16);
9983 movLeft2Result(left, MSB32, result, MSB24);
9984 pic16_addSign(result, MSB32, sign);
9986 else{ //shcount >= 2
9987 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9988 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9989 /* the last shift is signed */
9990 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9991 pic16_addSign(result, MSB32, sign);
9994 else{ /* 1 <= shCount <= 7 */
9996 shiftRLong(left, LSB, result, sign);
9998 shiftRLong(result, LSB, result, sign);
10001 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10002 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10003 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10008 /*-----------------------------------------------------------------*/
10009 /* genRightShiftLiteral - right shifting by known count */
10010 /*-----------------------------------------------------------------*/
10011 static void genRightShiftLiteral (operand *left,
10017 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10018 int lsize,res_size;
10020 pic16_freeAsmop(right,NULL,ic,TRUE);
10022 pic16_aopOp(left,ic,FALSE);
10023 pic16_aopOp(result,ic,TRUE);
10025 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10028 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10032 lsize = pic16_getDataSize(left);
10033 res_size = pic16_getDataSize(result);
10034 /* test the LEFT size !!! */
10036 /* I suppose that the left size >= result size */
10038 assert (res_size <= lsize);
10039 while (res_size--) {
10040 pic16_mov2f (AOP(result), AOP(left), res_size);
10044 else if(shCount >= (lsize * 8)){
10046 if(res_size == 1) {
10047 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10049 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10050 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10055 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10056 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10057 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10059 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10064 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10069 switch (res_size) {
10071 genrshOne (result,left,shCount,sign);
10075 genrshTwo (result,left,shCount,sign);
10079 genrshFour (result,left,shCount,sign);
10087 pic16_freeAsmop(left,NULL,ic,TRUE);
10088 pic16_freeAsmop(result,NULL,ic,TRUE);
10091 #if !(USE_GENERIC_SIGNED_SHIFT)
10092 /*-----------------------------------------------------------------*/
10093 /* genSignedRightShift - right shift of signed number */
10094 /*-----------------------------------------------------------------*/
10095 static void genSignedRightShift (iCode *ic)
10097 operand *right, *left, *result;
10100 symbol *tlbl, *tlbl1 ;
10103 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10105 /* we do it the hard way put the shift count in b
10106 and loop thru preserving the sign */
10107 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10109 right = IC_RIGHT(ic);
10110 left = IC_LEFT(ic);
10111 result = IC_RESULT(ic);
10113 pic16_aopOp(right,ic,FALSE);
10114 pic16_aopOp(left,ic,FALSE);
10115 pic16_aopOp(result,ic,FALSE);
10118 if ( AOP_TYPE(right) == AOP_LIT) {
10119 genRightShiftLiteral (left,right,result,ic,1);
10122 /* shift count is unknown then we have to form
10123 a loop get the loop count in B : Note: we take
10124 only the lower order byte since shifting
10125 more that 32 bits make no sense anyway, ( the
10126 largest size of an object can be only 32 bits ) */
10128 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10129 //pic16_emitcode("inc","b");
10130 //pic16_freeAsmop (right,NULL,ic,TRUE);
10131 //pic16_aopOp(left,ic,FALSE);
10132 //pic16_aopOp(result,ic,FALSE);
10134 /* now move the left to the result if they are not the
10136 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10137 AOP_SIZE(result) > 1) {
10139 size = AOP_SIZE(result);
10143 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10144 if (*l == '@' && IS_AOP_PREG(result)) {
10146 pic16_emitcode("mov","a,%s",l);
10147 pic16_aopPut(AOP(result),"a",offset);
10149 pic16_aopPut(AOP(result),l,offset);
10151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10152 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10158 /* mov the highest order bit to OVR */
10159 tlbl = newiTempLabel(NULL);
10160 tlbl1= newiTempLabel(NULL);
10162 size = AOP_SIZE(result);
10165 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10167 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10169 /* offset should be 0, 1 or 3 */
10170 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10172 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10174 pic16_emitpcode(POC_MOVWF, pctemp);
10177 pic16_emitpLabel(tlbl->key);
10179 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10180 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10183 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10186 pic16_emitpcode(POC_DECFSZ, pctemp);
10187 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10188 pic16_emitpLabel(tlbl1->key);
10190 pic16_popReleaseTempReg(pctemp,1);
10192 size = AOP_SIZE(result);
10194 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10195 pic16_emitcode("rlc","a");
10196 pic16_emitcode("mov","ov,c");
10197 /* if it is only one byte then */
10199 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10201 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10202 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10203 pic16_emitcode("mov","c,ov");
10204 pic16_emitcode("rrc","a");
10205 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10206 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10207 pic16_aopPut(AOP(result),"a",0);
10211 reAdjustPreg(AOP(result));
10212 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10213 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10214 pic16_emitcode("mov","c,ov");
10216 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10218 pic16_emitcode("rrc","a");
10219 pic16_aopPut(AOP(result),"a",offset--);
10221 reAdjustPreg(AOP(result));
10222 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10223 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10228 pic16_freeAsmop(left,NULL,ic,TRUE);
10229 pic16_freeAsmop(result,NULL,ic,TRUE);
10230 pic16_freeAsmop(right,NULL,ic,TRUE);
10234 #if !(USE_GENERIC_SIGNED_SHIFT)
10235 #warning This implementation of genRightShift() is incomplete!
10236 /*-----------------------------------------------------------------*/
10237 /* genRightShift - generate code for right shifting */
10238 /*-----------------------------------------------------------------*/
10239 static void genRightShift (iCode *ic)
10241 operand *right, *left, *result;
10245 symbol *tlbl, *tlbl1 ;
10247 /* if signed then we do it the hard way preserve the
10248 sign bit moving it inwards */
10249 letype = getSpec(operandType(IC_LEFT(ic)));
10250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10252 if (!SPEC_USIGN(letype)) {
10253 genSignedRightShift (ic);
10257 /* signed & unsigned types are treated the same : i.e. the
10258 signed is NOT propagated inwards : quoting from the
10259 ANSI - standard : "for E1 >> E2, is equivalent to division
10260 by 2**E2 if unsigned or if it has a non-negative value,
10261 otherwise the result is implementation defined ", MY definition
10262 is that the sign does not get propagated */
10264 right = IC_RIGHT(ic);
10265 left = IC_LEFT(ic);
10266 result = IC_RESULT(ic);
10268 pic16_aopOp(right,ic,FALSE);
10270 /* if the shift count is known then do it
10271 as efficiently as possible */
10272 if (AOP_TYPE(right) == AOP_LIT) {
10273 genRightShiftLiteral (left,right,result,ic, 0);
10277 /* shift count is unknown then we have to form
10278 a loop get the loop count in B : Note: we take
10279 only the lower order byte since shifting
10280 more that 32 bits make no sense anyway, ( the
10281 largest size of an object can be only 32 bits ) */
10283 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10284 pic16_emitcode("inc","b");
10285 pic16_aopOp(left,ic,FALSE);
10286 pic16_aopOp(result,ic,FALSE);
10288 /* now move the left to the result if they are not the
10290 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10291 AOP_SIZE(result) > 1) {
10293 size = AOP_SIZE(result);
10296 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10297 if (*l == '@' && IS_AOP_PREG(result)) {
10299 pic16_emitcode("mov","a,%s",l);
10300 pic16_aopPut(AOP(result),"a",offset);
10302 pic16_aopPut(AOP(result),l,offset);
10307 tlbl = newiTempLabel(NULL);
10308 tlbl1= newiTempLabel(NULL);
10309 size = AOP_SIZE(result);
10312 /* if it is only one byte then */
10315 tlbl = newiTempLabel(NULL);
10316 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10317 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10318 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10321 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10322 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10323 pic16_emitpLabel(tlbl->key);
10324 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10325 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10327 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10332 reAdjustPreg(AOP(result));
10333 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10334 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10337 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10339 pic16_emitcode("rrc","a");
10340 pic16_aopPut(AOP(result),"a",offset--);
10342 reAdjustPreg(AOP(result));
10344 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10345 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10348 pic16_freeAsmop(left,NULL,ic,TRUE);
10349 pic16_freeAsmop (right,NULL,ic,TRUE);
10350 pic16_freeAsmop(result,NULL,ic,TRUE);
10354 #if (USE_GENERIC_SIGNED_SHIFT)
10355 /*-----------------------------------------------------------------*/
10356 /* genGenericShift - generates code for left or right shifting */
10357 /*-----------------------------------------------------------------*/
10358 static void genGenericShift (iCode *ic, int isShiftLeft) {
10359 operand *left,*right, *result;
10361 int sign, signedCount;
10362 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10363 PIC_OPCODE pos_shift, neg_shift;
10367 right = IC_RIGHT(ic);
10368 left = IC_LEFT(ic);
10369 result = IC_RESULT(ic);
10371 pic16_aopOp(right,ic,FALSE);
10372 pic16_aopOp(left,ic,FALSE);
10373 pic16_aopOp(result,ic,TRUE);
10375 sign = !SPEC_USIGN(operandType (left));
10376 signedCount = !SPEC_USIGN(operandType (right));
10378 /* if the shift count is known then do it
10379 as efficiently as possible */
10380 if (AOP_TYPE(right) == AOP_LIT) {
10381 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10382 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10383 // we should modify right->aopu.aop_lit here!
10384 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10385 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10387 pic16_genLeftShiftLiteral (left,right,result,ic);
10389 genRightShiftLiteral (left,right,result,ic, sign);
10392 } // if (right is literal)
10394 /* shift count is unknown then we have to form a loop.
10395 * Note: we take only the lower order byte since shifting
10396 * more than 32 bits make no sense anyway, ( the
10397 * largest size of an object can be only 32 bits )
10398 * Note: we perform arithmetic shifts if the left operand is
10399 * signed and we do an (effective) right shift, i. e. we
10400 * shift in the sign bit from the left. */
10402 label_complete = newiTempLabel ( NULL );
10403 label_loop_pos = newiTempLabel ( NULL );
10404 label_loop_neg = NULL;
10405 label_negative = NULL;
10406 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10407 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10410 // additional labels needed
10411 label_loop_neg = newiTempLabel ( NULL );
10412 label_negative = newiTempLabel ( NULL );
10415 // copy source to result -- this will effectively truncate the left operand to the size of result!
10416 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10417 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10418 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10419 pic16_mov2f (AOP(result),AOP(left), offset);
10422 // if result is longer than left, fill with zeros (or sign)
10423 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10424 if (sign && AOP_SIZE(left) > 0) {
10425 // shift signed operand -- fill with sign
10426 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10427 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10428 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10429 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10430 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10433 // shift unsigned operand -- fill result with zeros
10434 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10435 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10438 } // if (size mismatch)
10440 pic16_mov2w (AOP(right), 0);
10441 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10442 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10445 // perform a shift by one (shift count is positive)
10446 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10447 // 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])
10448 pic16_emitpLabel (label_loop_pos->key);
10450 if (sign && (pos_shift == POC_RRCF)) {
10451 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10454 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10455 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10456 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10458 // perform a shift by one (shift count is positive)
10459 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460 // 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])
10461 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10462 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10464 pic16_emitpLabel (label_loop_pos->key);
10465 if (sign && (pos_shift == POC_RRCF)) {
10466 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10469 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10470 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10471 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10472 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10476 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10478 pic16_emitpLabel (label_negative->key);
10479 // perform a shift by -1 (shift count is negative)
10480 // 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)
10482 pic16_emitpLabel (label_loop_neg->key);
10483 if (sign && (neg_shift == POC_RRCF)) {
10484 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10487 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10488 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10489 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10490 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10491 } // if (signedCount)
10493 pic16_emitpLabel (label_complete->key);
10496 pic16_freeAsmop (right,NULL,ic,TRUE);
10497 pic16_freeAsmop(left,NULL,ic,TRUE);
10498 pic16_freeAsmop(result,NULL,ic,TRUE);
10501 static void genLeftShift (iCode *ic) {
10502 genGenericShift (ic, 1);
10505 static void genRightShift (iCode *ic) {
10506 genGenericShift (ic, 0);
10511 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10512 void pic16_loadFSR0(operand *op, int lit)
10514 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10515 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10517 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10518 // set up FSR0 with address of result
10519 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10520 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10524 /*----------------------------------------------------------------*/
10525 /* pic16_derefPtr - move one byte from the location ptr points to */
10526 /* to WREG (doWrite == 0) or one byte from WREG */
10527 /* to the location ptr points to (doWrite != 0) */
10528 /*----------------------------------------------------------------*/
10529 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10531 if (!IS_PTR(operandType(ptr)))
10533 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10534 else pic16_mov2w (AOP(ptr), 0);
10538 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10539 /* We might determine pointer type right here: */
10540 p_type = DCL_TYPE(operandType(ptr));
10545 if (!fsr0_setup || !*fsr0_setup)
10547 pic16_loadFSR0( ptr, 0 );
10548 if (fsr0_setup) *fsr0_setup = 1;
10551 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10553 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10557 if (AOP(ptr)->aopu.aop_reg[2]) {
10558 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10559 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10560 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10561 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10562 pic16_mov2w(AOP(ptr), 2);
10563 pic16_callGenericPointerRW(doWrite, 1);
10565 // data pointer (just 2 byte given)
10566 if (!fsr0_setup || !*fsr0_setup)
10568 pic16_loadFSR0( ptr, 0 );
10569 if (fsr0_setup) *fsr0_setup = 1;
10572 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10574 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10579 assert (0 && "invalid pointer type specified");
10584 /*-----------------------------------------------------------------*/
10585 /* genUnpackBits - generates code for unpacking bits */
10586 /*-----------------------------------------------------------------*/
10587 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10590 sym_link *etype, *letype;
10591 int blen=0, bstr=0;
10596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10597 etype = getSpec(operandType(result));
10598 letype = getSpec(operandType(left));
10600 // if(IS_BITFIELD(etype)) {
10601 blen = SPEC_BLEN(etype);
10602 bstr = SPEC_BSTR(etype);
10605 lbstr = SPEC_BSTR( letype );
10607 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10608 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10611 if((blen == 1) && (bstr < 8)
10612 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10613 /* it is a single bit, so use the appropriate bit instructions */
10614 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10616 same = pic16_sameRegs(AOP(left),AOP(result));
10617 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10618 pic16_emitpcode(POC_CLRF, op);
10620 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10621 /* workaround to reduce the extra lfsr instruction */
10622 pic16_emitpcode(POC_BTFSC,
10623 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10625 assert (PIC_IS_DATA_PTR (operandType(left)));
10626 pic16_loadFSR0 (left, 0);
10627 pic16_emitpcode(POC_BTFSC,
10628 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10631 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10632 /* unsigned bitfields result in either 0 or 1 */
10633 pic16_emitpcode(POC_INCF, op);
10635 /* signed bitfields result in either 0 or -1 */
10636 pic16_emitpcode(POC_DECF, op);
10639 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10642 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10648 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10649 // access symbol directly
10650 pic16_mov2w (AOP(left), 0);
10652 pic16_derefPtr (left, ptype, 0, NULL);
10655 /* if we have bitdisplacement then it fits */
10656 /* into this byte completely or if length is */
10657 /* less than a byte */
10658 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10660 /* shift right acc */
10663 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10664 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10666 /* VR -- normally I would use the following, but since we use the hack,
10667 * to avoid the masking from AccRsh, why not mask it right now? */
10670 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10673 /* extend signed bitfields to 8 bits */
10674 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10676 assert (blen + bstr > 0);
10677 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10678 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10681 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10683 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10687 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10688 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10695 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10697 int size, offset = 0, leoffset=0 ;
10699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10700 pic16_aopOp(result, ic, TRUE);
10704 size = AOP_SIZE(result);
10705 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10709 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10710 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10711 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10716 if(AOP(left)->aopu.pcop->type == PO_DIR)
10717 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10719 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10722 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10724 // pic16_DumpOp("(result)",result);
10725 if(is_LitAOp(AOP(result))) {
10726 pic16_mov2w(AOP(left), offset); // patch 8
10727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10729 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10730 pic16_popGet(AOP(left), offset), //patch 8
10731 pic16_popGet(AOP(result), offset)));
10739 pic16_freeAsmop(result,NULL,ic,TRUE);
10744 /*-----------------------------------------------------------------*/
10745 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10746 /*-----------------------------------------------------------------*/
10747 static void genNearPointerGet (operand *left,
10751 // asmop *aop = NULL;
10752 //regs *preg = NULL ;
10753 sym_link *rtype, *retype;
10754 sym_link *ltype, *letype;
10758 rtype = operandType(result);
10759 retype= getSpec(rtype);
10760 ltype = operandType(left);
10761 letype= getSpec(ltype);
10763 pic16_aopOp(left,ic,FALSE);
10765 // pic16_DumpOp("(left)",left);
10766 // pic16_DumpOp("(result)",result);
10768 /* if left is rematerialisable and
10769 * result is not bit variable type and
10770 * the left is pointer to data space i.e
10771 * lower 128 bytes of space */
10773 if (AOP_TYPE(left) == AOP_PCODE
10774 && !IS_BITFIELD(retype)
10775 && DCL_TYPE(ltype) == POINTER) {
10777 genDataPointerGet (left,result,ic);
10778 pic16_freeAsmop(left, NULL, ic, TRUE);
10782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10783 pic16_aopOp (result,ic,TRUE);
10785 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10788 if(IS_BITFIELD( retype )
10789 && (SPEC_BLEN(operandType(result))==1)
10793 int bitstrt, bytestrt;
10795 /* if this is bitfield of size 1, see if we are checking the value
10796 * of a single bit in an if-statement,
10797 * if yes, then don't generate usual code, but execute the
10798 * genIfx directly -- VR */
10802 /* CHECK: if next iCode is IFX
10803 * and current result operand is nextic's conditional operand
10804 * and current result operand live ranges ends at nextic's key number
10806 if((nextic->op == IFX)
10807 && (result == IC_COND(nextic))
10808 && (OP_LIVETO(result) == nextic->seq)
10809 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10811 /* everything is ok then */
10812 /* find a way to optimize the genIfx iCode */
10814 bytestrt = SPEC_BSTR(operandType(result))/8;
10815 bitstrt = SPEC_BSTR(operandType(result))%8;
10817 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10819 genIfxpCOpJump(nextic, jop);
10821 pic16_freeAsmop(left, NULL, ic, TRUE);
10822 pic16_freeAsmop(result, NULL, ic, TRUE);
10828 /* if bitfield then unpack the bits */
10829 if (IS_BITFIELD(letype))
10830 genUnpackBits (result, left, NULL, POINTER);
10832 /* we have can just get the values */
10833 int size = AOP_SIZE(result);
10836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10838 pic16_loadFSR0( left, 0 );
10842 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10843 pic16_popGet(AOP(result), offset++)));
10845 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10846 pic16_popGet(AOP(result), offset++)));
10852 /* now some housekeeping stuff */
10854 /* we had to allocate for this iCode */
10855 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10856 pic16_freeAsmop(NULL,aop,ic,TRUE);
10858 /* we did not allocate which means left
10859 * already in a pointer register, then
10860 * if size > 0 && this could be used again
10861 * we have to point it back to where it
10863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10864 if (AOP_SIZE(result) > 1
10865 && !OP_SYMBOL(left)->remat
10866 && ( OP_SYMBOL(left)->liveTo > ic->seq
10868 // int size = AOP_SIZE(result) - 1;
10870 // pic16_emitcode("dec","%s",rname);
10876 pic16_freeAsmop(left,NULL,ic,TRUE);
10877 pic16_freeAsmop(result,NULL,ic,TRUE);
10880 /*-----------------------------------------------------------------*/
10881 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10882 /*-----------------------------------------------------------------*/
10883 static void genPagedPointerGet (operand *left,
10888 regs *preg = NULL ;
10890 sym_link *rtype, *retype;
10892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10894 rtype = operandType(result);
10895 retype= getSpec(rtype);
10897 pic16_aopOp(left,ic,FALSE);
10899 /* if the value is already in a pointer register
10900 then don't need anything more */
10901 if (!AOP_INPREG(AOP(left))) {
10902 /* otherwise get a free pointer register */
10904 preg = getFreePtr(ic,&aop,FALSE);
10905 pic16_emitcode("mov","%s,%s",
10907 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10908 rname = preg->name ;
10910 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10912 pic16_freeAsmop(left,NULL,ic,TRUE);
10913 pic16_aopOp (result,ic,TRUE);
10915 /* if bitfield then unpack the bits */
10916 if (IS_BITFIELD(retype))
10917 genUnpackBits (result,left,rname,PPOINTER);
10919 /* we have can just get the values */
10920 int size = AOP_SIZE(result);
10925 pic16_emitcode("movx","a,@%s",rname);
10926 pic16_aopPut(AOP(result),"a",offset);
10931 pic16_emitcode("inc","%s",rname);
10935 /* now some housekeeping stuff */
10937 /* we had to allocate for this iCode */
10938 pic16_freeAsmop(NULL,aop,ic,TRUE);
10940 /* we did not allocate which means left
10941 already in a pointer register, then
10942 if size > 0 && this could be used again
10943 we have to point it back to where it
10945 if (AOP_SIZE(result) > 1 &&
10946 !OP_SYMBOL(left)->remat &&
10947 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10949 int size = AOP_SIZE(result) - 1;
10951 pic16_emitcode("dec","%s",rname);
10956 pic16_freeAsmop(result,NULL,ic,TRUE);
10962 /* This code is not adjusted to PIC16 and fails utterly.
10963 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10965 /*-----------------------------------------------------------------*/
10966 /* genFarPointerGet - gget value from far space */
10967 /*-----------------------------------------------------------------*/
10968 static void genFarPointerGet (operand *left,
10969 operand *result, iCode *ic)
10972 sym_link *retype = getSpec(operandType(result));
10974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10976 pic16_aopOp(left,ic,FALSE);
10978 /* if the operand is already in dptr
10979 then we do nothing else we move the value to dptr */
10980 if (AOP_TYPE(left) != AOP_STR) {
10981 /* if this is remateriazable */
10982 if (AOP_TYPE(left) == AOP_IMMD)
10983 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10984 else { /* we need to get it byte by byte */
10985 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10986 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10987 if (options.model == MODEL_FLAT24)
10989 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10993 /* so dptr know contains the address */
10994 pic16_freeAsmop(left,NULL,ic,TRUE);
10995 pic16_aopOp(result,ic,TRUE);
10997 /* if bit then unpack */
10998 if (IS_BITFIELD(retype))
10999 genUnpackBits(result,left,"dptr",FPOINTER);
11001 size = AOP_SIZE(result);
11005 pic16_emitcode("movx","a,@dptr");
11006 pic16_aopPut(AOP(result),"a",offset++);
11008 pic16_emitcode("inc","dptr");
11012 pic16_freeAsmop(result,NULL,ic,TRUE);
11017 /*-----------------------------------------------------------------*/
11018 /* genCodePointerGet - get value from code space */
11019 /*-----------------------------------------------------------------*/
11020 static void genCodePointerGet (operand *left,
11021 operand *result, iCode *ic)
11024 sym_link *retype = getSpec(operandType(result));
11026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11028 pic16_aopOp(left,ic,FALSE);
11030 /* if the operand is already in dptr
11031 then we do nothing else we move the value to dptr */
11032 if (AOP_TYPE(left) != AOP_STR) {
11033 /* if this is remateriazable */
11034 if (AOP_TYPE(left) == AOP_IMMD)
11035 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11036 else { /* we need to get it byte by byte */
11037 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11038 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11039 if (options.model == MODEL_FLAT24)
11041 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11045 /* so dptr know contains the address */
11046 pic16_freeAsmop(left,NULL,ic,TRUE);
11047 pic16_aopOp(result,ic,FALSE);
11049 /* if bit then unpack */
11050 if (IS_BITFIELD(retype))
11051 genUnpackBits(result,left,"dptr",CPOINTER);
11053 size = AOP_SIZE(result);
11057 pic16_emitcode("clr","a");
11058 pic16_emitcode("movc","a,@a+dptr");
11059 pic16_aopPut(AOP(result),"a",offset++);
11061 pic16_emitcode("inc","dptr");
11065 pic16_freeAsmop(result,NULL,ic,TRUE);
11070 /*-----------------------------------------------------------------*/
11071 /* genGenPointerGet - gget value from generic pointer space */
11072 /*-----------------------------------------------------------------*/
11073 static void genGenPointerGet (operand *left,
11074 operand *result, iCode *ic)
11076 int size, offset, lit;
11077 sym_link *retype = getSpec(operandType(result));
11079 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11080 pic16_aopOp(left,ic,FALSE);
11081 pic16_aopOp(result,ic,FALSE);
11082 size = AOP_SIZE(result);
11084 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11086 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11088 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11089 // load FSR0 from immediate
11090 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11092 // pic16_loadFSR0( left );
11097 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11099 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11106 else { /* we need to get it byte by byte */
11107 // set up FSR0 with address from left
11108 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11109 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11115 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11117 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11124 /* if bit then unpack */
11125 if (IS_BITFIELD(retype))
11126 genUnpackBits(result,left,"BAD",GPOINTER);
11129 pic16_freeAsmop(left,NULL,ic,TRUE);
11130 pic16_freeAsmop(result,NULL,ic,TRUE);
11136 /*-----------------------------------------------------------------*/
11137 /* genGenPointerGet - gget value from generic pointer space */
11138 /*-----------------------------------------------------------------*/
11139 static void genGenPointerGet (operand *left,
11140 operand *result, iCode *ic)
11142 int size, offset, lit;
11143 sym_link *letype = getSpec(operandType(left));
11145 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11146 pic16_aopOp(left,ic,FALSE);
11147 pic16_aopOp(result,ic,TRUE);
11148 size = AOP_SIZE(result);
11150 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11152 /* if bit then unpack */
11153 if (IS_BITFIELD(letype)) {
11154 genUnpackBits(result,left,"BAD",GPOINTER);
11158 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11160 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11161 // load FSR0 from immediate
11162 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11164 werror(W_POSSBUG2, __FILE__, __LINE__);
11169 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11171 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11178 } else { /* we need to get it byte by byte */
11180 /* set up WREG:PRODL:FSR0L with address from left */
11181 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11182 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11183 pic16_mov2w(AOP(left), 2);
11184 pic16_callGenericPointerRW(0, size);
11186 assignResultValue(result, 1);
11192 pic16_freeAsmop(left,NULL,ic,TRUE);
11193 pic16_freeAsmop(result,NULL,ic,TRUE);
11196 /*-----------------------------------------------------------------*/
11197 /* genConstPointerGet - get value from const generic pointer space */
11198 /*-----------------------------------------------------------------*/
11199 static void genConstPointerGet (operand *left,
11200 operand *result, iCode *ic)
11202 //sym_link *retype = getSpec(operandType(result));
11203 // symbol *albl = newiTempLabel(NULL); // patch 15
11204 // symbol *blbl = newiTempLabel(NULL); //
11205 // PIC_OPCODE poc; // patch 15
11209 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11210 pic16_aopOp(left,ic,FALSE);
11211 pic16_aopOp(result,ic,TRUE);
11212 size = AOP_SIZE(result);
11214 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11216 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11218 // set up table pointer
11219 if( (AOP_TYPE(left) == AOP_PCODE)
11220 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11221 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11223 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11224 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11225 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11226 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11227 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11228 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11230 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11231 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11232 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11236 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11237 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11241 pic16_freeAsmop(left,NULL,ic,TRUE);
11242 pic16_freeAsmop(result,NULL,ic,TRUE);
11246 /*-----------------------------------------------------------------*/
11247 /* genPointerGet - generate code for pointer get */
11248 /*-----------------------------------------------------------------*/
11249 static void genPointerGet (iCode *ic)
11251 operand *left, *result ;
11252 sym_link *type, *etype;
11257 left = IC_LEFT(ic);
11258 result = IC_RESULT(ic) ;
11260 /* depending on the type of pointer we need to
11261 move it to the correct pointer register */
11262 type = operandType(left);
11263 etype = getSpec(type);
11266 if (IS_PTR_CONST(type))
11268 if (IS_CODEPTR(type))
11270 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11272 /* if left is of type of pointer then it is simple */
11273 if (IS_PTR(type) && !IS_FUNC(type->next))
11274 p_type = DCL_TYPE(type);
11276 /* we have to go by the storage class */
11277 p_type = PTR_TYPE(SPEC_OCLS(etype));
11279 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11281 if (SPEC_OCLS(etype)->codesp ) {
11282 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11283 //p_type = CPOINTER ;
11285 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11286 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11287 /*p_type = FPOINTER ;*/
11289 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11290 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11291 /* p_type = PPOINTER; */
11293 if (SPEC_OCLS(etype) == idata ) {
11294 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11295 /* p_type = IPOINTER; */
11297 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11298 /* p_type = POINTER ; */
11302 /* now that we have the pointer type we assign
11303 the pointer values */
11308 genNearPointerGet (left,result,ic);
11312 genPagedPointerGet(left,result,ic);
11316 /* PICs do not support FAR pointers... */
11317 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11319 genFarPointerGet (left,result,ic);
11324 genConstPointerGet (left,result,ic);
11325 //pic16_emitcodePointerGet (left,result,ic);
11330 if (IS_PTR_CONST(type))
11331 genConstPointerGet (left,result,ic);
11334 genGenPointerGet (left,result,ic);
11338 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11339 "genPointerGet: illegal pointer type");
11344 /*-----------------------------------------------------------------*/
11345 /* genPackBits - generates code for packed bit storage */
11346 /*-----------------------------------------------------------------*/
11347 static void genPackBits (sym_link *etype , operand *result,
11349 char *rname, int p_type)
11355 int shifted_and_masked = 0;
11356 unsigned long lit = (unsigned long)-1;
11359 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11360 blen = SPEC_BLEN(etype);
11361 bstr = SPEC_BSTR(etype);
11363 retype = getSpec(operandType(right));
11365 if(AOP_TYPE(right) == AOP_LIT) {
11366 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11368 if((blen == 1) && (bstr < 8)) {
11369 /* it is a single bit, so use the appropriate bit instructions */
11371 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11373 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11374 /* workaround to reduce the extra lfsr instruction */
11376 pic16_emitpcode(POC_BSF,
11377 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11379 pic16_emitpcode(POC_BCF,
11380 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11383 if (PIC_IS_DATA_PTR(operandType(result))) {
11384 pic16_loadFSR0(result, 0);
11385 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11386 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11388 /* get old value */
11389 pic16_derefPtr (result, p_type, 0, NULL);
11390 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11391 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11392 /* write back new value */
11393 pic16_derefPtr (result, p_type, 1, NULL);
11399 /* IORLW below is more efficient */
11400 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11401 lit = (lit & ((1UL << blen) - 1)) << bstr;
11402 shifted_and_masked = 1;
11405 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11406 && IS_BITFIELD(retype)
11407 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11411 rblen = SPEC_BLEN( retype );
11412 rbstr = SPEC_BSTR( retype );
11414 if(IS_BITFIELD(etype)) {
11415 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11416 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11418 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11421 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11423 if(IS_BITFIELD(etype)) {
11424 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11426 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11429 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11433 /* move right to W */
11434 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11437 /* if the bit length is less than or */
11438 /* it exactly fits a byte then */
11439 if((shCnt=SPEC_BSTR(etype))
11440 || SPEC_BLEN(etype) <= 8 ) {
11441 int fsr0_setup = 0;
11443 if (blen != 8 || bstr != 0) {
11444 // we need to combine the value with the old value
11445 if(!shifted_and_masked)
11447 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11449 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11450 SPEC_BSTR(etype), SPEC_BLEN(etype));
11452 /* shift left acc, do NOT mask the result again */
11455 /* using PRODH as a temporary register here */
11456 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11459 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11460 || IS_DIRECT(result)) {
11461 /* access symbol directly */
11462 pic16_mov2w (AOP(result), 0);
11464 /* get old value */
11465 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11468 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11469 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11470 (unsigned char)(0xff >> (8-bstr))) ));
11471 if (!shifted_and_masked) {
11472 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11474 /* We have the shifted and masked (literal) right value in `lit' */
11476 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11478 } // if (blen != 8 || bstr != 0)
11480 /* write new value back */
11481 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11482 || IS_DIRECT(result)) {
11483 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11485 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11494 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11495 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11500 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11501 rLen = SPEC_BLEN(etype)-8;
11503 /* now generate for lengths greater than one byte */
11507 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11513 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11519 pic16_emitcode("movx","@dptr,a");
11524 DEBUGpic16_emitcode(";lcall","__gptrput");
11532 pic16_mov2w(AOP(right), offset++);
11535 /* last last was not complete */
11537 /* save the byte & read byte */
11540 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11541 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11546 pic16_emitcode ("mov","b,a");
11547 pic16_emitcode("movx","a,@dptr");
11551 pic16_emitcode ("push","b");
11552 pic16_emitcode ("push","acc");
11553 pic16_emitcode ("lcall","__gptrget");
11554 pic16_emitcode ("pop","b");
11560 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11561 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11562 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11563 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11564 // pic16_emitcode ("orl","a,b");
11567 // if (p_type == GPOINTER)
11568 // pic16_emitcode("pop","b");
11573 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11574 // pic16_emitcode("mov","@%s,a",rname);
11578 pic16_emitcode("movx","@dptr,a");
11582 DEBUGpic16_emitcode(";lcall","__gptrput");
11589 // pic16_freeAsmop(right, NULL, ic, TRUE);
11592 /*-----------------------------------------------------------------*/
11593 /* genDataPointerSet - remat pointer to data space */
11594 /*-----------------------------------------------------------------*/
11595 static void genDataPointerSet(operand *right,
11599 int size, offset = 0, resoffset=0 ;
11601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11602 pic16_aopOp(right,ic,FALSE);
11604 size = AOP_SIZE(right);
11606 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11609 if ( AOP_TYPE(result) == AOP_PCODE) {
11610 fprintf(stderr,"genDataPointerSet %s, %d\n",
11611 AOP(result)->aopu.pcop->name,
11612 (AOP(result)->aopu.pcop->type == PO_DIR)?
11613 PCOR(AOP(result)->aopu.pcop)->instance:
11614 PCOI(AOP(result)->aopu.pcop)->offset);
11618 if(AOP(result)->aopu.pcop->type == PO_DIR)
11619 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11622 if (AOP_TYPE(right) == AOP_LIT) {
11625 if(!IS_FLOAT(operandType( right )))
11626 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11629 unsigned long lit_int;
11633 /* take care if literal is a float */
11634 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11635 lit = info.lit_int;
11637 lit = lit >> (8*offset);
11638 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11640 pic16_mov2w(AOP(right), offset);
11641 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11647 pic16_freeAsmop(right,NULL,ic,TRUE);
11652 /*-----------------------------------------------------------------*/
11653 /* genNearPointerSet - pic16_emitcode for near pointer put */
11654 /*-----------------------------------------------------------------*/
11655 static void genNearPointerSet (operand *right,
11661 sym_link *ptype = operandType(result);
11662 sym_link *resetype;
11664 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11665 retype= getSpec(operandType(right));
11666 resetype = getSpec(operandType(result));
11668 pic16_aopOp(result,ic,FALSE);
11670 /* if the result is rematerializable &
11671 * in data space & not a bit variable */
11673 /* and result is not a bit variable */
11674 if (AOP_TYPE(result) == AOP_PCODE
11675 // && AOP_TYPE(result) == AOP_IMMD
11676 && DCL_TYPE(ptype) == POINTER
11677 && !IS_BITFIELD(retype)
11678 && !IS_BITFIELD(resetype)) {
11680 genDataPointerSet (right,result,ic);
11681 pic16_freeAsmop(result,NULL,ic,TRUE);
11685 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11686 pic16_aopOp(right,ic,FALSE);
11687 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11689 /* if bitfield then unpack the bits */
11690 if (IS_BITFIELD(resetype)) {
11691 genPackBits (resetype, result, right, NULL, POINTER);
11693 /* we have can just get the values */
11694 int size = AOP_SIZE(right);
11697 pic16_loadFSR0(result, 0);
11699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11701 if (AOP_TYPE(right) == AOP_LIT) {
11702 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11704 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11706 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11708 } else { // no literal
11710 pic16_emitpcode(POC_MOVFF,
11711 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11712 pic16_popCopyReg(&pic16_pc_postinc0)));
11714 pic16_emitpcode(POC_MOVFF,
11715 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11716 pic16_popCopyReg(&pic16_pc_indf0)));
11724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11725 /* now some housekeeping stuff */
11727 /* we had to allocate for this iCode */
11728 pic16_freeAsmop(NULL,aop,ic,TRUE);
11730 /* we did not allocate which means left
11731 * already in a pointer register, then
11732 * if size > 0 && this could be used again
11733 * we have to point it back to where it
11735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11736 if (AOP_SIZE(right) > 1
11737 && !OP_SYMBOL(result)->remat
11738 && ( OP_SYMBOL(result)->liveTo > ic->seq
11741 int size = AOP_SIZE(right) - 1;
11744 pic16_emitcode("decf","fsr0,f");
11745 //pic16_emitcode("dec","%s",rname);
11749 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11752 pic16_freeAsmop(right,NULL,ic,TRUE);
11753 pic16_freeAsmop(result,NULL,ic,TRUE);
11756 /*-----------------------------------------------------------------*/
11757 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11758 /*-----------------------------------------------------------------*/
11759 static void genPagedPointerSet (operand *right,
11764 regs *preg = NULL ;
11768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11770 retype= getSpec(operandType(right));
11772 pic16_aopOp(result,ic,FALSE);
11774 /* if the value is already in a pointer register
11775 then don't need anything more */
11776 if (!AOP_INPREG(AOP(result))) {
11777 /* otherwise get a free pointer register */
11779 preg = getFreePtr(ic,&aop,FALSE);
11780 pic16_emitcode("mov","%s,%s",
11782 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11783 rname = preg->name ;
11785 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11787 pic16_freeAsmop(result,NULL,ic,TRUE);
11788 pic16_aopOp (right,ic,FALSE);
11790 /* if bitfield then unpack the bits */
11791 if (IS_BITFIELD(retype))
11792 genPackBits (retype,result,right,rname,PPOINTER);
11794 /* we have can just get the values */
11795 int size = AOP_SIZE(right);
11799 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11802 pic16_emitcode("movx","@%s,a",rname);
11805 pic16_emitcode("inc","%s",rname);
11811 /* now some housekeeping stuff */
11813 /* we had to allocate for this iCode */
11814 pic16_freeAsmop(NULL,aop,ic,TRUE);
11816 /* we did not allocate which means left
11817 already in a pointer register, then
11818 if size > 0 && this could be used again
11819 we have to point it back to where it
11821 if (AOP_SIZE(right) > 1 &&
11822 !OP_SYMBOL(result)->remat &&
11823 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11825 int size = AOP_SIZE(right) - 1;
11827 pic16_emitcode("dec","%s",rname);
11832 pic16_freeAsmop(right,NULL,ic,TRUE);
11838 /* This code is not adjusted to PIC16 and fails utterly...
11839 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11841 /*-----------------------------------------------------------------*/
11842 /* genFarPointerSet - set value from far space */
11843 /*-----------------------------------------------------------------*/
11844 static void genFarPointerSet (operand *right,
11845 operand *result, iCode *ic)
11848 sym_link *retype = getSpec(operandType(right));
11850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11851 pic16_aopOp(result,ic,FALSE);
11853 /* if the operand is already in dptr
11854 then we do nothing else we move the value to dptr */
11855 if (AOP_TYPE(result) != AOP_STR) {
11856 /* if this is remateriazable */
11857 if (AOP_TYPE(result) == AOP_IMMD)
11858 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11859 else { /* we need to get it byte by byte */
11860 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11861 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11862 if (options.model == MODEL_FLAT24)
11864 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11868 /* so dptr know contains the address */
11869 pic16_freeAsmop(result,NULL,ic,TRUE);
11870 pic16_aopOp(right,ic,FALSE);
11872 /* if bit then unpack */
11873 if (IS_BITFIELD(retype))
11874 genPackBits(retype,result,right,"dptr",FPOINTER);
11876 size = AOP_SIZE(right);
11880 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11882 pic16_emitcode("movx","@dptr,a");
11884 pic16_emitcode("inc","dptr");
11888 pic16_freeAsmop(right,NULL,ic,TRUE);
11892 /*-----------------------------------------------------------------*/
11893 /* genGenPointerSet - set value from generic pointer space */
11894 /*-----------------------------------------------------------------*/
11896 static void genGenPointerSet (operand *right,
11897 operand *result, iCode *ic)
11899 int i, size, offset, lit;
11900 sym_link *retype = getSpec(operandType(right));
11902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11904 pic16_aopOp(result,ic,FALSE);
11905 pic16_aopOp(right,ic,FALSE);
11906 size = AOP_SIZE(right);
11909 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11911 /* if the operand is already in dptr
11912 then we do nothing else we move the value to dptr */
11913 if (AOP_TYPE(result) != AOP_STR) {
11914 /* if this is remateriazable */
11915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11916 // WARNING: anythig until "else" is untested!
11917 if (AOP_TYPE(result) == AOP_IMMD) {
11918 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11919 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11920 // load FSR0 from immediate
11921 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11925 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11927 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11933 else { /* we need to get it byte by byte */
11934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11935 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11937 // set up FSR0 with address of result
11938 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11939 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11941 /* hack hack! see if this the FSR. If so don't load W */
11942 if(AOP_TYPE(right) != AOP_ACC) {
11944 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11946 if(AOP_TYPE(right) == AOP_LIT)
11949 // note: pic16_popGet handles sign extension
11950 for(i=0;i<size;i++) {
11951 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11953 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11955 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11960 for(i=0;i<size;i++) {
11962 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11963 pic16_popCopyReg(&pic16_pc_postinc0)));
11965 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11966 pic16_popCopyReg(&pic16_pc_indf0)));
11972 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11973 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11975 } // if (AOP_TYPE(result) != AOP_IMMD)
11977 } // if (AOP_TYPE(result) != AOP_STR)
11978 /* so dptr know contains the address */
11981 /* if bit then unpack */
11982 if (IS_BITFIELD(retype))
11983 genPackBits(retype,result,right,"dptr",GPOINTER);
11985 size = AOP_SIZE(right);
11988 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11990 // set up FSR0 with address of result
11991 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11992 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11995 if (AOP_TYPE(right) == AOP_LIT) {
11996 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11998 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12000 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12002 } else { // no literal
12004 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12014 pic16_freeAsmop(right,NULL,ic,TRUE);
12015 pic16_freeAsmop(result,NULL,ic,TRUE);
12019 static void genGenPointerSet (operand *right,
12020 operand *result, iCode *ic)
12023 sym_link *retype = getSpec(operandType(result));
12025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12027 pic16_aopOp(result,ic,FALSE);
12028 pic16_aopOp(right,ic,FALSE);
12029 size = AOP_SIZE(right);
12031 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12034 /* if bit then unpack */
12035 if (IS_BITFIELD(retype)) {
12036 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12037 genPackBits(retype,result,right,"dptr",GPOINTER);
12041 size = AOP_SIZE(right);
12043 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12046 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12048 /* value of right+0 is placed on stack, which will be retrieved
12049 * by the support function thus restoring the stack. The important
12050 * thing is that there is no need to manually restore stack pointer
12052 pushaop(AOP(right), 0);
12053 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12054 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12055 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12056 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12058 /* load address to write to in WREG:FSR0H:FSR0L */
12059 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12060 pic16_popCopyReg(&pic16_pc_fsr0l)));
12061 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12062 pic16_popCopyReg(&pic16_pc_prodl)));
12063 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12065 pic16_callGenericPointerRW(1, size);
12068 pic16_freeAsmop(right,NULL,ic,TRUE);
12069 pic16_freeAsmop(result,NULL,ic,TRUE);
12072 /*-----------------------------------------------------------------*/
12073 /* genPointerSet - stores the value into a pointer location */
12074 /*-----------------------------------------------------------------*/
12075 static void genPointerSet (iCode *ic)
12077 operand *right, *result ;
12078 sym_link *type, *etype;
12083 right = IC_RIGHT(ic);
12084 result = IC_RESULT(ic) ;
12086 /* depending on the type of pointer we need to
12087 move it to the correct pointer register */
12088 type = operandType(result);
12089 etype = getSpec(type);
12091 /* if left is of type of pointer then it is simple */
12092 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12093 p_type = DCL_TYPE(type);
12096 /* we have to go by the storage class */
12097 p_type = PTR_TYPE(SPEC_OCLS(etype));
12099 /* if (SPEC_OCLS(etype)->codesp ) { */
12100 /* p_type = CPOINTER ; */
12103 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12104 /* p_type = FPOINTER ; */
12106 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12107 /* p_type = PPOINTER ; */
12109 /* if (SPEC_OCLS(etype) == idata ) */
12110 /* p_type = IPOINTER ; */
12112 /* p_type = POINTER ; */
12115 /* now that we have the pointer type we assign
12116 the pointer values */
12121 genNearPointerSet (right,result,ic);
12125 genPagedPointerSet (right,result,ic);
12129 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12131 genFarPointerSet (right,result,ic);
12136 genGenPointerSet (right,result,ic);
12140 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12141 "genPointerSet: illegal pointer type");
12145 /*-----------------------------------------------------------------*/
12146 /* genIfx - generate code for Ifx statement */
12147 /*-----------------------------------------------------------------*/
12148 static void genIfx (iCode *ic, iCode *popIc)
12150 operand *cond = IC_COND(ic);
12155 pic16_aopOp(cond,ic,FALSE);
12157 /* get the value into acc */
12158 if (AOP_TYPE(cond) != AOP_CRY)
12159 pic16_toBoolean(cond);
12162 /* the result is now in the accumulator */
12163 pic16_freeAsmop(cond,NULL,ic,TRUE);
12165 /* if there was something to be popped then do it */
12169 /* if the condition is a bit variable */
12170 if (isbit && IS_ITEMP(cond) &&
12172 genIfxJump(ic,"c");
12173 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12175 if (isbit && !IS_ITEMP(cond))
12176 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12178 genIfxJump(ic,"a");
12183 /*-----------------------------------------------------------------*/
12184 /* genAddrOf - generates code for address of */
12185 /*-----------------------------------------------------------------*/
12186 static void genAddrOf (iCode *ic)
12188 operand *result, *left;
12190 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12191 pCodeOp *pcop0, *pcop1, *pcop2;
12195 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12197 sym = OP_SYMBOL( IC_LEFT(ic) );
12200 /* get address of symbol on stack */
12201 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12203 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12204 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12207 // operands on stack are accessible via "FSR2 + index" with index
12208 // starting at 2 for arguments and growing from 0 downwards for
12209 // local variables (index == 0 is not assigned so we add one here)
12211 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12214 assert (soffs < 0);
12218 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12219 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12220 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12221 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12222 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12223 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12224 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12230 // if(pic16_debug_verbose) {
12231 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12232 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12235 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12236 size = AOP_SIZE(IC_RESULT(ic));
12238 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12239 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12240 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12243 pic16_emitpcode(POC_MOVLW, pcop0);
12244 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12245 pic16_emitpcode(POC_MOVLW, pcop1);
12246 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12247 pic16_emitpcode(POC_MOVLW, pcop2);
12248 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12251 pic16_emitpcode(POC_MOVLW, pcop0);
12252 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12253 pic16_emitpcode(POC_MOVLW, pcop1);
12254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12256 pic16_emitpcode(POC_MOVLW, pcop0);
12257 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12260 pic16_freeAsmop(left, NULL, ic, FALSE);
12262 pic16_freeAsmop(result,NULL,ic,TRUE);
12267 /*-----------------------------------------------------------------*/
12268 /* genFarFarAssign - assignment when both are in far space */
12269 /*-----------------------------------------------------------------*/
12270 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12272 int size = AOP_SIZE(right);
12275 /* first push the right side on to the stack */
12277 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12279 pic16_emitcode ("push","acc");
12282 pic16_freeAsmop(right,NULL,ic,FALSE);
12283 /* now assign DPTR to result */
12284 pic16_aopOp(result,ic,FALSE);
12285 size = AOP_SIZE(result);
12287 pic16_emitcode ("pop","acc");
12288 pic16_aopPut(AOP(result),"a",--offset);
12290 pic16_freeAsmop(result,NULL,ic,FALSE);
12295 /*-----------------------------------------------------------------*/
12296 /* genAssign - generate code for assignment */
12297 /*-----------------------------------------------------------------*/
12298 static void genAssign (iCode *ic)
12300 operand *result, *right;
12301 sym_link *restype, *rtype;
12302 int size, offset,know_W;
12303 unsigned long lit = 0L;
12305 result = IC_RESULT(ic);
12306 right = IC_RIGHT(ic) ;
12310 /* if they are the same */
12311 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12314 /* reversed order operands are aopOp'ed so that result operand
12315 * is effective in case right is a stack symbol. This maneauver
12316 * allows to use the _G.resDirect flag later */
12317 pic16_aopOp(result,ic,TRUE);
12318 pic16_aopOp(right,ic,FALSE);
12320 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12322 /* if they are the same registers */
12323 if (pic16_sameRegs(AOP(right),AOP(result)))
12326 /* if the result is a bit */
12327 if (AOP_TYPE(result) == AOP_CRY) {
12328 /* if the right size is a literal then
12329 we know what the value is */
12330 if (AOP_TYPE(right) == AOP_LIT) {
12332 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12333 pic16_popGet(AOP(result),0));
12335 if (((int) operandLitValue(right)))
12336 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12337 AOP(result)->aopu.aop_dir,
12338 AOP(result)->aopu.aop_dir);
12340 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12341 AOP(result)->aopu.aop_dir,
12342 AOP(result)->aopu.aop_dir);
12347 /* the right is also a bit variable */
12348 if (AOP_TYPE(right) == AOP_CRY) {
12349 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12350 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12351 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12356 /* we need to or */
12357 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12358 pic16_toBoolean(right);
12360 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12361 //pic16_aopPut(AOP(result),"a",0);
12365 /* bit variables done */
12367 size = AOP_SIZE(result);
12370 /* bit variables done */
12372 size = AOP_SIZE(result);
12373 restype = operandType(result);
12374 rtype = operandType(right);
12377 if(AOP_TYPE(right) == AOP_LIT) {
12378 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12380 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12382 /* patch tag for literals that are cast to pointers */
12383 if (IS_CODEPTR(restype)) {
12384 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12385 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12387 if (IS_GENPTR(restype))
12389 if (IS_CODEPTR(rtype)) {
12390 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12391 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12392 } else if (PIC_IS_DATA_PTR(rtype)) {
12393 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12394 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12395 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12396 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12397 } else if (IS_PTR(rtype)) {
12398 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12399 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12405 unsigned long lit_int;
12410 if(IS_FIXED16X16(operandType(right))) {
12411 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12413 /* take care if literal is a float */
12414 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12415 lit = info.lit_int;
12420 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12421 // sizeof(unsigned long int), sizeof(float));
12424 if (AOP_TYPE(right) == AOP_REG) {
12425 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12427 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12432 /* when do we have to read the program memory?
12433 * - if right itself is a symbol in code space
12434 * (we don't care what it points to if it's a pointer)
12435 * - AND right is not a function (we would want its address)
12437 if(AOP_TYPE(right) != AOP_LIT
12438 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12439 && !IS_FUNC(OP_SYM_TYPE(right))
12440 && !IS_ITEMP(right)) {
12442 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12443 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12445 // set up table pointer
12446 if(is_LitOp(right)) {
12447 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12448 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12449 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12450 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12451 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12452 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12453 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12455 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12456 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12457 pic16_popCopyReg(&pic16_pc_tblptrl)));
12458 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12459 pic16_popCopyReg(&pic16_pc_tblptrh)));
12460 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12461 pic16_popCopyReg(&pic16_pc_tblptru)));
12464 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12465 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12467 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12469 pic16_popGet(AOP(result),offset)));
12473 /* FIXME: for pointers we need to extend differently (according
12474 * to pointer type DATA/CODE/EEPROM/... :*/
12475 size = getSize(OP_SYM_TYPE(right));
12476 if(AOP_SIZE(result) > size) {
12477 size = AOP_SIZE(result) - size;
12479 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12487 /* VR - What is this?! */
12488 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12491 if(aopIdx(AOP(result),0) == 4) {
12492 /* this is a workaround to save value of right into wreg too,
12493 * value of wreg is going to be used later */
12494 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12495 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12496 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12500 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12506 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12507 if(AOP_TYPE(right) == AOP_LIT) {
12509 if(know_W != (lit&0xff))
12510 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12512 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12514 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12518 } else if (AOP_TYPE(right) == AOP_CRY) {
12519 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12521 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12522 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12523 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12525 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12526 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12531 if(!_G.resDirect) { /* use this aopForSym feature */
12532 if(AOP_TYPE(result) == AOP_ACC) {
12533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12535 if(AOP_TYPE(right) == AOP_ACC) {
12536 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12538 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12547 pic16_freeAsmop (right,NULL,ic,FALSE);
12548 pic16_freeAsmop (result,NULL,ic,TRUE);
12551 /*-----------------------------------------------------------------*/
12552 /* genJumpTab - generates code for jump table */
12553 /*-----------------------------------------------------------------*/
12554 static void genJumpTab (iCode *ic)
12559 pCodeOp *jt_offs_hi;
12564 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12565 /* get the condition into accumulator */
12566 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12568 /* multiply by three */
12569 pic16_emitcode("add","a,acc");
12570 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12572 jtab = newiTempLabel(NULL);
12573 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12574 pic16_emitcode("jmp","@a+dptr");
12575 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12578 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12579 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12581 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12582 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12583 pic16_emitpLabel(jtab->key);
12587 jt_offs = pic16_popGetTempReg(0);
12588 jt_offs_hi = pic16_popGetTempReg(1);
12589 jt_label = pic16_popGetLabel (jtab->key);
12590 //fprintf (stderr, "Creating jump table...\n");
12592 // calculate offset into jump table (idx * sizeof (GOTO))
12593 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12594 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12595 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12596 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12597 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12598 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12599 pic16_emitpcode(POC_MOVWF , jt_offs);
12601 // prepare PCLATx (set to first entry in jump table)
12602 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12603 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12604 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12605 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12606 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12608 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12609 pic16_emitpcode(POC_ADDWF , jt_offs);
12610 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12611 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12613 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12615 // release temporaries and prepare jump into table (new PCL --> WREG)
12616 pic16_emitpcode(POC_MOVFW , jt_offs);
12617 pic16_popReleaseTempReg (jt_offs_hi, 1);
12618 pic16_popReleaseTempReg (jt_offs, 0);
12620 // jump into the table
12621 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12623 pic16_emitpLabelFORCE(jtab->key);
12626 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12627 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12629 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12630 /* now generate the jump labels */
12631 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12632 jtab = setNextItem(IC_JTLABELS(ic))) {
12633 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12634 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12637 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12641 /*-----------------------------------------------------------------*/
12642 /* genMixedOperation - gen code for operators between mixed types */
12643 /*-----------------------------------------------------------------*/
12645 TSD - Written for the PIC port - but this unfortunately is buggy.
12646 This routine is good in that it is able to efficiently promote
12647 types to different (larger) sizes. Unfortunately, the temporary
12648 variables that are optimized out by this routine are sometimes
12649 used in other places. So until I know how to really parse the
12650 iCode tree, I'm going to not be using this routine :(.
12652 static int genMixedOperation (iCode *ic)
12655 operand *result = IC_RESULT(ic);
12656 sym_link *ctype = operandType(IC_LEFT(ic));
12657 operand *right = IC_RIGHT(ic);
12663 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12665 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12671 nextright = IC_RIGHT(nextic);
12672 nextleft = IC_LEFT(nextic);
12673 nextresult = IC_RESULT(nextic);
12675 pic16_aopOp(right,ic,FALSE);
12676 pic16_aopOp(result,ic,FALSE);
12677 pic16_aopOp(nextright, nextic, FALSE);
12678 pic16_aopOp(nextleft, nextic, FALSE);
12679 pic16_aopOp(nextresult, nextic, FALSE);
12681 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12683 operand *t = right;
12687 pic16_emitcode(";remove right +","");
12689 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12691 operand *t = right;
12695 pic16_emitcode(";remove left +","");
12699 big = AOP_SIZE(nextleft);
12700 small = AOP_SIZE(nextright);
12702 switch(nextic->op) {
12705 pic16_emitcode(";optimize a +","");
12706 /* if unsigned or not an integral type */
12707 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12708 pic16_emitcode(";add a bit to something","");
12711 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12713 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12714 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12715 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12717 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12725 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12726 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12727 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12730 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12732 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12733 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12734 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12735 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12736 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12739 pic16_emitcode("rlf","known_zero,w");
12746 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12747 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12748 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12750 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12760 pic16_freeAsmop(right,NULL,ic,TRUE);
12761 pic16_freeAsmop(result,NULL,ic,TRUE);
12762 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12763 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12765 nextic->generated = 1;
12772 /*-----------------------------------------------------------------*/
12773 /* genCast - gen code for casting */
12774 /*-----------------------------------------------------------------*/
12775 static void genCast (iCode *ic)
12777 operand *result = IC_RESULT(ic);
12778 sym_link *ctype = operandType(IC_LEFT(ic));
12779 sym_link *rtype = operandType(IC_RIGHT(ic));
12780 sym_link *restype = operandType(IC_RESULT(ic));
12781 operand *right = IC_RIGHT(ic);
12787 /* if they are equivalent then do nothing */
12788 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12791 pic16_aopOp(result,ic,FALSE);
12792 pic16_aopOp(right,ic,FALSE) ;
12794 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12797 /* if the result is a bit */
12798 if (AOP_TYPE(result) == AOP_CRY) {
12800 /* if the right size is a literal then
12801 * we know what the value is */
12802 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12804 if (AOP_TYPE(right) == AOP_LIT) {
12805 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12806 pic16_popGet(AOP(result),0));
12808 if (((int) operandLitValue(right)))
12809 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12810 AOP(result)->aopu.aop_dir,
12811 AOP(result)->aopu.aop_dir);
12813 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12814 AOP(result)->aopu.aop_dir,
12815 AOP(result)->aopu.aop_dir);
12819 /* the right is also a bit variable */
12820 if (AOP_TYPE(right) == AOP_CRY) {
12822 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12824 pic16_emitcode("clrc","");
12825 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12826 AOP(right)->aopu.aop_dir,
12827 AOP(right)->aopu.aop_dir);
12828 pic16_aopPut(AOP(result),"c",0);
12832 /* we need to or */
12833 if (AOP_TYPE(right) == AOP_REG) {
12834 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12835 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12836 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12838 pic16_toBoolean(right);
12839 pic16_aopPut(AOP(result),"a",0);
12843 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12846 size = AOP_SIZE(result);
12848 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12850 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12851 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12852 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12855 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12860 if(IS_BITFIELD(getSpec(restype))
12861 && IS_BITFIELD(getSpec(rtype))) {
12862 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12865 /* port from pic14 to cope with generic pointers */
12866 if (PIC_IS_TAGGED(restype))
12868 operand *result = IC_RESULT(ic);
12869 //operand *left = IC_LEFT(ic);
12870 operand *right = IC_RIGHT(ic);
12873 /* copy common part */
12874 int max, size = AOP_SIZE(result);
12875 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12876 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12881 pic16_mov2w (AOP(right), size);
12882 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12885 /* upcast into generic pointer type? */
12886 if (IS_GENPTR(restype)
12887 && !PIC_IS_TAGGED(rtype)
12888 && (AOP_SIZE(result) > max))
12890 /* determine appropriate tag for right */
12891 if (PIC_IS_DATA_PTR(rtype))
12892 tag = GPTR_TAG_DATA;
12893 else if (IS_CODEPTR(rtype))
12894 tag = GPTR_TAG_CODE;
12895 else if (PIC_IS_DATA_PTR(ctype)) {
12896 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12897 tag = GPTR_TAG_DATA;
12898 } else if (IS_CODEPTR(ctype)) {
12899 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12900 tag = GPTR_TAG_CODE;
12901 } else if (IS_PTR(rtype)) {
12902 PERFORM_ONCE(weirdcast,
12903 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12905 tag = GPTR_TAG_DATA;
12907 PERFORM_ONCE(weirdcast,
12908 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12910 tag = GPTR_TAG_DATA;
12913 assert (AOP_SIZE(result) == 3);
12914 /* zero-extend address... */
12915 for (size = max; size < AOP_SIZE(result)-1; size++)
12916 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12917 /* ...and add tag */
12918 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12919 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12920 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12921 for (size = max; size < AOP_SIZE(result)-1; size++)
12922 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12923 /* add __code tag */
12924 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12925 } else if (AOP_SIZE(result) > max) {
12926 /* extend non-pointers */
12927 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12928 pic16_addSign(result, max, 0);
12933 /* if they are the same size : or less */
12934 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12936 /* if they are in the same place */
12937 if (pic16_sameRegs(AOP(right),AOP(result)))
12940 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12942 if (IS_PTR_CONST(rtype))
12944 if (IS_CODEPTR(rtype))
12946 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12949 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12951 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12953 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12956 if(AOP_TYPE(right) == AOP_IMMD) {
12957 pCodeOp *pcop0, *pcop1, *pcop2;
12958 symbol *sym = OP_SYMBOL( right );
12960 size = AOP_SIZE(result);
12962 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12964 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12966 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12969 pic16_emitpcode(POC_MOVLW, pcop0);
12970 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12971 pic16_emitpcode(POC_MOVLW, pcop1);
12972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12973 pic16_emitpcode(POC_MOVLW, pcop2);
12974 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12977 pic16_emitpcode(POC_MOVLW, pcop0);
12978 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12979 pic16_emitpcode(POC_MOVLW, pcop1);
12980 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12982 pic16_emitpcode(POC_MOVLW, pcop0);
12983 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12987 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12988 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12990 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12992 if(AOP_SIZE(result) <2)
12993 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12995 /* if they in different places then copy */
12996 size = AOP_SIZE(result);
12999 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13007 /* if the result is of type pointer */
13008 if (IS_PTR(ctype)) {
13010 sym_link *type = operandType(right);
13011 sym_link *etype = getSpec(type);
13013 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13015 /* pointer to generic pointer */
13016 if (IS_GENPTR(ctype)) {
13020 p_type = DCL_TYPE(type);
13022 /* we have to go by the storage class */
13023 p_type = PTR_TYPE(SPEC_OCLS(etype));
13025 /* if (SPEC_OCLS(etype)->codesp ) */
13026 /* p_type = CPOINTER ; */
13028 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13029 /* p_type = FPOINTER ; */
13031 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13032 /* p_type = PPOINTER; */
13034 /* if (SPEC_OCLS(etype) == idata ) */
13035 /* p_type = IPOINTER ; */
13037 /* p_type = POINTER ; */
13040 /* the first two bytes are known */
13041 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13042 size = GPTRSIZE - 1;
13045 if(offset < AOP_SIZE(right)) {
13046 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13047 pic16_mov2f(AOP(result), AOP(right), offset);
13049 if ((AOP_TYPE(right) == AOP_PCODE) &&
13050 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13051 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13055 pic16_aopPut(AOP(result),
13056 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13061 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13064 /* the last byte depending on type */
13069 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13073 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13077 pic16_emitcode(";BUG!? ","%d",__LINE__);
13082 if (GPTRSIZE > AOP_SIZE(right)) {
13083 // assume __data pointer... THIS MIGHT BE WRONG!
13084 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13086 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13091 /* this should never happen */
13092 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13093 "got unknown pointer type");
13096 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13102 /* just copy the pointers */
13103 size = AOP_SIZE(result);
13106 pic16_aopPut(AOP(result),
13107 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13116 /* so we now know that the size of destination is greater
13117 than the size of the source.
13118 Now, if the next iCode is an operator then we might be
13119 able to optimize the operation without performing a cast.
13121 if(genMixedOperation(ic))
13124 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13126 /* we move to result for the size of source */
13127 size = AOP_SIZE(right);
13132 pic16_mov2f(AOP(result), AOP(right), offset);
13136 /* now depending on the sign of the destination */
13137 size = AOP_SIZE(result) - AOP_SIZE(right);
13138 /* if unsigned or not an integral type */
13139 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13141 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13143 /* we need to extend the sign :( */
13146 /* Save one instruction of casting char to int */
13147 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13148 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13149 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13151 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13154 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13156 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13158 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13161 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13166 pic16_freeAsmop(right,NULL,ic,TRUE);
13167 pic16_freeAsmop(result,NULL,ic,TRUE);
13171 /*-----------------------------------------------------------------*/
13172 /* genDjnz - generate decrement & jump if not zero instrucion */
13173 /*-----------------------------------------------------------------*/
13174 static int genDjnz (iCode *ic, iCode *ifx)
13176 symbol *lbl, *lbl1;
13177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13182 /* if the if condition has a false label
13183 then we cannot save */
13187 /* if the minus is not of the form
13189 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13190 !IS_OP_LITERAL(IC_RIGHT(ic)))
13193 if (operandLitValue(IC_RIGHT(ic)) != 1)
13196 /* if the size of this greater than one then no
13198 if (getSize(operandType(IC_RESULT(ic))) > 1)
13201 /* otherwise we can save BIG */
13202 lbl = newiTempLabel(NULL);
13203 lbl1= newiTempLabel(NULL);
13205 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13207 if (IS_AOP_PREG(IC_RESULT(ic))) {
13208 pic16_emitcode("dec","%s",
13209 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13210 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13211 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13215 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13216 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13218 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13219 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13223 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13224 ifx->generated = 1;
13228 /*-----------------------------------------------------------------*/
13229 /* genReceive - generate code for a receive iCode */
13230 /*-----------------------------------------------------------------*/
13231 static void genReceive (iCode *ic)
13237 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13238 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13240 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13242 if (isOperandInFarSpace(IC_RESULT(ic))
13243 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13244 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13246 int size = getSize(operandType(IC_RESULT(ic)));
13247 int offset = pic16_fReturnSizePic - size;
13251 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13252 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13256 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13258 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13259 size = AOP_SIZE(IC_RESULT(ic));
13262 pic16_emitcode ("pop","acc");
13263 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13266 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13268 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13271 /* set pseudo stack pointer to where it should be - dw*/
13272 GpsuedoStkPtr = ic->parmBytes;
13274 /* setting GpsuedoStkPtr has side effects here: */
13275 assignResultValue(IC_RESULT(ic), 0);
13278 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13281 /*-----------------------------------------------------------------*/
13282 /* genDummyRead - generate code for dummy read of volatiles */
13283 /*-----------------------------------------------------------------*/
13285 genDummyRead (iCode * ic)
13291 if (op && IS_SYMOP(op)) {
13292 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13293 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13296 pic16_aopOp (op, ic, FALSE);
13297 for (i=0; i < AOP_SIZE(op); i++) {
13298 // may need to protect this from the peepholer -- this is not nice but works...
13299 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13300 pic16_mov2w (AOP(op),i);
13301 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13303 pic16_freeAsmop (op, NULL, ic, TRUE);
13305 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13309 /*-----------------------------------------------------------------*/
13310 /* genpic16Code - generate code for pic16 based controllers */
13311 /*-----------------------------------------------------------------*/
13313 * At this point, ralloc.c has gone through the iCode and attempted
13314 * to optimize in a way suitable for a PIC. Now we've got to generate
13315 * PIC instructions that correspond to the iCode.
13317 * Once the instructions are generated, we'll pass through both the
13318 * peep hole optimizer and the pCode optimizer.
13319 *-----------------------------------------------------------------*/
13321 void genpic16Code (iCode *lic)
13326 lineHead = lineCurr = NULL;
13328 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13329 pic16_addpBlock(pb);
13332 /* if debug information required */
13333 if (options.debug && currFunc) {
13335 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13340 for (ic = lic ; ic ; ic = ic->next ) {
13342 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13343 if ( cln != ic->lineno ) {
13344 if ( options.debug ) {
13345 debugFile->writeCLine (ic);
13348 if(!options.noCcodeInAsm) {
13349 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13350 printCLine(ic->filename, ic->lineno)));
13356 if(options.iCodeInAsm) {
13359 /* insert here code to print iCode as comment */
13360 l = Safe_strdup(printILine(ic));
13361 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13364 /* if the result is marked as
13365 * spilt and rematerializable or code for
13366 * this has already been generated then
13368 if (resultRemat(ic) || ic->generated )
13371 /* depending on the operation */
13390 /* IPOP happens only when trying to restore a
13391 * spilt live range, if there is an ifx statement
13392 * following this pop then the if statement might
13393 * be using some of the registers being popped which
13394 * would destroy the contents of the register so
13395 * we need to check for this condition and handle it */
13397 && ic->next->op == IFX
13398 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13399 genIfx (ic->next,ic);
13417 genEndFunction (ic);
13433 pic16_genPlus (ic) ;
13437 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13438 pic16_genMinus (ic);
13454 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13458 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13464 /* note these two are xlated by algebraic equivalence
13465 * during parsing SDCC.y */
13466 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13467 "got '>=' or '<=' shouldn't have come here");
13471 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13483 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13487 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13491 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13515 genRightShift (ic);
13518 case GET_VALUE_AT_ADDRESS:
13523 if (POINTER_SET(ic))
13550 addSet(&_G.sendSet,ic);
13553 case DUMMY_READ_VOLATILE:
13563 /* now we are ready to call the
13564 peep hole optimizer */
13565 if (!options.nopeep)
13566 peepHole (&lineHead);
13568 /* now do the actual printing */
13569 printLine (lineHead, codeOutFile);
13572 DFPRINTF((stderr,"printing pBlock\n\n"));
13573 pic16_printpBlock(stdout,pb);