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:%d: getting free ptr from ic = %c result: %d\n", __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 "FSR2 + 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 sym->aop = aop = newAsmop (AOP_DIR);
855 aop->aopu.aop_dir = sym->rname ;
856 aop->size = getSize(sym->type);
857 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
858 pic16_allocDirReg( IC_LEFT(ic) );
863 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
864 sym->aop = aop = newAsmop (AOP_DIR);
865 aop->aopu.aop_dir = sym->rname ;
866 aop->size = getSize(sym->type);
867 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
868 pic16_allocDirReg( IC_LEFT(ic) );
873 /* only remaining is far space */
874 sym->aop = aop = newAsmop(AOP_PCODE);
876 /* change the next if to 1 to revert to good old immediate code */
877 if(IN_CODESPACE(space)) {
878 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
879 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
880 PCOI(aop->aopu.pcop)->index = 0;
882 /* try to allocate via direct register */
883 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
884 // aop->size = getSize( sym->type );
887 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
888 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
891 if(!pic16_allocDirReg (IC_LEFT(ic)))
895 if(IN_DIRSPACE( space ))
897 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
898 aop->size = FPTRSIZE;
899 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
900 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
901 else if(sym->onStack) {
904 if(SPEC_SCLS(sym->etype) == S_PDATA) {
905 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
906 aop->size = FPTRSIZE;
911 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
913 /* if it is in code space */
914 if (IN_CODESPACE(space))
920 /*-----------------------------------------------------------------*/
921 /* aopForRemat - rematerialzes an object */
922 /*-----------------------------------------------------------------*/
923 static asmop *aopForRemat (operand *op) // x symbol *sym)
925 symbol *sym = OP_SYMBOL(op);
927 iCode *ic = NULL, *oldic;
928 asmop *aop = newAsmop(AOP_PCODE);
935 ic = sym->rematiCode;
937 if(IS_OP_POINTER(op)) {
938 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
944 // pic16_emitpcomment("ic: %s\n", printILine(ic));
947 val += (int) operandLitValue(IC_RIGHT(ic));
948 } else if (ic->op == '-') {
949 val -= (int) operandLitValue(IC_RIGHT(ic));
953 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
956 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
959 if(!op->isaddr)viaimmd++; else viaimmd=0;
961 /* set the following if to 1 to revert to good old immediate code */
962 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
965 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
967 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
970 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
972 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
975 PCOI(aop->aopu.pcop)->index = val;
977 aop->size = getSize( sym->type );
979 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
981 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
982 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
984 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
988 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
989 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
991 val, IS_PTR_CONST(operandType(op)));
993 val, IS_CODEPTR(operandType(op)));
996 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
998 pic16_allocDirReg (IC_LEFT(ic));
1000 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1007 static int aopIdx (asmop *aop, int offset)
1012 if(aop->type != AOP_REG)
1015 return aop->aopu.aop_reg[offset]->rIdx;
1020 /*-----------------------------------------------------------------*/
1021 /* regsInCommon - two operands have some registers in common */
1022 /*-----------------------------------------------------------------*/
1023 static bool regsInCommon (operand *op1, operand *op2)
1025 symbol *sym1, *sym2;
1028 /* if they have registers in common */
1029 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1032 sym1 = OP_SYMBOL(op1);
1033 sym2 = OP_SYMBOL(op2);
1035 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1038 for (i = 0 ; i < sym1->nRegs ; i++) {
1043 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1047 if (sym2->regs[j] == sym1->regs[i])
1055 /*-----------------------------------------------------------------*/
1056 /* operandsEqu - equivalent */
1057 /*-----------------------------------------------------------------*/
1058 static bool operandsEqu ( operand *op1, operand *op2)
1060 symbol *sym1, *sym2;
1062 /* if they not symbols */
1063 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1066 sym1 = OP_SYMBOL(op1);
1067 sym2 = OP_SYMBOL(op2);
1069 /* if both are itemps & one is spilt
1070 and the other is not then false */
1071 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1072 sym1->isspilt != sym2->isspilt )
1075 /* if they are the same */
1079 if (sym1->rname[0] && sym2->rname[0]
1080 && strcmp (sym1->rname, sym2->rname) == 0)
1084 /* if left is a tmp & right is not */
1085 if (IS_ITEMP(op1) &&
1088 (sym1->usl.spillLoc == sym2))
1091 if (IS_ITEMP(op2) &&
1095 (sym2->usl.spillLoc == sym1))
1101 /*-----------------------------------------------------------------*/
1102 /* pic16_sameRegs - two asmops have the same registers */
1103 /*-----------------------------------------------------------------*/
1104 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1111 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1112 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1114 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1116 if (aop1->type != AOP_REG ||
1117 aop2->type != AOP_REG )
1120 /* This is a bit too restrictive if one is a subset of the other...
1121 if (aop1->size != aop2->size )
1125 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1126 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1128 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1129 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1136 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1138 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1139 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1141 if(aop1 == aop2)return TRUE;
1142 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1144 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1150 /*-----------------------------------------------------------------*/
1151 /* pic16_aopOp - allocates an asmop for an operand : */
1152 /*-----------------------------------------------------------------*/
1153 void pic16_aopOp (operand *op, iCode *ic, bool result)
1162 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1164 /* if this a literal */
1165 if (IS_OP_LITERAL(op)) {
1166 op->aop = aop = newAsmop(AOP_LIT);
1167 aop->aopu.aop_lit = op->operand.valOperand;
1168 aop->size = getSize(operandType(op));
1173 sym_link *type = operandType(op);
1175 if(IS_PTR_CONST(type))
1177 if(IS_CODEPTR(type))
1179 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1182 /* if already has a asmop then continue */
1186 /* if the underlying symbol has a aop */
1187 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1188 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1189 op->aop = OP_SYMBOL(op)->aop;
1193 /* if this is a true symbol */
1194 if (IS_TRUE_SYMOP(op)) {
1195 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1196 op->aop = aopForSym(ic, op, result);
1200 /* this is a temporary : this has
1206 e) can be a return use only */
1208 sym = OP_SYMBOL(op);
1210 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1211 /* if the type is a conditional */
1212 if (sym->regType == REG_CND) {
1213 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1218 /* if it is spilt then two situations
1220 b) has a spill location */
1221 if (sym->isspilt || sym->nRegs == 0) {
1223 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1224 DEBUGpic16_emitcode(";","%d",__LINE__);
1225 /* rematerialize it NOW */
1228 sym->aop = op->aop = aop = aopForRemat (op);
1229 // aop->size = getSize(sym->type);
1230 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1237 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1238 aop->size = getSize(sym->type);
1239 for ( i = 0 ; i < 1 ; i++ ) {
1240 aop->aopu.aop_str[i] = accUse[i];
1241 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1243 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1244 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1252 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1253 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1254 //pic16_allocDirReg (IC_LEFT(ic));
1255 aop->size = getSize(sym->type);
1260 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1261 aop->size = getSize(sym->type);
1262 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1263 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1265 DEBUGpic16_emitcode(";","%d",__LINE__);
1269 /* else spill location */
1270 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1271 /* force a new aop if sizes differ */
1272 sym->usl.spillLoc->aop = NULL;
1276 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1277 __FUNCTION__,__LINE__,
1278 sym->usl.spillLoc->rname,
1279 sym->rname, sym->usl.spillLoc->offset);
1282 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1283 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1284 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1285 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1287 sym->usl.spillLoc->offset, op);
1289 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1290 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1291 assert (getSize(sym->type) <= 1);
1292 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1294 aop->size = getSize(sym->type);
1300 sym_link *type = operandType(op);
1302 if(IS_PTR_CONST(type))
1304 if(IS_CODEPTR(type))
1306 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1309 /* must be in a register */
1310 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1311 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1312 aop->size = sym->nRegs;
1313 for ( i = 0 ; i < sym->nRegs ;i++)
1314 aop->aopu.aop_reg[i] = sym->regs[i];
1317 /*-----------------------------------------------------------------*/
1318 /* pic16_freeAsmop - free up the asmop given to an operand */
1319 /*----------------------------------------------------------------*/
1320 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1337 /* depending on the asmop type only three cases need work AOP_RO
1338 , AOP_R1 && AOP_STK */
1340 switch (aop->type) {
1342 if (_G.fsr0Pushed ) {
1344 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1345 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1346 // pic16_emitcode ("pop","ar0");
1350 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1354 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1360 pic16_emitcode ("pop","ar0");
1364 bitVectUnSetBit(ic->rUsed,R0_IDX);
1370 pic16_emitcode ("pop","ar1");
1374 bitVectUnSetBit(ic->rUsed,R1_IDX);
1381 /* we must store the result on stack */
1382 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1383 // operands on stack are accessible via "FSR2 + index" with index
1384 // starting at 2 for arguments and growing from 0 downwards for
1385 // local variables (index == 0 is not assigned so we add one here)
1386 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1391 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1392 for(i=0;i<aop->size;i++) {
1393 /* initialise for stack access via frame pointer */
1394 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1396 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1399 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1403 for(i=0;i<aop->size;i++) {
1404 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1406 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1407 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1418 int stk = aop->aopu.aop_stk + aop->size;
1419 bitVectUnSetBit(ic->rUsed,R0_IDX);
1420 bitVectUnSetBit(ic->rUsed,R1_IDX);
1422 getFreePtr(ic,&aop,FALSE);
1424 if (options.stack10bit)
1426 /* I'm not sure what to do here yet... */
1429 "*** Warning: probably generating bad code for "
1430 "10 bit stack mode.\n");
1434 pic16_emitcode ("mov","a,_bp");
1435 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1436 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1438 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1442 pic16_emitcode("pop","acc");
1443 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1445 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1448 pic16_freeAsmop(op,NULL,ic,TRUE);
1450 pic16_emitcode("pop","ar0");
1455 pic16_emitcode("pop","ar1");
1465 /* all other cases just dealloc */
1469 OP_SYMBOL(op)->aop = NULL;
1470 /* if the symbol has a spill */
1472 SPIL_LOC(op)->aop = NULL;
1477 /*-----------------------------------------------------------------*/
1478 /* pic16_aopGet - for fetching value of the aop */
1479 /*-----------------------------------------------------------------*/
1480 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1485 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1487 /* offset is greater than size then zero */
1488 if (offset > (aop->size - 1) &&
1489 aop->type != AOP_LIT)
1492 /* depending on type */
1493 switch (aop->type) {
1497 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1498 rs = Safe_calloc(1, strlen(s)+1);
1503 /* if we need to increment it */
1504 while (offset > aop->coff)
1506 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1510 while (offset < aop->coff)
1512 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1518 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1519 return (dname ? "acc" : "a");
1521 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1522 rs = Safe_calloc (1, strlen (s) + 1);
1530 sprintf (s,"%s",aop->aopu.aop_immd);
1533 sprintf(s,"(%s >> %d)",
1538 aop->aopu.aop_immd);
1539 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1540 rs = Safe_calloc(1,strlen(s)+1);
1546 sprintf(s,"(%s + %d)",
1549 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1551 sprintf(s,"%s",aop->aopu.aop_dir);
1552 rs = Safe_calloc(1,strlen(s)+1);
1558 // return aop->aopu.aop_reg[offset]->dname;
1560 return aop->aopu.aop_reg[offset]->name;
1563 //pic16_emitcode(";","%d",__LINE__);
1564 return aop->aopu.aop_dir;
1567 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1568 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1570 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1571 rs = Safe_strdup("WREG");
1575 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1576 rs = Safe_calloc(1,strlen(s)+1);
1581 aop->coff = offset ;
1583 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1586 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1587 aop->type = AOP_ACC;
1588 return Safe_strdup("WREG");
1590 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1592 return aop->aopu.aop_str[offset];
1596 pCodeOp *pcop = aop->aopu.pcop;
1597 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1599 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1600 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1602 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1604 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1607 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1610 rs = Safe_calloc(1,strlen(s)+1);
1616 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1618 sprintf(s,"(%s + %d)",
1622 sprintf(s,"%s",aop->aopu.aop_dir);
1623 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1624 rs = Safe_calloc(1,strlen(s)+1);
1630 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1634 // pCodeOp *pcop = aop->aop
1639 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1640 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1641 "aopget got unsupported aop->type");
1647 /* lock has the following meaning: When allocating temporary registers
1648 * for stack variables storage, the value of the temporary register is
1649 * saved on stack. Its value is restored at the end. This procedure is
1650 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1651 * a possibility that before a call to pic16_aopOp, a temporary register
1652 * is allocated for a while and it is freed after some time, this will
1653 * mess the stack and values will not be restored properly. So use lock=1
1654 * to allocate temporary registers used internally by the programmer, and
1655 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1656 * to inform the compiler developer about a possible bug. This is an internal
1657 * feature for developing the compiler -- VR */
1659 int _TempReg_lock = 0;
1660 /*-----------------------------------------------------------------*/
1661 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1662 /*-----------------------------------------------------------------*/
1663 pCodeOp *pic16_popGetTempReg(int lock)
1668 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1670 // werror(W_POSSBUG2, __FILE__, __LINE__);
1673 _TempReg_lock += lock;
1678 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1679 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1680 PCOR(pcop)->r->wasUsed=1;
1681 PCOR(pcop)->r->isFree=0;
1683 /* push value on stack */
1684 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1694 /* is not part of f, but don't save if */
1696 /*-----------------------------------------------------------------*/
1697 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1703 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1706 // werror(W_POSSBUG2, __FILE__, __LINE__);
1709 _TempReg_lock += lock;
1714 i = bitVectFirstBit(f);
1717 /* bypass registers that are used by function */
1718 if(!bitVectBitValue(f, i)) {
1720 /* bypass registers that are already allocated for stack access */
1721 if(!bitVectBitValue(v, i)) {
1723 // debugf("getting register rIdx = %d\n", i);
1724 /* ok, get the operand */
1725 pcop = pic16_newpCodeOpReg( i );
1727 /* should never by NULL */
1728 assert( pcop != NULL );
1732 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1735 PCOR(pcop)->r->wasUsed=1;
1736 PCOR(pcop)->r->isFree=0;
1742 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1744 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1745 /* already used in previous steps, break */
1752 /* caller takes care of the following */
1753 // bitVectSetBit(v, i);
1756 /* push value on stack */
1757 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1758 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1776 /*-----------------------------------------------------------------*/
1777 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1779 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1781 _TempReg_lock -= lock;
1783 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1784 PCOR(pcop)->r->isFree = 1;
1786 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1789 /*-----------------------------------------------------------------*/
1790 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1791 /*-----------------------------------------------------------------*/
1792 pCodeOp *pic16_popGetLabel(unsigned int key)
1795 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1800 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1803 /*-----------------------------------------------------------------*/
1804 /* pic16_popCopyReg - copy a pcode operator */
1805 /*-----------------------------------------------------------------*/
1806 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1810 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1811 memcpy (pcor, pc, sizeof (pCodeOpReg));
1812 pcor->r->wasUsed = 1;
1814 //pcor->pcop.type = pc->pcop.type;
1816 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1817 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1819 pcor->pcop.name = NULL;
1822 //pcor->rIdx = pc->rIdx;
1823 //pcor->r->wasUsed=1;
1824 //pcor->instance = pc->instance;
1826 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1831 /*-----------------------------------------------------------------*/
1832 /* pic16_popGetLit - asm operator to pcode operator conversion */
1833 /*-----------------------------------------------------------------*/
1834 pCodeOp *pic16_popGetLit(int lit)
1836 return pic16_newpCodeOpLit(lit);
1839 /*-----------------------------------------------------------------*/
1840 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1841 /*-----------------------------------------------------------------*/
1842 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1844 return pic16_newpCodeOpLit2(lit, arg2);
1848 /*-----------------------------------------------------------------*/
1849 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1850 /*-----------------------------------------------------------------*/
1851 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1853 return pic16_newpCodeOpImmd(name, offset,index, 0);
1857 /*-----------------------------------------------------------------*/
1858 /* pic16_popGet - asm operator to pcode operator conversion */
1859 /*-----------------------------------------------------------------*/
1860 pCodeOp *pic16_popGetWithString(char *str)
1866 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1870 pcop = pic16_newpCodeOp(str,PO_STR);
1875 /*-----------------------------------------------------------------*/
1876 /* pic16_popRegFromString - */
1877 /*-----------------------------------------------------------------*/
1878 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1881 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1882 pcop->type = PO_DIR;
1884 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1885 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1890 pcop->name = Safe_calloc(1,strlen(str)+1);
1891 strcpy(pcop->name,str);
1893 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1895 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1897 /* make sure that register doesn't exist,
1898 * and operand isn't NULL
1899 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1900 if((PCOR(pcop)->r == NULL)
1902 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1903 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1904 // __FUNCTION__, __LINE__, str, size, offset);
1906 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1907 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1910 PCOR(pcop)->instance = offset;
1915 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1919 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1921 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1922 PCOR(pcop)->rIdx = rIdx;
1923 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1925 PCOR(pcop)->r->isFree = 0;
1926 PCOR(pcop)->r->wasUsed = 1;
1928 pcop->type = PCOR(pcop)->r->pc_type;
1933 /*---------------------------------------------------------------------------------*/
1934 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1936 /*---------------------------------------------------------------------------------*/
1937 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1942 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1944 /* comment the following check, so errors to throw up */
1945 // if(!pcop2)return NULL;
1947 temp = pic16_popGet(aop_dst, offset);
1948 pcop2->pcop2 = temp;
1955 /*--------------------------------------------------------------------------------.-*/
1956 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1957 /* VR 030601 , adapted by Hans Dorn */
1958 /*--------------------------------------------------------------------------------.-*/
1959 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1963 pcop2 = (pCodeOpReg2 *)src;
1971 /*---------------------------------------------------------------------------------*/
1972 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1973 /* movff instruction */
1974 /*---------------------------------------------------------------------------------*/
1975 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1980 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1981 pcop2->pcop2 = pic16_popCopyReg(dst);
1983 /* the pCodeOp may be already allocated */
1984 pcop2 = (pCodeOpReg2 *)(src);
1985 pcop2->pcop2 = (pCodeOp *)(dst);
1992 /*-----------------------------------------------------------------*/
1993 /* pic16_popGet - asm operator to pcode operator conversion */
1994 /*-----------------------------------------------------------------*/
1995 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1997 //char *s = buffer ;
2002 /* offset is greater than
2005 // if (offset > (aop->size - 1) &&
2006 // aop->type != AOP_LIT)
2007 // return NULL; //zero;
2009 /* depending on type */
2010 switch (aop->type) {
2016 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2017 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2024 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2025 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2026 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2027 PCOR(pcop)->r->wasUsed = 1;
2028 PCOR(pcop)->r->isFree = 0;
2030 PCOR(pcop)->instance = offset;
2031 pcop->type = PCOR(pcop)->r->pc_type;
2035 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2036 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2039 /* pCodeOp is already allocated from aopForSym */
2040 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2041 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2047 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2049 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2051 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2053 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2054 PCOR(pcop)->rIdx = rIdx;
2055 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2056 PCOR(pcop)->r->wasUsed=1;
2057 PCOR(pcop)->r->isFree=0;
2059 PCOR(pcop)->instance = offset;
2060 pcop->type = PCOR(pcop)->r->pc_type;
2061 // rs = aop->aopu.aop_reg[offset]->name;
2062 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2066 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2067 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2073 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2074 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2078 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2079 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2085 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2086 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2088 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2090 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2091 // pcop->type = PO_GPR_REGISTER;
2092 PCOR(pcop)->rIdx = rIdx;
2093 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2094 PCOR(pcop)->r->wasUsed=1;
2095 PCOR(pcop)->r->isFree=0;
2097 PCOR(pcop)->instance = offset;
2098 pcop->type = PCOR(pcop)->r->pc_type;
2100 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2101 rs = aop->aopu.aop_reg[offset]->name;
2102 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2107 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2109 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2110 PCOR(pcop)->instance = offset;
2111 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2112 //if(PCOR(pcop)->r == NULL)
2113 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2117 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2118 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2121 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2122 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2125 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2126 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2127 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2128 pcop->type = PCOR(pcop)->r->pc_type;
2129 pcop->name = PCOR(pcop)->r->name;
2135 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2137 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2138 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2139 switch( aop->aopu.pcop->type ) {
2140 case PO_DIR: PCOR(pcop)->instance += offset; break;
2141 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2146 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2147 assert( 0 ); /* should never reach here */;
2152 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2153 "pic16_popGet got unsupported aop->type");
2156 /*-----------------------------------------------------------------*/
2157 /* pic16_aopPut - puts a string for a aop */
2158 /*-----------------------------------------------------------------*/
2159 void pic16_aopPut (asmop *aop, char *s, int offset)
2166 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2168 if (aop->size && offset > ( aop->size - 1)) {
2169 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2170 "pic16_aopPut got offset > aop->size");
2174 /* will assign value to value */
2175 /* depending on where it is ofcourse */
2176 switch (aop->type) {
2179 sprintf(d,"(%s + %d)",
2180 aop->aopu.aop_dir,offset);
2181 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2184 sprintf(d,"%s",aop->aopu.aop_dir);
2187 DEBUGpic16_emitcode(";","%d",__LINE__);
2189 pic16_emitcode("movf","%s,w",s);
2190 pic16_emitcode("movwf","%s",d);
2193 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2194 if(offset >= aop->size) {
2195 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2198 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2201 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2208 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2209 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2212 strcmp(s,"r0") == 0 ||
2213 strcmp(s,"r1") == 0 ||
2214 strcmp(s,"r2") == 0 ||
2215 strcmp(s,"r3") == 0 ||
2216 strcmp(s,"r4") == 0 ||
2217 strcmp(s,"r5") == 0 ||
2218 strcmp(s,"r6") == 0 ||
2219 strcmp(s,"r7") == 0 )
2220 pic16_emitcode("mov","%s,%s ; %d",
2221 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2225 if(strcmp(s,"W")==0 )
2226 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2228 pic16_emitcode("movwf","%s",
2229 aop->aopu.aop_reg[offset]->name);
2231 if(strcmp(s,zero)==0) {
2232 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2234 } else if(strcmp(s,"W")==0) {
2235 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2236 pcop->type = PO_GPR_REGISTER;
2238 PCOR(pcop)->rIdx = -1;
2239 PCOR(pcop)->r = NULL;
2241 DEBUGpic16_emitcode(";","%d",__LINE__);
2242 pcop->name = Safe_strdup(s);
2243 pic16_emitpcode(POC_MOVFW,pcop);
2244 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2245 } else if(strcmp(s,one)==0) {
2246 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2247 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2249 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2257 if (aop->type == AOP_DPTR2)
2263 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2264 "pic16_aopPut writting to code space");
2268 while (offset > aop->coff) {
2270 pic16_emitcode ("inc","dptr");
2273 while (offset < aop->coff) {
2275 pic16_emitcode("lcall","__decdptr");
2280 /* if not in accumulater */
2283 pic16_emitcode ("movx","@dptr,a");
2285 if (aop->type == AOP_DPTR2)
2293 while (offset > aop->coff) {
2295 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2297 while (offset < aop->coff) {
2299 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2305 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2310 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2312 if (strcmp(s,"r0") == 0 ||
2313 strcmp(s,"r1") == 0 ||
2314 strcmp(s,"r2") == 0 ||
2315 strcmp(s,"r3") == 0 ||
2316 strcmp(s,"r4") == 0 ||
2317 strcmp(s,"r5") == 0 ||
2318 strcmp(s,"r6") == 0 ||
2319 strcmp(s,"r7") == 0 ) {
2321 sprintf(buffer,"a%s",s);
2322 pic16_emitcode("mov","@%s,%s",
2323 aop->aopu.aop_ptr->name,buffer);
2325 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2330 if (strcmp(s,"a") == 0)
2331 pic16_emitcode("push","acc");
2333 pic16_emitcode("push","%s",s);
2338 /* if bit variable */
2339 if (!aop->aopu.aop_dir) {
2340 pic16_emitcode("clr","a");
2341 pic16_emitcode("rlc","a");
2344 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2347 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2350 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2352 lbl = newiTempLabel(NULL);
2354 if (strcmp(s,"a")) {
2357 pic16_emitcode("clr","c");
2358 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2359 pic16_emitcode("cpl","c");
2360 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2361 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2368 if (strcmp(aop->aopu.aop_str[offset],s))
2369 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2374 if (!offset && (strcmp(s,"acc") == 0))
2377 if (strcmp(aop->aopu.aop_str[offset],s))
2378 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2382 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2383 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2384 // "pic16_aopPut got unsupported aop->type");
2390 /*-----------------------------------------------------------------*/
2391 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2392 /*-----------------------------------------------------------------*/
2393 void pic16_mov2w (asmop *aop, int offset)
2395 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2398 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2400 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2403 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2405 if(is_LitAOp(src)) {
2406 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2407 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2409 if(pic16_sameRegsOfs(src, dst, offset))return;
2410 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2411 pic16_popGet(dst, offset)));
2415 static void pic16_movLit2f(pCodeOp *pc, int lit)
2417 if (0 == (lit & 0x00ff))
2419 pic16_emitpcode (POC_CLRF, pc);
2420 } else if (0xff == (lit & 0x00ff))
2422 pic16_emitpcode (POC_SETF, pc);
2424 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2425 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2429 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2431 if(is_LitAOp(src)) {
2432 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2433 pic16_emitpcode(POC_MOVWF, dst);
2435 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2439 void pic16_testStackOverflow(void)
2441 #define GSTACK_TEST_NAME "_gstack_test"
2443 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2448 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2449 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2450 // strcpy(sym->rname, GSTACK_TEST_NAME);
2451 checkAddSym(&externs, sym);
2456 /* push pcop into stack */
2457 void pic16_pushpCodeOp(pCodeOp *pcop)
2459 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2460 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2461 if(pic16_options.gstack)
2462 pic16_testStackOverflow();
2466 /* pop pcop from stack */
2467 void pic16_poppCodeOp(pCodeOp *pcop)
2469 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2470 if(pic16_options.gstack)
2471 pic16_testStackOverflow();
2475 /*-----------------------------------------------------------------*/
2476 /* pushw - pushes wreg to stack */
2477 /*-----------------------------------------------------------------*/
2480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2481 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2482 if(pic16_options.gstack)
2483 pic16_testStackOverflow();
2487 /*-----------------------------------------------------------------*/
2488 /* pushaop - pushes aop to stack */
2489 /*-----------------------------------------------------------------*/
2490 void pushaop(asmop *aop, int offset)
2492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2494 if(is_LitAOp(aop)) {
2495 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2496 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2498 pic16_emitpcode(POC_MOVFF,
2499 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2502 if(pic16_options.gstack)
2503 pic16_testStackOverflow();
2506 /*-----------------------------------------------------------------*/
2507 /* popaop - pops aop from stack */
2508 /*-----------------------------------------------------------------*/
2509 void popaop(asmop *aop, int offset)
2511 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2512 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2513 if(pic16_options.gstack)
2514 pic16_testStackOverflow();
2517 void popaopidx(asmop *aop, int offset, int index)
2521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2523 if(STACK_MODEL_LARGE)ofs++;
2525 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2526 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2527 if(pic16_options.gstack)
2528 pic16_testStackOverflow();
2531 #if !(USE_GENERIC_SIGNED_SHIFT)
2532 /*-----------------------------------------------------------------*/
2533 /* reAdjustPreg - points a register back to where it should */
2534 /*-----------------------------------------------------------------*/
2535 static void reAdjustPreg (asmop *aop)
2539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2541 if ((size = aop->size) <= 1)
2544 switch (aop->type) {
2548 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2552 if (aop->type == AOP_DPTR2)
2558 pic16_emitcode("lcall","__decdptr");
2561 if (aop->type == AOP_DPTR2)
2573 /*-----------------------------------------------------------------*/
2574 /* opIsGptr: returns non-zero if the passed operand is */
2575 /* a generic pointer type. */
2576 /*-----------------------------------------------------------------*/
2577 static int opIsGptr(operand *op)
2579 sym_link *type = operandType(op);
2581 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2582 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2590 /*-----------------------------------------------------------------*/
2591 /* pic16_getDataSize - get the operand data size */
2592 /*-----------------------------------------------------------------*/
2593 int pic16_getDataSize(operand *op)
2595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2598 return AOP_SIZE(op);
2600 // tsd- in the pic port, the genptr size is 1, so this code here
2601 // fails. ( in the 8051 port, the size was 4).
2604 size = AOP_SIZE(op);
2605 if (size == GPTRSIZE)
2607 sym_link *type = operandType(op);
2608 if (IS_GENPTR(type))
2610 /* generic pointer; arithmetic operations
2611 * should ignore the high byte (pointer type).
2614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2621 /*-----------------------------------------------------------------*/
2622 /* pic16_outAcc - output Acc */
2623 /*-----------------------------------------------------------------*/
2624 void pic16_outAcc(operand *result)
2627 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2628 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2631 size = pic16_getDataSize(result);
2633 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2636 /* unsigned or positive */
2638 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2643 /*-----------------------------------------------------------------*/
2644 /* pic16_outBitC - output a bit C */
2645 /* Move to result the value of Carry flag -- VR */
2646 /*-----------------------------------------------------------------*/
2647 void pic16_outBitC(operand *result)
2651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2653 /* if the result is bit */
2654 if (AOP_TYPE(result) == AOP_CRY) {
2655 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2656 pic16_aopPut(AOP(result),"c",0);
2659 i = AOP_SIZE(result);
2661 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2667 /*-----------------------------------------------------------------*/
2668 /* pic16_outBitOp - output a bit from Op */
2669 /* Move to result the value of set/clr op -- VR */
2670 /*-----------------------------------------------------------------*/
2671 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2677 /* if the result is bit */
2678 if (AOP_TYPE(result) == AOP_CRY) {
2679 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2680 pic16_aopPut(AOP(result),"c",0);
2683 i = AOP_SIZE(result);
2685 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2687 pic16_emitpcode(POC_RRCF, pcop);
2688 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2692 /*-----------------------------------------------------------------*/
2693 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2694 /*-----------------------------------------------------------------*/
2695 void pic16_toBoolean(operand *oper)
2697 int size = AOP_SIZE(oper) - 1;
2700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2702 if ( AOP_TYPE(oper) != AOP_ACC) {
2703 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2706 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2710 /*-----------------------------------------------------------------*/
2711 /* genUminusFloat - unary minus for floating points */
2712 /*-----------------------------------------------------------------*/
2713 static void genUminusFloat(operand *op,operand *result)
2715 int size ,offset =0 ;
2718 /* for this we just need to flip the
2719 first it then copy the rest in place */
2720 size = AOP_SIZE(op);
2721 assert( size == AOP_SIZE(result) );
2724 pic16_mov2f(AOP(result), AOP(op), offset);
2728 /* toggle the MSB's highest bit */
2729 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2732 /*-----------------------------------------------------------------*/
2733 /* genUminus - unary minus code generation */
2734 /*-----------------------------------------------------------------*/
2735 static void genUminus (iCode *ic)
2738 sym_link *optype, *rtype;
2745 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2746 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2748 /* if both in bit space then special case */
2749 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2750 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2752 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2753 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2754 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2758 optype = operandType(IC_LEFT(ic));
2759 rtype = operandType(IC_RESULT(ic));
2762 /* if float then do float stuff */
2763 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2764 if(IS_FIXED(optype))
2765 debugf("implement fixed16x16 type\n", 0);
2767 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2771 /* otherwise subtract from zero by taking the 2's complement */
2772 size = AOP_SIZE(IC_LEFT(ic));
2773 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2774 label = newiTempLabel ( NULL );
2776 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2777 for (i=size-1; i > 0; i--) {
2778 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2780 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2781 for (i=1; i < size; i++) {
2782 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2783 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2786 for (i=size-1; i >= 0; i--) {
2787 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2788 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2791 for (i=0; i < size-2; i++) {
2792 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2793 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2795 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2797 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2800 pic16_emitpLabel (label->key);
2803 /* release the aops */
2804 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2805 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2809 /*-----------------------------------------------------------------*/
2810 /* saveRegisters - will look for a call and save the registers */
2811 /*-----------------------------------------------------------------*/
2812 static void saveRegisters(iCode *lic)
2819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2821 for (ic = lic ; ic ; ic = ic->next)
2822 if (ic->op == CALL || ic->op == PCALL)
2826 fprintf(stderr,"found parameter push with no function call\n");
2830 /* if the registers have been saved already then
2832 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2835 /* find the registers in use at this time
2836 and push them away to safety */
2837 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2841 if (options.useXstack) {
2842 if (bitVectBitValue(rsave,R0_IDX))
2843 pic16_emitcode("mov","b,r0");
2844 pic16_emitcode("mov","r0,%s",spname);
2845 for (i = 0 ; i < pic16_nRegs ; i++) {
2846 if (bitVectBitValue(rsave,i)) {
2848 pic16_emitcode("mov","a,b");
2850 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2851 pic16_emitcode("movx","@r0,a");
2852 pic16_emitcode("inc","r0");
2855 pic16_emitcode("mov","%s,r0",spname);
2856 if (bitVectBitValue(rsave,R0_IDX))
2857 pic16_emitcode("mov","r0,b");
2859 //for (i = 0 ; i < pic16_nRegs ; i++) {
2860 // if (bitVectBitValue(rsave,i))
2861 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2864 dtype = operandType(IC_LEFT(ic));
2865 if (currFunc && dtype &&
2866 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2867 IFFUNC_ISISR(currFunc->type) &&
2870 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2873 /*-----------------------------------------------------------------*/
2874 /* unsaveRegisters - pop the pushed registers */
2875 /*-----------------------------------------------------------------*/
2876 static void unsaveRegisters (iCode *ic)
2881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2882 /* find the registers in use at this time
2883 and push them away to safety */
2884 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2887 if (options.useXstack) {
2888 pic16_emitcode("mov","r0,%s",spname);
2889 for (i = pic16_nRegs ; i >= 0 ; i--) {
2890 if (bitVectBitValue(rsave,i)) {
2891 pic16_emitcode("dec","r0");
2892 pic16_emitcode("movx","a,@r0");
2894 pic16_emitcode("mov","b,a");
2896 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2900 pic16_emitcode("mov","%s,r0",spname);
2901 if (bitVectBitValue(rsave,R0_IDX))
2902 pic16_emitcode("mov","r0,b");
2904 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2905 // if (bitVectBitValue(rsave,i))
2906 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2913 /*-----------------------------------------------------------------*/
2915 /*-----------------------------------------------------------------*/
2916 static void pushSide(operand * oper, int size)
2919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2921 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2922 if (AOP_TYPE(oper) != AOP_REG &&
2923 AOP_TYPE(oper) != AOP_DIR &&
2925 pic16_emitcode("mov","a,%s",l);
2926 pic16_emitcode("push","acc");
2928 pic16_emitcode("push","%s",l);
2933 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2935 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2936 pic16_emitpcode(POC_MOVFW, src);
2937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2939 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2940 src, pic16_popGet(AOP(op), offset)));
2945 /*-----------------------------------------------------------------*/
2946 /* assignResultValue - assign results to oper, rescall==1 is */
2947 /* called from genCall() or genPcall() */
2948 /*-----------------------------------------------------------------*/
2949 static void assignResultValue(operand * oper, int rescall)
2951 int size = AOP_SIZE(oper);
2955 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2956 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2959 /* assign result from a call/pcall function() */
2961 /* function results are stored in a special order,
2962 * see top of file with Function return policy, or manual */
2965 /* 8-bits, result in WREG */
2966 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2969 /* 16-bits, result in PRODL:WREG */
2970 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2974 /* 24-bits, result in PRODH:PRODL:WREG */
2975 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2979 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2980 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2984 /* >32-bits, result on stack, and FSR0 points to beginning.
2985 * Fix stack when done */
2987 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2989 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2990 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2992 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2997 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2998 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2999 if(STACK_MODEL_LARGE) {
3001 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3005 int areg = 0; /* matching argument register */
3007 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3008 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3011 /* its called from genReceive (probably) -- VR */
3012 /* I hope this code will not be called from somewhere else in the future!
3013 * We manually set the pseudo stack pointer in genReceive. - dw
3015 if(!GpsuedoStkPtr && _G.useWreg) {
3016 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3018 /* The last byte in the assignment is in W */
3019 if(areg <= GpsuedoStkPtr) {
3021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3023 // debugf("receive from WREG\n", 0);
3025 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3028 _G.stack_lat = AOP_SIZE(oper)-1;
3033 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3034 // debugf("receive from STACK\n", 0);
3041 /*-----------------------------------------------------------------*/
3042 /* genIpush - generate code for pushing this gets a little complex */
3043 /*-----------------------------------------------------------------*/
3044 static void genIpush (iCode *ic)
3046 // int size, offset=0;
3049 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3052 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3054 /* send to stack as normal */
3055 addSet(&_G.sendSet,ic);
3056 // addSetHead(&_G.sendSet,ic);
3057 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3062 int size, offset = 0 ;
3066 /* if this is not a parm push : ie. it is spill push
3067 and spill push is always done on the local stack */
3068 if (!ic->parmPush) {
3070 /* and the item is spilt then do nothing */
3071 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3074 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3075 size = AOP_SIZE(IC_LEFT(ic));
3076 /* push it on the stack */
3078 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3083 pic16_emitcode("push","%s",l);
3088 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3092 /*-----------------------------------------------------------------*/
3093 /* genIpop - recover the registers: can happen only for spilling */
3094 /*-----------------------------------------------------------------*/
3095 static void genIpop (iCode *ic)
3098 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3103 /* if the temp was not pushed then */
3104 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3107 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3108 size = AOP_SIZE(IC_LEFT(ic));
3111 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3114 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3119 /*-----------------------------------------------------------------*/
3120 /* unsaverbank - restores the resgister bank from stack */
3121 /*-----------------------------------------------------------------*/
3122 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3124 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3132 if (options.useXstack) {
3134 r = getFreePtr(ic,&aop,FALSE);
3137 pic16_emitcode("mov","%s,_spx",r->name);
3138 pic16_emitcode("movx","a,@%s",r->name);
3139 pic16_emitcode("mov","psw,a");
3140 pic16_emitcode("dec","%s",r->name);
3143 pic16_emitcode ("pop","psw");
3146 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3147 if (options.useXstack) {
3148 pic16_emitcode("movx","a,@%s",r->name);
3149 //pic16_emitcode("mov","(%s+%d),a",
3150 // regspic16[i].base,8*bank+regspic16[i].offset);
3151 pic16_emitcode("dec","%s",r->name);
3154 pic16_emitcode("pop",""); //"(%s+%d)",
3155 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3158 if (options.useXstack) {
3160 pic16_emitcode("mov","_spx,%s",r->name);
3161 pic16_freeAsmop(NULL,aop,ic,TRUE);
3167 /*-----------------------------------------------------------------*/
3168 /* saverbank - saves an entire register bank on the stack */
3169 /*-----------------------------------------------------------------*/
3170 static void saverbank (int bank, iCode *ic, bool pushPsw)
3172 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3179 if (options.useXstack) {
3182 r = getFreePtr(ic,&aop,FALSE);
3183 pic16_emitcode("mov","%s,_spx",r->name);
3187 for (i = 0 ; i < pic16_nRegs ;i++) {
3188 if (options.useXstack) {
3189 pic16_emitcode("inc","%s",r->name);
3190 //pic16_emitcode("mov","a,(%s+%d)",
3191 // regspic16[i].base,8*bank+regspic16[i].offset);
3192 pic16_emitcode("movx","@%s,a",r->name);
3194 pic16_emitcode("push","");// "(%s+%d)",
3195 //regspic16[i].base,8*bank+regspic16[i].offset);
3199 if (options.useXstack) {
3200 pic16_emitcode("mov","a,psw");
3201 pic16_emitcode("movx","@%s,a",r->name);
3202 pic16_emitcode("inc","%s",r->name);
3203 pic16_emitcode("mov","_spx,%s",r->name);
3204 pic16_freeAsmop (NULL,aop,ic,TRUE);
3207 pic16_emitcode("push","psw");
3209 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3217 static int wparamCmp(void *p1, void *p2)
3219 return (!strcmp((char *)p1, (char *)p2));
3222 int inWparamList(char *s)
3224 return isinSetWith(wparamList, s, wparamCmp);
3228 /*-----------------------------------------------------------------*/
3229 /* genCall - generates a call statement */
3230 /*-----------------------------------------------------------------*/
3231 static void genCall (iCode *ic)
3241 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3242 /* if caller saves & we have not saved then */
3243 // if (!ic->regsSaved)
3244 // saveRegisters(ic);
3246 /* initialise stackParms for IPUSH pushes */
3247 // stackParms = psuedoStkPtr;
3248 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3249 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3250 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3253 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3256 /* if send set is not empty the assign */
3259 int psuedoStkPtr=-1;
3260 int firstTimeThruLoop = 1;
3263 /* reverse sendSet if function is not reentrant */
3264 if(!IFFUNC_ISREENT(ftype))
3265 _G.sendSet = reverseSet(_G.sendSet);
3267 /* First figure how many parameters are getting passed */
3271 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3275 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3276 size = AOP_SIZE(IC_LEFT(sic));
3280 /* pass the last byte through WREG */
3284 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3285 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3286 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3288 if(!firstTimeThruLoop) {
3289 /* If this is not the first time we've been through the loop
3290 * then we need to save the parameter in a temporary
3291 * register. The last byte of the last parameter is
3295 // --psuedoStkPtr; // sanity check
3299 firstTimeThruLoop=0;
3301 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3306 /* all arguments are passed via stack */
3310 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3311 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3312 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3314 // pushaop(AOP(IC_LEFT(sic)), size);
3315 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3322 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3326 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3327 pushw(); /* save last parameter to stack if functions has varargs */
3331 } else use_wreg = 0;
3333 _G.stackRegSet = _G.sendSet;
3338 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3342 /* if we need to assign a result value */
3343 if ((IS_ITEMP(IC_RESULT(ic))
3344 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3345 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3346 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3349 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3352 assignResultValue(IC_RESULT(ic), 1);
3354 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3355 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3357 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3360 if(!stackParms && ic->parmBytes) {
3361 stackParms = ic->parmBytes;
3364 stackParms -= use_wreg;
3367 if(stackParms == 1) {
3368 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3371 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3373 if(STACK_MODEL_LARGE) {
3375 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3380 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3383 /* adjust the stack for parameters if required */
3384 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3387 /* if register bank was saved then pop them */
3389 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3391 /* if we hade saved some registers then unsave them */
3392 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3393 unsaveRegisters (ic);
3399 /*-----------------------------------------------------------------*/
3400 /* genPcall - generates a call by pointer statement */
3401 /* new version, created from genCall - HJD */
3402 /*-----------------------------------------------------------------*/
3403 static void genPcall (iCode *ic)
3405 sym_link *ftype, *fntype;
3407 symbol *retlbl = newiTempLabel(NULL);
3408 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3412 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3413 fntype = operandType( IC_LEFT(ic) )->next;
3415 /* if send set is not empty the assign */
3418 int psuedoStkPtr=-1;
3420 /* reverse sendSet if function is not reentrant */
3421 if(!IFFUNC_ISREENT(fntype))
3422 _G.sendSet = reverseSet(_G.sendSet);
3426 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3429 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3430 size = AOP_SIZE(IC_LEFT(sic));
3433 /* all parameters are passed via stack, since WREG is clobbered
3434 * by the calling sequence */
3436 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3437 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3438 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3440 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3444 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3447 _G.stackRegSet = _G.sendSet;
3451 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3453 // push return address
3454 // push $ on return stack, then replace with retlbl
3456 /* Thanks to Thorsten Klose for pointing out that the following
3457 * snippet should be interrupt safe */
3458 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3459 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3461 pic16_emitpcodeNULLop(POC_PUSH);
3463 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3464 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3465 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3466 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3467 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3468 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3471 /* restore interrupt control register */
3472 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3473 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3475 /* make the call by writing the pointer into pc */
3476 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3477 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3479 // note: MOVFF to PCL not allowed
3480 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3481 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3484 /* return address is here: (X) */
3485 pic16_emitpLabelFORCE(retlbl->key);
3487 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3490 /* if we need assign a result value */
3491 if ((IS_ITEMP(IC_RESULT(ic))
3492 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3493 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3494 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3497 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3500 assignResultValue(IC_RESULT(ic), 1);
3502 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3503 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3505 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3508 // stackParms -= use_wreg;
3511 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3512 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3513 if(STACK_MODEL_LARGE) {
3515 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3520 /*-----------------------------------------------------------------*/
3521 /* resultRemat - result is rematerializable */
3522 /*-----------------------------------------------------------------*/
3523 static int resultRemat (iCode *ic)
3525 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3526 if (SKIP_IC(ic) || ic->op == IFX)
3529 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3530 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3531 if (sym->remat && !POINTER_SET(ic))
3538 #if defined(__BORLANDC__) || defined(_MSC_VER)
3539 #define STRCASECMP stricmp
3541 #define STRCASECMP strcasecmp
3545 /*-----------------------------------------------------------------*/
3546 /* inExcludeList - return 1 if the string is in exclude Reg list */
3547 /*-----------------------------------------------------------------*/
3548 static bool inExcludeList(char *s)
3550 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3554 if (options.excludeRegs[i] &&
3555 STRCASECMP(options.excludeRegs[i],"none") == 0)
3558 for ( i = 0 ; options.excludeRegs[i]; i++) {
3559 if (options.excludeRegs[i] &&
3560 STRCASECMP(s,options.excludeRegs[i]) == 0)
3567 /*-----------------------------------------------------------------*/
3568 /* genFunction - generated code for function entry */
3569 /*-----------------------------------------------------------------*/
3570 static void genFunction (iCode *ic)
3576 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3578 pic16_labelOffset += (max_key+4);
3583 ftype = operandType(IC_LEFT(ic));
3584 sym = OP_SYMBOL(IC_LEFT(ic));
3586 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3587 /* create an absolute section at the interrupt vector:
3588 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3593 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3595 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3596 sprintf(asymname, "ivec_%s", sym->name);
3598 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3600 /* when an interrupt is declared as naked, do not emit the special
3601 * wrapper segment at vector address. The user should take care for
3602 * this instead. -- VR */
3604 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3605 asym = newSymbol(asymname, 0);
3606 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3607 pic16_addpBlock( apb );
3609 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3610 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3611 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3612 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3613 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3615 /* mark the end of this tiny function */
3616 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3618 sprintf(asymname, "%s", sym->rname);
3624 abSym = Safe_calloc(1, sizeof(absSym));
3625 strcpy(abSym->name, asymname);
3627 switch( FUNC_INTNO(sym->type) ) {
3628 case 0: abSym->address = 0x000000; break;
3629 case 1: abSym->address = 0x000008; break;
3630 case 2: abSym->address = 0x000018; break;
3633 // fprintf(stderr, "no interrupt number is given\n");
3634 abSym->address = -1; break;
3637 /* relocate interrupt vectors if needed */
3638 if(abSym->address != -1)
3639 abSym->address += pic16_options.ivt_loc;
3641 addSet(&absSymSet, abSym);
3645 /* create the function header */
3646 pic16_emitcode(";","-----------------------------------------");
3647 pic16_emitcode(";"," function %s",sym->name);
3648 pic16_emitcode(";","-----------------------------------------");
3650 pic16_emitcode("","%s:",sym->rname);
3651 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3656 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3657 if(!strcmp(ab->name, sym->rname)) {
3658 pic16_pBlockConvert2Absolute(pb);
3664 if(IFFUNC_ISNAKED(ftype)) {
3665 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3669 /* if critical function then turn interrupts off */
3670 if (IFFUNC_ISCRITICAL(ftype)) {
3671 //pic16_emitcode("clr","ea");
3674 currFunc = sym; /* update the currFunc symbol */
3675 _G.fregsUsed = sym->regsUsed;
3676 _G.sregsAlloc = newBitVect(128);
3679 /* if this is an interrupt service routine then
3680 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3681 if (IFFUNC_ISISR(sym->type)) {
3682 _G.usefastretfie = 1; /* use shadow registers by default */
3684 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3685 if(!FUNC_ISSHADOWREGS(sym->type)) {
3686 /* do not save WREG,STATUS,BSR for high priority interrupts
3687 * because they are stored in the hardware shadow registers already */
3688 _G.usefastretfie = 0;
3689 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3690 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3691 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3694 /* these should really be optimized somehow, because not all
3695 * interrupt handlers modify them */
3696 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3697 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3698 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3699 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3701 // pic16_pBlockConvert2ISR(pb);
3704 /* emit code to setup stack frame if user enabled,
3705 * and function is not main() */
3707 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3708 if(strcmp(sym->name, "main")) {
3710 || !options.ommitFramePtr
3712 || IFFUNC_ARGS(sym->type)
3713 || FUNC_HASSTACKPARM(sym->etype)
3715 /* setup the stack frame */
3716 if(STACK_MODEL_LARGE)
3717 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3718 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3720 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3721 if(STACK_MODEL_LARGE)
3722 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3726 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3729 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3731 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3732 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3734 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3737 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3738 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3745 /* if callee-save to be used for this function
3746 * then save the registers being used in this function */
3747 // if (IFFUNC_CALLEESAVES(sym->type))
3751 /* if any registers used */
3752 if (sym->regsUsed) {
3753 /* save the registers used */
3754 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3755 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3756 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3757 if (bitVectBitValue(sym->regsUsed,i)) {
3758 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3761 if(!pic16_regWithIdx(i)->wasUsed) {
3762 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3763 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3764 pic16_regWithIdx(i)->wasUsed = 1;
3768 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3772 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3773 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3776 /*-----------------------------------------------------------------*/
3777 /* genEndFunction - generates epilogue for functions */
3778 /*-----------------------------------------------------------------*/
3779 static void genEndFunction (iCode *ic)
3781 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3785 if(IFFUNC_ISNAKED(sym->type)) {
3786 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3792 /* add code for ISCRITICAL */
3793 if(IFFUNC_ISCRITICAL(sym->type)) {
3794 /* if critical function, turn on interrupts */
3796 /* TODO: add code here -- VR */
3799 // sym->regsUsed = _G.fregsUsed;
3801 /* now we need to restore the registers */
3802 /* if any registers used */
3804 /* first restore registers that might be used for stack access */
3805 if(_G.sregsAllocSet) {
3808 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3809 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3810 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3814 if (sym->regsUsed) {
3817 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3818 /* restore registers used */
3819 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3820 for ( i = sym->regsUsed->size; i >= 0; i--) {
3821 if (bitVectBitValue(sym->regsUsed,i)) {
3822 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3826 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3831 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3833 if (sym->stack == 1) {
3834 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3835 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3837 // we have to add more than one...
3838 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3839 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3840 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3842 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3843 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3844 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3848 if(strcmp(sym->name, "main")) {
3850 || !options.ommitFramePtr
3852 || IFFUNC_ARGS(sym->type)
3853 || FUNC_HASSTACKPARM(sym->etype)
3855 /* restore stack frame */
3856 if(STACK_MODEL_LARGE)
3857 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3858 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3864 if (IFFUNC_ISISR(sym->type)) {
3865 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3866 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3867 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3868 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3870 if(!FUNC_ISSHADOWREGS(sym->type)) {
3871 /* do not restore interrupt vector for WREG,STATUS,BSR
3872 * for high priority interrupt, see genFunction */
3873 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3874 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3875 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3877 // _G.interruptvector = 0; /* sanity check */
3880 /* if debug then send end of function */
3881 /* if (options.debug && currFunc) */
3883 debugFile->writeEndFunction (currFunc, ic, 1);
3886 if(_G.usefastretfie)
3887 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3889 pic16_emitpcodeNULLop(POC_RETFIE);
3891 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3893 _G.usefastretfie = 0;
3897 if (IFFUNC_ISCRITICAL(sym->type)) {
3898 pic16_emitcode("setb","ea");
3901 /* if debug then send end of function */
3903 debugFile->writeEndFunction (currFunc, ic, 1);
3906 /* insert code to restore stack frame, if user enabled it
3907 * and function is not main() */
3910 pic16_emitpcodeNULLop(POC_RETURN);
3912 /* Mark the end of a function */
3913 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3917 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3919 unsigned long lit=1;
3924 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3925 if(AOP_TYPE(op) == AOP_LIT) {
3926 if(!IS_FLOAT(operandType( op ))) {
3927 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3930 unsigned long lit_int;
3934 /* take care if literal is a float */
3935 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3941 pic16_movLit2f(dest, lit);
3943 if(dest->type == PO_WREG && (offset == 0)) {
3944 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3947 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3951 /*-----------------------------------------------------------------*/
3952 /* genRet - generate code for return statement */
3953 /*-----------------------------------------------------------------*/
3954 static void genRet (iCode *ic)
3960 /* if we have no return value then
3961 * just generate the "ret" */
3966 /* we have something to return then
3967 * move the return value into place */
3968 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3969 size = AOP_SIZE(IC_LEFT(ic));
3973 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3976 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3979 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3981 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3984 /* >32-bits, setup stack and FSR0 */
3986 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3987 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3989 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3991 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3996 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3997 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3999 if(STACK_MODEL_LARGE) {
4000 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4001 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4003 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4008 /* old code, left here for reference -- VR */
4012 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4014 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4015 pic16_emitpcomment("push %s",l);
4018 DEBUGpic16_emitcode(";", "%d", __LINE__);
4019 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4020 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4022 if (strcmp(fReturn[offset],l)) {
4023 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4024 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4025 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4027 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4031 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4041 if (strcmp(fReturn[pushed],"a"))
4042 pic16_emitcode("pop",fReturn[pushed]);
4044 pic16_emitcode("pop","acc");
4050 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4053 /* generate a jump to the return label
4054 * if the next is not the return statement */
4055 if (!(ic->next && ic->next->op == LABEL
4056 && IC_LABEL(ic->next) == returnLabel)) {
4058 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4059 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4063 /*-----------------------------------------------------------------*/
4064 /* genLabel - generates a label */
4065 /*-----------------------------------------------------------------*/
4066 static void genLabel (iCode *ic)
4070 /* special case never generate */
4071 if (IC_LABEL(ic) == entryLabel)
4074 pic16_emitpLabel(IC_LABEL(ic)->key);
4075 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4078 /*-----------------------------------------------------------------*/
4079 /* genGoto - generates a goto */
4080 /*-----------------------------------------------------------------*/
4082 static void genGoto (iCode *ic)
4085 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4086 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4090 /*-----------------------------------------------------------------*/
4091 /* genMultbits :- multiplication of bits */
4092 /*-----------------------------------------------------------------*/
4093 static void genMultbits (operand *left,
4099 if(!pic16_sameRegs(AOP(result),AOP(right)))
4100 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4102 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4103 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4104 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4109 /*-----------------------------------------------------------------*/
4110 /* genMultOneByte : 8 bit multiplication & division */
4111 /*-----------------------------------------------------------------*/
4112 static void genMultOneByte (operand *left,
4118 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4119 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4121 /* (if two literals, the value is computed before) */
4122 /* if one literal, literal on the right */
4123 if (AOP_TYPE(left) == AOP_LIT){
4129 /* size is already checked in genMult == 1 */
4130 // size = AOP_SIZE(result);
4132 if (AOP_TYPE(right) == AOP_LIT){
4133 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4134 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4135 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4136 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4138 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4139 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4140 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4141 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4144 pic16_genMult8X8_8 (left, right,result);
4147 /*-----------------------------------------------------------------*/
4148 /* genMultOneWord : 16 bit multiplication */
4149 /*-----------------------------------------------------------------*/
4150 static void genMultOneWord (operand *left,
4155 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4156 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4158 /* (if two literals, the value is computed before)
4159 * if one literal, literal on the right */
4160 if (AOP_TYPE(left) == AOP_LIT){
4166 /* size is checked already == 2 */
4167 // size = AOP_SIZE(result);
4169 if (AOP_TYPE(right) == AOP_LIT) {
4170 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4171 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4172 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4173 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4175 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4176 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4177 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4178 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4181 pic16_genMult16X16_16(left, right,result);
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneLong : 32 bit multiplication */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneLong (operand *left,
4192 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4193 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4195 /* (if two literals, the value is computed before)
4196 * if one literal, literal on the right */
4197 if (AOP_TYPE(left) == AOP_LIT){
4203 /* size is checked already == 4 */
4204 // size = AOP_SIZE(result);
4206 if (AOP_TYPE(right) == AOP_LIT) {
4207 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4208 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4213 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4214 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4215 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4218 pic16_genMult32X32_32(left, right,result);
4223 /*-----------------------------------------------------------------*/
4224 /* genMult - generates code for multiplication */
4225 /*-----------------------------------------------------------------*/
4226 static void genMult (iCode *ic)
4228 operand *left = IC_LEFT(ic);
4229 operand *right = IC_RIGHT(ic);
4230 operand *result= IC_RESULT(ic);
4233 /* assign the amsops */
4234 pic16_aopOp (left,ic,FALSE);
4235 pic16_aopOp (right,ic,FALSE);
4236 pic16_aopOp (result,ic,TRUE);
4238 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4240 /* special cases first *
4242 if (AOP_TYPE(left) == AOP_CRY
4243 && AOP_TYPE(right)== AOP_CRY) {
4244 genMultbits(left,right,result);
4248 /* if both are of size == 1 */
4249 if(AOP_SIZE(left) == 1
4250 && AOP_SIZE(right) == 1) {
4251 genMultOneByte(left,right,result);
4255 /* if both are of size == 2 */
4256 if(AOP_SIZE(left) == 2
4257 && AOP_SIZE(right) == 2) {
4258 genMultOneWord(left, right, result);
4262 /* if both are of size == 4 */
4263 if(AOP_SIZE(left) == 4
4264 && AOP_SIZE(right) == 4) {
4265 genMultOneLong(left, right, result);
4269 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4272 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4273 /* should have been converted to function call */
4277 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4279 pic16_freeAsmop(result,NULL,ic,TRUE);
4282 /*-----------------------------------------------------------------*/
4283 /* genDivbits :- division of bits */
4284 /*-----------------------------------------------------------------*/
4285 static void genDivbits (operand *left,
4292 /* the result must be bit */
4293 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4294 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4298 pic16_emitcode("div","ab");
4299 pic16_emitcode("rrc","a");
4300 pic16_aopPut(AOP(result),"c",0);
4303 /*-----------------------------------------------------------------*/
4304 /* genDivOneByte : 8 bit division */
4305 /*-----------------------------------------------------------------*/
4306 static void genDivOneByte (operand *left,
4310 sym_link *opetype = operandType(result);
4315 /* result = divident / divisor
4316 * - divident may be a register or a literal,
4317 * - divisor may be a register or a literal,
4318 * so there are 3 cases (literal / literal is optimized
4319 * by the front-end) to handle.
4320 * In addition we must handle signed and unsigned, which
4321 * result in 6 final different cases -- VR */
4325 size = AOP_SIZE(result) - 1;
4327 /* signed or unsigned */
4328 if (SPEC_USIGN(opetype)) {
4329 pCodeOp *pct1, /* count */
4332 symbol *label1, *label2, *label3;;
4335 /* unsigned is easy */
4337 pct1 = pic16_popGetTempReg(1);
4338 pct2 = pic16_popGetTempReg(1);
4339 pct3 = pic16_popGetTempReg(1);
4341 label1 = newiTempLabel(NULL);
4342 label2 = newiTempLabel(NULL);
4343 label3 = newiTempLabel(NULL);
4345 /* the following algorithm is extracted from divuint.c */
4347 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4348 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4350 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4352 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4354 pic16_emitpLabel(label1->key);
4357 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4361 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4365 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4367 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4368 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4370 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4371 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4372 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4374 pic16_emitpLabel( label3->key );
4375 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4376 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4380 pic16_emitpLabel(label2->key);
4381 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4382 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4383 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4385 /* result is in wreg */
4386 if(AOP_TYPE(result) != AOP_ACC)
4387 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4389 pic16_popReleaseTempReg( pct3, 1);
4390 pic16_popReleaseTempReg( pct2, 1);
4391 pic16_popReleaseTempReg( pct1, 1);
4396 /* signed is a little bit more difficult */
4398 /* save the signs of the operands */
4399 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4401 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4402 pic16_emitcode("push","acc"); /* save it on the stack */
4404 /* now sign adjust for both left & right */
4405 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4407 lbl = newiTempLabel(NULL);
4408 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4409 pic16_emitcode("cpl","a");
4410 pic16_emitcode("inc","a");
4411 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4412 pic16_emitcode("mov","b,a");
4414 /* sign adjust left side */
4415 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4418 lbl = newiTempLabel(NULL);
4419 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4420 pic16_emitcode("cpl","a");
4421 pic16_emitcode("inc","a");
4422 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4424 /* now the division */
4425 pic16_emitcode("div","ab");
4426 /* we are interested in the lower order
4428 pic16_emitcode("mov","b,a");
4429 lbl = newiTempLabel(NULL);
4430 pic16_emitcode("pop","acc");
4431 /* if there was an over flow we don't
4432 adjust the sign of the result */
4433 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4434 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4436 pic16_emitcode("clr","a");
4437 pic16_emitcode("subb","a,b");
4438 pic16_emitcode("mov","b,a");
4439 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4441 /* now we are done */
4442 pic16_aopPut(AOP(result),"b",0);
4444 pic16_emitcode("mov","c,b.7");
4445 pic16_emitcode("subb","a,acc");
4448 pic16_aopPut(AOP(result),"a",offset++);
4452 /*-----------------------------------------------------------------*/
4453 /* genDiv - generates code for division */
4454 /*-----------------------------------------------------------------*/
4455 static void genDiv (iCode *ic)
4457 operand *left = IC_LEFT(ic);
4458 operand *right = IC_RIGHT(ic);
4459 operand *result= IC_RESULT(ic);
4462 /* Division is a very lengthy algorithm, so it is better
4463 * to call support routines than inlining algorithm.
4464 * Division functions written here just in case someone
4465 * wants to inline and not use the support libraries -- VR */
4469 /* assign the amsops */
4470 pic16_aopOp (left,ic,FALSE);
4471 pic16_aopOp (right,ic,FALSE);
4472 pic16_aopOp (result,ic,TRUE);
4474 /* special cases first */
4476 if (AOP_TYPE(left) == AOP_CRY &&
4477 AOP_TYPE(right)== AOP_CRY) {
4478 genDivbits(left,right,result);
4482 /* if both are of size == 1 */
4483 if (AOP_SIZE(left) == 1 &&
4484 AOP_SIZE(right) == 1 ) {
4485 genDivOneByte(left,right,result);
4489 /* should have been converted to function call */
4492 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4494 pic16_freeAsmop(result,NULL,ic,TRUE);
4497 /*-----------------------------------------------------------------*/
4498 /* genModbits :- modulus of bits */
4499 /*-----------------------------------------------------------------*/
4500 static void genModbits (operand *left,
4508 werror(W_POSSBUG2, __FILE__, __LINE__);
4509 /* the result must be bit */
4510 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4511 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4515 pic16_emitcode("div","ab");
4516 pic16_emitcode("mov","a,b");
4517 pic16_emitcode("rrc","a");
4518 pic16_aopPut(AOP(result),"c",0);
4521 /*-----------------------------------------------------------------*/
4522 /* genModOneByte : 8 bit modulus */
4523 /*-----------------------------------------------------------------*/
4524 static void genModOneByte (operand *left,
4528 sym_link *opetype = operandType(result);
4533 werror(W_POSSBUG2, __FILE__, __LINE__);
4535 /* signed or unsigned */
4536 if (SPEC_USIGN(opetype)) {
4537 /* unsigned is easy */
4538 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4539 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4541 pic16_emitcode("div","ab");
4542 pic16_aopPut(AOP(result),"b",0);
4546 /* signed is a little bit more difficult */
4548 /* save the signs of the operands */
4549 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4552 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4553 pic16_emitcode("push","acc"); /* save it on the stack */
4555 /* now sign adjust for both left & right */
4556 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4559 lbl = newiTempLabel(NULL);
4560 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4561 pic16_emitcode("cpl","a");
4562 pic16_emitcode("inc","a");
4563 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4564 pic16_emitcode("mov","b,a");
4566 /* sign adjust left side */
4567 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4570 lbl = newiTempLabel(NULL);
4571 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4572 pic16_emitcode("cpl","a");
4573 pic16_emitcode("inc","a");
4574 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4576 /* now the multiplication */
4577 pic16_emitcode("div","ab");
4578 /* we are interested in the lower order
4580 lbl = newiTempLabel(NULL);
4581 pic16_emitcode("pop","acc");
4582 /* if there was an over flow we don't
4583 adjust the sign of the result */
4584 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4585 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4587 pic16_emitcode("clr","a");
4588 pic16_emitcode("subb","a,b");
4589 pic16_emitcode("mov","b,a");
4590 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4592 /* now we are done */
4593 pic16_aopPut(AOP(result),"b",0);
4597 /*-----------------------------------------------------------------*/
4598 /* genMod - generates code for division */
4599 /*-----------------------------------------------------------------*/
4600 static void genMod (iCode *ic)
4602 operand *left = IC_LEFT(ic);
4603 operand *right = IC_RIGHT(ic);
4604 operand *result= IC_RESULT(ic);
4608 /* assign the amsops */
4609 pic16_aopOp (left,ic,FALSE);
4610 pic16_aopOp (right,ic,FALSE);
4611 pic16_aopOp (result,ic,TRUE);
4613 /* special cases first */
4615 if (AOP_TYPE(left) == AOP_CRY &&
4616 AOP_TYPE(right)== AOP_CRY) {
4617 genModbits(left,right,result);
4621 /* if both are of size == 1 */
4622 if (AOP_SIZE(left) == 1 &&
4623 AOP_SIZE(right) == 1 ) {
4624 genModOneByte(left,right,result);
4628 /* should have been converted to function call */
4632 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4633 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4634 pic16_freeAsmop(result,NULL,ic,TRUE);
4637 /*-----------------------------------------------------------------*/
4638 /* genIfxJump :- will create a jump depending on the ifx */
4639 /*-----------------------------------------------------------------*/
4641 note: May need to add parameter to indicate when a variable is in bit space.
4643 static void genIfxJump (iCode *ic, char *jval)
4647 /* if true label then we jump if condition
4649 if ( IC_TRUE(ic) ) {
4651 if(strcmp(jval,"a") == 0)
4653 else if (strcmp(jval,"c") == 0)
4656 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4657 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4660 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4661 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4665 /* false label is present */
4666 if(strcmp(jval,"a") == 0)
4668 else if (strcmp(jval,"c") == 0)
4671 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4672 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4675 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4676 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4681 /* mark the icode as generated */
4685 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4689 /* if true label then we jump if condition
4691 if ( IC_TRUE(ic) ) {
4692 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4693 pic16_emitpcode(POC_BTFSC, jop);
4695 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4696 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4699 /* false label is present */
4700 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4701 pic16_emitpcode(POC_BTFSS, jop);
4703 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4704 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4708 /* mark the icode as generated */
4715 /*-----------------------------------------------------------------*/
4717 /*-----------------------------------------------------------------*/
4718 static void genSkip(iCode *ifx,int status_bit)
4720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4724 if ( IC_TRUE(ifx) ) {
4725 switch(status_bit) {
4740 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4741 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4745 switch(status_bit) {
4759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4760 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4767 /*-----------------------------------------------------------------*/
4769 /*-----------------------------------------------------------------*/
4770 static void genSkipc(resolvedIfx *rifx)
4772 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4782 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4783 rifx->generated = 1;
4786 #if !(USE_SIMPLE_GENCMP)
4787 /*-----------------------------------------------------------------*/
4789 /*-----------------------------------------------------------------*/
4790 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4792 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4797 if( (rifx->condition ^ invert_condition) & 1)
4802 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4803 rifx->generated = 1;
4808 /*-----------------------------------------------------------------*/
4810 /*-----------------------------------------------------------------*/
4811 static void genSkipz(iCode *ifx, int condition)
4822 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4824 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4827 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4829 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4834 #if !(USE_SIMPLE_GENCMP)
4835 /*-----------------------------------------------------------------*/
4837 /*-----------------------------------------------------------------*/
4838 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4844 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4846 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4849 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4850 rifx->generated = 1;
4855 /*-----------------------------------------------------------------*/
4856 /* genChkZeroes :- greater or less than comparison */
4857 /* For each byte in a literal that is zero, inclusive or the */
4858 /* the corresponding byte in the operand with W */
4859 /* returns true if any of the bytes are zero */
4860 /*-----------------------------------------------------------------*/
4861 static int genChkZeroes(operand *op, int lit, int size)
4868 i = (lit >> (size*8)) & 0xff;
4872 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4874 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4884 /*-----------------------------------------------------------------*/
4885 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4886 /* aop (if it's NOT a literal) or from lit (if */
4887 /* aop is a literal) */
4888 /*-----------------------------------------------------------------*/
4889 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4890 if (aop->type == AOP_LIT) {
4891 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4893 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4897 /*-----------------------------------------------------------------*/
4898 /* genCmp :- greater or less than comparison */
4899 /*-----------------------------------------------------------------*/
4901 #if USE_SIMPLE_GENCMP /* { */
4903 /* genCmp performs a left < right comparison, stores
4904 * the outcome in result (if != NULL) and generates
4905 * control flow code for the ifx (if != NULL).
4907 * This version leaves in sequences like
4908 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4909 * which should be optmized by the peephole
4910 * optimizer - RN 2005-01-01 */
4911 static void genCmp (operand *left,operand *right,
4912 operand *result, iCode *ifx, int sign)
4925 assert (left && right);
4926 assert (AOP_SIZE(left) == AOP_SIZE(right));
4928 size = AOP_SIZE(right) - 1;
4929 mask = (0x100UL << (size*8)) - 1;
4930 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4935 resolveIfx (&rIfx, ifx);
4937 /* handle for special cases */
4938 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4941 /**********************************************************************
4942 * handle bits - bit compares are promoted to int compares seemingly! *
4943 **********************************************************************/
4945 // THIS IS COMPLETELY UNTESTED!
4946 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4947 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4948 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4949 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4952 // 1 < {0,1} is false --> clear C by skipping the next instruction
4953 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4954 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4955 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4956 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4957 emitCLRC; // only skipped for left=0 && right=1
4959 goto correct_result_in_carry;
4963 /*************************************************
4964 * make sure that left is register (or the like) *
4965 *************************************************/
4966 if (!isAOP_REGlike(left)) {
4967 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4968 assert (isAOP_LIT(left));
4969 assert (isAOP_REGlike(right));
4970 // swap left and right
4971 // left < right <==> right > left <==> (right >= left + 1)
4972 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4974 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4975 // MAXVALUE < right? always false
4976 if (performedLt) emitCLRC; else emitSETC;
4977 goto correct_result_in_carry;
4980 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4981 // that's why we handled it above.
4988 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4989 } else if (isAOP_LIT(right)) {
4990 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4993 assert (isAOP_REGlike(left)); // left must be register or the like
4994 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4996 /*************************************************
4997 * special cases go here *
4998 *************************************************/
5000 if (isAOP_LIT(right)) {
5002 // unsigned comparison to a literal
5003 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5005 // unsigned left < 0? always false
5006 if (performedLt) emitCLRC; else emitSETC;
5007 goto correct_result_in_carry;
5010 // signed comparison to a literal
5011 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5012 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5013 // signed left < 0x80000000? always false
5014 if (performedLt) emitCLRC; else emitSETC;
5015 goto correct_result_in_carry;
5016 } else if (lit == 0) {
5017 // compare left < 0; set CARRY if SIGNBIT(left) is set
5018 if (performedLt) emitSETC; else emitCLRC;
5019 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5020 if (performedLt) emitCLRC; else emitSETC;
5021 goto correct_result_in_carry;
5024 } // right is literal
5026 /*************************************************
5027 * perform a general case comparison *
5028 * make sure we get CARRY==1 <==> left >= right *
5029 *************************************************/
5030 // compare most significant bytes
5031 //DEBUGpc ("comparing bytes at offset %d", size);
5033 // unsigned comparison
5034 mov2w_regOrLit (AOP(right), lit, size);
5035 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5037 // signed comparison
5038 // (add 2^n to both operands then perform an unsigned comparison)
5039 if (isAOP_LIT(right)) {
5040 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5041 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5043 if (litbyte == 0x80) {
5044 // left >= 0x80 -- always true, but more bytes to come
5045 pic16_mov2w (AOP(left), size);
5046 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5049 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5050 pic16_mov2w (AOP(left), size);
5051 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5052 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5055 /* using PRODL as a temporary register here */
5056 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5057 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5058 pic16_mov2w (AOP(left), size);
5059 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5060 pic16_emitpcode (POC_MOVWF, pctemp);
5061 pic16_mov2w (AOP(right), size);
5062 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5063 pic16_emitpcode (POC_SUBFW, pctemp);
5064 //pic16_popReleaseTempReg(pctemp, 1);
5068 // compare remaining bytes (treat as unsigned case from above)
5069 templbl = newiTempLabel ( NULL );
5072 //DEBUGpc ("comparing bytes at offset %d", offs);
5073 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5074 mov2w_regOrLit (AOP(right), lit, offs);
5075 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5077 pic16_emitpLabel (templbl->key);
5078 goto result_in_carry;
5082 /****************************************************
5083 * now CARRY contains the result of the comparison: *
5084 * SUBWF sets CARRY iff *
5085 * F-W >= 0 <==> F >= W <==> !(F < W) *
5086 * (F=left, W=right) *
5087 ****************************************************/
5090 if (result && AOP_TYPE(result) != AOP_CRY) {
5091 // value will be stored
5094 // value wil only be used in the following genSkipc()
5095 rIfx.condition ^= 1;
5099 correct_result_in_carry:
5101 // assign result to variable (if neccessary)
5102 if (result && AOP_TYPE(result) != AOP_CRY) {
5103 //DEBUGpc ("assign result");
5104 size = AOP_SIZE(result);
5106 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5108 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5111 // perform conditional jump
5113 //DEBUGpc ("generate control flow");
5122 static void genCmp (operand *left,operand *right,
5123 operand *result, iCode *ifx, int sign)
5125 int size; //, offset = 0 ;
5126 unsigned long lit = 0L,i = 0;
5127 resolvedIfx rFalseIfx;
5128 // resolvedIfx rTrueIfx;
5130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5133 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5134 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5140 resolveIfx(&rFalseIfx,ifx);
5141 truelbl = newiTempLabel(NULL);
5142 size = max(AOP_SIZE(left),AOP_SIZE(right));
5144 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5148 /* if literal is on the right then swap with left */
5149 if ((AOP_TYPE(right) == AOP_LIT)) {
5150 operand *tmp = right ;
5151 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5152 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5155 lit = (lit - 1) & mask;
5158 rFalseIfx.condition ^= 1;
5161 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5162 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5166 //if(IC_TRUE(ifx) == NULL)
5167 /* if left & right are bit variables */
5168 if (AOP_TYPE(left) == AOP_CRY &&
5169 AOP_TYPE(right) == AOP_CRY ) {
5170 assert (0 && "bit variables used in genCmp");
5171 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5172 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5174 /* subtract right from left if at the
5175 end the carry flag is set then we know that
5176 left is greater than right */
5178 symbol *lbl = newiTempLabel(NULL);
5181 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5182 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5186 if(AOP_TYPE(right) == AOP_LIT) {
5188 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5190 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5197 genSkipCond(&rFalseIfx,left,size-1,7);
5199 /* no need to compare to 0...*/
5200 /* NOTE: this is a de-generate compare that most certainly
5201 * creates some dead code. */
5202 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5204 if(ifx) ifx->generated = 1;
5211 //i = (lit >> (size*8)) & 0xff;
5212 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5216 i = ((0-lit) & 0xff);
5219 /* lit is 0x7f, all signed chars are less than
5220 * this except for 0x7f itself */
5221 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5222 genSkipz2(&rFalseIfx,0);
5224 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5225 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5226 genSkipc(&rFalseIfx);
5231 genSkipz2(&rFalseIfx,1);
5233 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5234 genSkipc(&rFalseIfx);
5238 if(ifx) ifx->generated = 1;
5242 /* chars are out of the way. now do ints and longs */
5245 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5252 genSkipCond(&rFalseIfx,left,size,7);
5253 if(ifx) ifx->generated = 1;
5258 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5260 //rFalseIfx.condition ^= 1;
5261 //genSkipCond(&rFalseIfx,left,size,7);
5262 //rFalseIfx.condition ^= 1;
5264 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5265 if(rFalseIfx.condition)
5266 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5268 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5270 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5271 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5272 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5275 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5277 if(rFalseIfx.condition) {
5279 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5285 genSkipc(&rFalseIfx);
5286 pic16_emitpLabel(truelbl->key);
5287 if(ifx) ifx->generated = 1;
5294 if( (lit & 0xff) == 0) {
5295 /* lower byte is zero */
5296 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5297 i = ((lit >> 8) & 0xff) ^0x80;
5298 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5299 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5300 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5301 genSkipc(&rFalseIfx);
5304 if(ifx) ifx->generated = 1;
5309 /* Special cases for signed longs */
5310 if( (lit & 0xffffff) == 0) {
5311 /* lower byte is zero */
5312 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5313 i = ((lit >> 8*3) & 0xff) ^0x80;
5314 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5315 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5316 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5317 genSkipc(&rFalseIfx);
5320 if(ifx) ifx->generated = 1;
5328 if(lit & (0x80 << (size*8))) {
5329 /* lit is negative */
5330 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5332 //genSkipCond(&rFalseIfx,left,size,7);
5334 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336 if(rFalseIfx.condition)
5337 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5343 /* lit is positive */
5344 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5345 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5346 if(rFalseIfx.condition)
5347 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5349 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5354 This works, but is only good for ints.
5355 It also requires a "known zero" register.
5356 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5357 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5358 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5359 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5360 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5361 genSkipc(&rFalseIfx);
5363 pic16_emitpLabel(truelbl->key);
5364 if(ifx) ifx->generated = 1;
5368 /* There are no more special cases, so perform a general compare */
5370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5371 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5375 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5377 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5379 //rFalseIfx.condition ^= 1;
5380 genSkipc(&rFalseIfx);
5382 pic16_emitpLabel(truelbl->key);
5384 if(ifx) ifx->generated = 1;
5391 /* sign is out of the way. So now do an unsigned compare */
5392 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5395 /* General case - compare to an unsigned literal on the right.*/
5397 i = (lit >> (size*8)) & 0xff;
5398 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5399 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5401 i = (lit >> (size*8)) & 0xff;
5404 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5406 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5408 /* this byte of the lit is zero,
5409 *if it's not the last then OR in the variable */
5411 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5416 pic16_emitpLabel(lbl->key);
5417 // pic16_emitpLabel(truelbl->key);
5418 //if(emitFinalCheck)
5419 genSkipc(&rFalseIfx);
5421 pic16_emitpLabel(truelbl->key);
5423 if(ifx) ifx->generated = 1;
5430 if(AOP_TYPE(left) == AOP_LIT) {
5431 //symbol *lbl = newiTempLabel(NULL);
5433 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5436 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5439 if((lit == 0) && (sign == 0)){
5442 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5444 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5446 genSkipz2(&rFalseIfx,0);
5447 if(ifx) ifx->generated = 1;
5454 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5455 /* degenerate compare can never be true */
5456 if(rFalseIfx.condition == 0)
5457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5459 if(ifx) ifx->generated = 1;
5464 /* signed comparisons to a literal byte */
5466 int lp1 = (lit+1) & 0xff;
5468 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5471 rFalseIfx.condition ^= 1;
5472 genSkipCond(&rFalseIfx,right,0,7);
5475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5476 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5477 genSkipz2(&rFalseIfx,1);
5480 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5481 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5482 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5483 rFalseIfx.condition ^= 1;
5484 genSkipc(&rFalseIfx);
5488 /* unsigned comparisons to a literal byte */
5490 switch(lit & 0xff ) {
5492 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5493 genSkipz2(&rFalseIfx,0);
5496 rFalseIfx.condition ^= 1;
5497 genSkipCond(&rFalseIfx,right,0,7);
5501 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5502 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5504 rFalseIfx.condition ^= 1;
5505 if (AOP_TYPE(result) == AOP_CRY)
5506 genSkipc(&rFalseIfx);
5508 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5509 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5515 if(ifx) ifx->generated = 1;
5516 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5522 /* Size is greater than 1 */
5530 /* this means lit = 0xffffffff, or -1 */
5533 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5534 rFalseIfx.condition ^= 1;
5535 genSkipCond(&rFalseIfx,right,size,7);
5536 if(ifx) ifx->generated = 1;
5538 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5547 if(rFalseIfx.condition) {
5548 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5549 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5552 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5554 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5558 if(rFalseIfx.condition) {
5559 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5560 pic16_emitpLabel(truelbl->key);
5562 rFalseIfx.condition ^= 1;
5563 genSkipCond(&rFalseIfx,right,s,7);
5566 if(ifx) ifx->generated = 1;
5568 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5574 if((size == 1) && (0 == (lp1&0xff))) {
5575 /* lower byte of signed word is zero */
5576 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5577 i = ((lp1 >> 8) & 0xff) ^0x80;
5578 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5579 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5580 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5582 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5584 if(ifx) ifx->generated = 1;
5587 rFalseIfx.condition ^= 1;
5588 genSkipc(&rFalseIfx);
5589 if(ifx) ifx->generated = 1;
5595 if(lit & (0x80 << (size*8))) {
5596 /* Lit is less than zero */
5597 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5598 //rFalseIfx.condition ^= 1;
5599 //genSkipCond(&rFalseIfx,left,size,7);
5600 //rFalseIfx.condition ^= 1;
5601 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5602 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5604 if(rFalseIfx.condition)
5605 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5607 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5611 /* Lit is greater than or equal to zero */
5612 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5613 //rFalseIfx.condition ^= 1;
5614 //genSkipCond(&rFalseIfx,right,size,7);
5615 //rFalseIfx.condition ^= 1;
5617 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5618 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5620 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5621 if(rFalseIfx.condition)
5622 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5624 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5628 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5629 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5633 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5635 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5637 rFalseIfx.condition ^= 1;
5638 //rFalseIfx.condition = 1;
5639 genSkipc(&rFalseIfx);
5641 pic16_emitpLabel(truelbl->key);
5643 if(ifx) ifx->generated = 1;
5646 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5653 /* compare word or long to an unsigned literal on the right.*/
5658 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5661 break; /* handled above */
5664 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5666 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5667 genSkipz2(&rFalseIfx,0);
5671 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5673 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5676 if(rFalseIfx.condition)
5677 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5679 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5682 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5683 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5685 rFalseIfx.condition ^= 1;
5686 genSkipc(&rFalseIfx);
5689 pic16_emitpLabel(truelbl->key);
5691 if(ifx) ifx->generated = 1;
5693 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5701 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5702 i = (lit >> (size*8)) & 0xff;
5704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5705 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 i = (lit >> (size*8)) & 0xff;
5711 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5713 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5715 /* this byte of the lit is zero,
5716 * if it's not the last then OR in the variable */
5718 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5723 pic16_emitpLabel(lbl->key);
5725 rFalseIfx.condition ^= 1;
5727 genSkipc(&rFalseIfx);
5731 pic16_emitpLabel(truelbl->key);
5732 if(ifx) ifx->generated = 1;
5734 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5740 /* Compare two variables */
5742 DEBUGpic16_emitcode(";sign","%d",sign);
5746 /* Sigh. thus sucks... */
5750 pctemp = pic16_popGetTempReg(1);
5751 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5752 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5753 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5754 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5755 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5756 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5757 pic16_popReleaseTempReg(pctemp, 1);
5759 /* Signed char comparison */
5760 /* Special thanks to Nikolai Golovchenko for this snippet */
5761 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5762 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5763 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5764 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5765 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5766 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5769 genSkipc(&rFalseIfx);
5771 if(ifx) ifx->generated = 1;
5773 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5781 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5782 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5786 /* The rest of the bytes of a multi-byte compare */
5790 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5793 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5794 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5799 pic16_emitpLabel(lbl->key);
5801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5802 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5803 (AOP_TYPE(result) == AOP_REG)) {
5804 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5805 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5807 genSkipc(&rFalseIfx);
5809 //genSkipc(&rFalseIfx);
5810 if(ifx) ifx->generated = 1;
5813 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5821 if ((AOP_TYPE(result) != AOP_CRY)
5822 && AOP_SIZE(result)) {
5823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5825 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5827 pic16_outBitC(result);
5829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5830 /* if the result is used in the next
5831 ifx conditional branch then generate
5832 code a little differently */
5834 genIfxJump (ifx,"c");
5836 pic16_outBitC(result);
5837 /* leave the result in acc */
5842 #elif 0 /* VR version of genCmp() */ /* } else { */
5844 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5845 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5846 operand *result, int offset, int invert_op)
5850 /* check condition, > or < ?? */
5851 if(rIfx->condition != 0)invert_op ^= 1;
5853 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5855 if(!ifx)invert_op ^= 1;
5857 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5858 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5861 if(!invert_op)return POC_CPFSGT;
5862 else return POC_CPFSLT;
5865 static int compareAopfirstpass=1;
5867 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5868 operand *oper, int offset, operand *result,
5869 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5875 /* invert if there is a result to be loaded, in order to fit,
5876 * SETC/CLRC sequence */
5877 if(AOP_SIZE(result))invert_op ^= 1;
5879 // if(sign && !offset)invert_op ^= 1;
5881 // if(sign)invert_op ^= 1;
5883 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5885 if(AOP_SIZE(result) && compareAopfirstpass) {
5888 pic16_emitpcode(POC_SETF, pcop2);
5893 pic16_emitpcode(POC_CLRF, pcop2);
5899 compareAopfirstpass = 0;
5901 /* there is a bug when comparing operands with size > 1,
5902 * because higher bytes can be equal and test should be performed
5903 * to the next lower byte, current algorithm, considers operands
5904 * inequal in these cases! -- VR 20041107 */
5908 pic16_emitpcode(op, pcop);
5910 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5913 if((!sign || !offset) && AOP_SIZE(result)) {
5916 pic16_emitpcode(POC_CLRF, pcop2);
5921 pic16_emitpcode(POC_SETF, pcop2);
5926 /* don't emit final branch (offset == 0) */
5930 pic16_emitpcode(POC_RRCF, pcop2);
5932 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5935 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5936 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5937 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5939 truelbl = newiTempLabel( NULL );
5940 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5941 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5942 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5945 pic16_emitpLabel(truelbl->key);
5947 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5952 static void genCmp (operand *left, operand *right,
5953 operand *result, iCode *ifx, int sign)
5957 resolvedIfx rFalseIfx;
5958 symbol *falselbl, *tlbl;
5962 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5964 resolveIfx(&rFalseIfx, ifx);
5965 size = max(AOP_SIZE(left), AOP_SIZE(right));
5967 /* if left & right are bit variables */
5968 if(AOP_TYPE(left) == AOP_CRY
5969 && AOP_TYPE(right) == AOP_CRY ) {
5971 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5972 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5974 werror(W_POSSBUG2, __FILE__, __LINE__);
5978 /* if literal is on the right then swap with left */
5979 if((AOP_TYPE(right) == AOP_LIT)) {
5980 operand *tmp = right ;
5981 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5983 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5985 // lit = (lit - 1) & mask;
5988 rFalseIfx.condition ^= 1; /* reverse compare */
5990 if ((AOP_TYPE(left) == AOP_LIT)) {
5991 /* float compares are handled by support functions */
5992 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5995 /* actual comparing algorithm */
5996 // size = AOP_SIZE( right );
5998 falselbl = newiTempLabel( NULL );
5999 if(AOP_TYPE(left) == AOP_LIT) {
6000 /* compare to literal */
6001 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6004 pCodeOp *pct, *pct2;
6007 /* signed compare */
6008 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6010 /* using PRODL:PRODH as a temporary register here */
6011 pct = pic16_popCopyReg(&pic16_pc_prodl);
6012 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6013 tlbl = newiTempLabel( NULL );
6015 /* first compare signs:
6016 * a. if both are positive, compare just like unsigned
6017 * b. if both are negative, invert cmpop, compare just like unsigned
6018 * c. if different signs, determine the result directly */
6024 tlbl1 = newiTempLabel( NULL );
6025 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6029 /* literal is zero or positive:
6030 * a. if carry is zero, too, continue compare,
6031 * b. if carry is set, then continue depending on cmpop ^ condition:
6032 * 1. '<' return false (literal < variable),
6033 * 2. '>' return true (literal > variable) */
6034 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6035 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6038 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6039 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6043 /* literal is negative:
6044 * a. if carry is set, too, continue compare,
6045 * b. if carry is zero, then continue depending on cmpop ^ condition:
6046 * 1. '<' return true (literal < variable),
6047 * 2. '>' return false (literal > variable) */
6048 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6049 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6051 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6052 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6057 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6059 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6060 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6065 pic16_emitpLabel( tlbl1->key );
6068 compareAopfirstpass=1;
6069 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6070 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6071 // pic16_emitpcode(POC_MOVWF, pct);
6073 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6074 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6075 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6076 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6080 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6081 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6082 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6083 // pic16_emitpcode(POC_MOVWF, pct);
6085 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6086 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6087 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6088 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6089 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6092 if(ifx)ifx->generated = 1;
6094 if(AOP_SIZE(result)) {
6095 pic16_emitpLabel(tlbl->key);
6096 pic16_emitpLabel(falselbl->key);
6097 pic16_outBitOp( result, pct2 );
6099 pic16_emitpLabel(tlbl->key);
6103 /* unsigned compare */
6104 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6106 compareAopfirstpass=1;
6109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6110 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6113 if(ifx)ifx->generated = 1;
6115 if(AOP_SIZE(result)) {
6116 pic16_emitpLabel(falselbl->key);
6117 pic16_outBitC( result );
6122 /* compare registers */
6123 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6127 pCodeOp *pct, *pct2;
6129 /* signed compare */
6130 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6132 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6133 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6134 tlbl = newiTempLabel( NULL );
6136 compareAopfirstpass=1;
6139 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6140 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6141 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6142 pic16_emitpcode(POC_MOVWF, pct);
6144 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6145 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6146 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6148 /* WREG already holds left + 0x80 */
6149 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6152 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6153 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6155 pic16_emitpcode(POC_MOVWF, pct);
6157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6159 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6161 /* WREG already holds left + 0x80 */
6162 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6163 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6166 if(ifx)ifx->generated = 1;
6168 if(AOP_SIZE(result)) {
6169 pic16_emitpLabel(tlbl->key);
6170 pic16_emitpLabel(falselbl->key);
6171 pic16_outBitOp( result, pct2 );
6173 pic16_emitpLabel(tlbl->key);
6177 /* unsigned compare */
6178 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6180 compareAopfirstpass=1;
6183 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6184 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6188 if(ifx)ifx->generated = 1;
6189 if(AOP_SIZE(result)) {
6191 pic16_emitpLabel(falselbl->key);
6192 pic16_outBitC( result );
6203 /*-----------------------------------------------------------------*/
6204 /* genCmpGt :- greater than comparison */
6205 /*-----------------------------------------------------------------*/
6206 static void genCmpGt (iCode *ic, iCode *ifx)
6208 operand *left, *right, *result;
6209 sym_link *letype , *retype;
6215 right= IC_RIGHT(ic);
6216 result = IC_RESULT(ic);
6218 letype = getSpec(operandType(left));
6219 retype =getSpec(operandType(right));
6220 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6221 /* assign the amsops */
6222 pic16_aopOp (left,ic,FALSE);
6223 pic16_aopOp (right,ic,FALSE);
6224 pic16_aopOp (result,ic,TRUE);
6226 genCmp(right, left, result, ifx, sign);
6228 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6229 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6230 pic16_freeAsmop(result,NULL,ic,TRUE);
6233 /*-----------------------------------------------------------------*/
6234 /* genCmpLt - less than comparisons */
6235 /*-----------------------------------------------------------------*/
6236 static void genCmpLt (iCode *ic, iCode *ifx)
6238 operand *left, *right, *result;
6239 sym_link *letype , *retype;
6245 right= IC_RIGHT(ic);
6246 result = IC_RESULT(ic);
6248 letype = getSpec(operandType(left));
6249 retype =getSpec(operandType(right));
6250 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6252 /* assign the amsops */
6253 pic16_aopOp (left,ic,FALSE);
6254 pic16_aopOp (right,ic,FALSE);
6255 pic16_aopOp (result,ic,TRUE);
6257 genCmp(left, right, result, ifx, sign);
6259 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6261 pic16_freeAsmop(result,NULL,ic,TRUE);
6266 // FIXME reenable literal optimisation when the pic16 port is stable
6268 /*-----------------------------------------------------------------*/
6269 /* genc16bit2lit - compare a 16 bit value to a literal */
6270 /*-----------------------------------------------------------------*/
6271 static void genc16bit2lit(operand *op, int lit, int offset)
6275 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6276 if( (lit&0xff) == 0)
6281 switch( BYTEofLONG(lit,i)) {
6283 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6286 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6289 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6292 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6293 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6298 switch( BYTEofLONG(lit,i)) {
6300 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6304 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6308 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6311 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6313 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6322 /*-----------------------------------------------------------------*/
6323 /* gencjneshort - compare and jump if not equal */
6324 /*-----------------------------------------------------------------*/
6325 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6327 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6329 int res_offset = 0; /* the result may be a different size then left or right */
6330 int res_size = AOP_SIZE(result);
6332 symbol *lbl, *lbl_done;
6334 unsigned long lit = 0L;
6335 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6338 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6340 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6341 resolveIfx(&rIfx,ifx);
6342 lbl = newiTempLabel(NULL);
6343 lbl_done = newiTempLabel(NULL);
6346 /* if the left side is a literal or
6347 if the right is in a pointer register and left
6349 if ((AOP_TYPE(left) == AOP_LIT) ||
6350 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6355 if(AOP_TYPE(right) == AOP_LIT)
6356 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6358 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6359 preserve_result = 1;
6361 if(result && !preserve_result)
6364 for(i = 0; i < AOP_SIZE(result); i++)
6365 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6369 /* if the right side is a literal then anything goes */
6370 if (AOP_TYPE(right) == AOP_LIT &&
6371 AOP_TYPE(left) != AOP_DIR ) {
6374 genc16bit2lit(left, lit, 0);
6376 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6382 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6383 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6385 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6389 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6391 if(res_offset < res_size-1)
6399 /* if the right side is in a register or in direct space or
6400 if the left is a pointer register & right is not */
6401 else if (AOP_TYPE(right) == AOP_REG ||
6402 AOP_TYPE(right) == AOP_DIR ||
6403 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6404 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6405 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6406 int lbl_key = lbl->key;
6409 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6410 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6412 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6413 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6414 __FUNCTION__,__LINE__);
6418 /* switch(size) { */
6420 /* genc16bit2lit(left, lit, 0); */
6422 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6427 if((AOP_TYPE(left) == AOP_DIR) &&
6428 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6430 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6431 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6433 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6435 switch (lit & 0xff) {
6437 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6440 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6441 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6446 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6447 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6448 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6453 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6454 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6459 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6462 if(AOP_TYPE(result) == AOP_CRY) {
6463 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6468 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6470 /* fix me. probably need to check result size too */
6471 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6476 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6477 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6484 if(res_offset < res_size-1)
6489 } else if(AOP_TYPE(right) == AOP_REG &&
6490 AOP_TYPE(left) != AOP_DIR){
6493 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6494 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6495 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6500 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6502 if(res_offset < res_size-1)
6507 /* right is a pointer reg need both a & b */
6509 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6511 pic16_emitcode("mov","b,%s",l);
6512 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6513 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6518 if(result && preserve_result)
6521 for(i = 0; i < AOP_SIZE(result); i++)
6522 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6525 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6527 if(result && preserve_result)
6528 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6531 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6533 pic16_emitpLabel(lbl->key);
6535 if(result && preserve_result)
6538 for(i = 0; i < AOP_SIZE(result); i++)
6539 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6541 pic16_emitpLabel(lbl_done->key);
6544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6552 /*-----------------------------------------------------------------*/
6553 /* gencjne - compare and jump if not equal */
6554 /*-----------------------------------------------------------------*/
6555 static void gencjne(operand *left, operand *right, iCode *ifx)
6557 symbol *tlbl = newiTempLabel(NULL);
6559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6560 gencjneshort(left, right, lbl);
6562 pic16_emitcode("mov","a,%s",one);
6563 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6564 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6565 pic16_emitcode("clr","a");
6566 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6568 pic16_emitpLabel(lbl->key);
6569 pic16_emitpLabel(tlbl->key);
6575 /*-----------------------------------------------------------------*/
6576 /* is_LitOp - check if operand has to be treated as literal */
6577 /*-----------------------------------------------------------------*/
6578 static bool is_LitOp(operand *op)
6580 return ((AOP_TYPE(op) == AOP_LIT)
6581 || ( (AOP_TYPE(op) == AOP_PCODE)
6582 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6583 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6586 /*-----------------------------------------------------------------*/
6587 /* is_LitAOp - check if operand has to be treated as literal */
6588 /*-----------------------------------------------------------------*/
6589 static bool is_LitAOp(asmop *aop)
6591 return ((aop->type == AOP_LIT)
6592 || ( (aop->type == AOP_PCODE)
6593 && ( (aop->aopu.pcop->type == PO_LITERAL)
6594 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6599 /*-----------------------------------------------------------------*/
6600 /* genCmpEq - generates code for equal to */
6601 /*-----------------------------------------------------------------*/
6602 static void genCmpEq (iCode *ic, iCode *ifx)
6604 operand *left, *right, *result;
6605 symbol *falselbl = newiTempLabel(NULL);
6606 symbol *donelbl = newiTempLabel(NULL);
6608 int preserve_result = 0;
6609 int generate_result = 0;
6611 unsigned long lit = -1;
6615 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6616 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6617 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6619 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6621 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6623 werror(W_POSSBUG2, __FILE__, __LINE__);
6624 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6625 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6629 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6631 operand *tmp = right ;
6636 if (AOP_TYPE(right) == AOP_LIT) {
6637 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6640 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6641 preserve_result = 1;
6643 if(result && AOP_SIZE(result))
6644 generate_result = 1;
6646 if(generate_result && !preserve_result)
6648 for(i = 0; i < AOP_SIZE(result); i++)
6649 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6652 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6653 for(i=0; i < AOP_SIZE(left); i++)
6655 if(AOP_TYPE(left) != AOP_ACC)
6658 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6660 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6662 if(is_LitOp(right)) {
6663 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6664 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6667 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6669 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6674 if(generate_result && preserve_result)
6676 for(i = 0; i < AOP_SIZE(result); i++)
6677 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6681 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6683 if(generate_result && preserve_result)
6684 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6686 if(ifx && IC_TRUE(ifx))
6687 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6689 if(ifx && IC_FALSE(ifx))
6690 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6692 pic16_emitpLabel(falselbl->key);
6696 if(ifx && IC_FALSE(ifx))
6697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
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 pic16_emitpLabel(donelbl->key);
6711 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6712 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6713 pic16_freeAsmop(result,NULL,ic,TRUE);
6719 // old version kept for reference
6721 /*-----------------------------------------------------------------*/
6722 /* genCmpEq - generates code for equal to */
6723 /*-----------------------------------------------------------------*/
6724 static void genCmpEq (iCode *ic, iCode *ifx)
6726 operand *left, *right, *result;
6727 unsigned long lit = 0L;
6729 symbol *falselbl = newiTempLabel(NULL);
6732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6735 DEBUGpic16_emitcode ("; ifx is non-null","");
6737 DEBUGpic16_emitcode ("; ifx is null","");
6739 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6740 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6741 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6743 size = max(AOP_SIZE(left),AOP_SIZE(right));
6745 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6747 /* if literal, literal on the right or
6748 if the right is in a pointer register and left
6750 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6751 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6752 operand *tmp = right ;
6758 if(ifx && !AOP_SIZE(result)){
6760 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6761 /* if they are both bit variables */
6762 if (AOP_TYPE(left) == AOP_CRY &&
6763 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6764 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6765 if(AOP_TYPE(right) == AOP_LIT){
6766 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6768 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6769 pic16_emitcode("cpl","c");
6770 } else if(lit == 1L) {
6771 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6773 pic16_emitcode("clr","c");
6775 /* AOP_TYPE(right) == AOP_CRY */
6777 symbol *lbl = newiTempLabel(NULL);
6778 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6779 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6780 pic16_emitcode("cpl","c");
6781 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6783 /* if true label then we jump if condition
6785 tlbl = newiTempLabel(NULL);
6786 if ( IC_TRUE(ifx) ) {
6787 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6788 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6790 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6791 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6793 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6796 /* left and right are both bit variables, result is carry */
6799 resolveIfx(&rIfx,ifx);
6801 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6802 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6803 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6804 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6809 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6811 /* They're not both bit variables. Is the right a literal? */
6812 if(AOP_TYPE(right) == AOP_LIT) {
6813 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6818 switch(lit & 0xff) {
6820 if ( IC_TRUE(ifx) ) {
6821 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6823 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6825 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6826 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6830 if ( IC_TRUE(ifx) ) {
6831 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6833 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6835 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6836 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6840 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6842 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6847 /* end of size == 1 */
6851 genc16bit2lit(left,lit,offset);
6854 /* end of size == 2 */
6859 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6860 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6861 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6862 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6865 /* search for patterns that can be optimized */
6867 genc16bit2lit(left,lit,0);
6871 emitSKPZ; // if hi word unequal
6873 emitSKPNZ; // if hi word equal
6875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6876 genc16bit2lit(left,lit,2);
6879 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6880 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6884 pic16_emitpLabel(falselbl->key);
6893 } else if(AOP_TYPE(right) == AOP_CRY ) {
6894 /* we know the left is not a bit, but that the right is */
6895 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6896 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6897 pic16_popGet(AOP(right),offset));
6898 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6900 /* if the two are equal, then W will be 0 and the Z bit is set
6901 * we could test Z now, or go ahead and check the high order bytes if
6902 * the variable we're comparing is larger than a byte. */
6905 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6907 if ( IC_TRUE(ifx) ) {
6909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6910 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6913 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6914 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6918 /* They're both variables that are larger than bits */
6921 tlbl = newiTempLabel(NULL);
6924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6925 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6927 if ( IC_TRUE(ifx) ) {
6931 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6933 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6934 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6938 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6942 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6947 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6949 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6950 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6954 if(s>1 && IC_TRUE(ifx)) {
6955 pic16_emitpLabel(tlbl->key);
6956 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6960 /* mark the icode as generated */
6965 /* if they are both bit variables */
6966 if (AOP_TYPE(left) == AOP_CRY &&
6967 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6968 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6969 if(AOP_TYPE(right) == AOP_LIT){
6970 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6972 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6973 pic16_emitcode("cpl","c");
6974 } else if(lit == 1L) {
6975 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6977 pic16_emitcode("clr","c");
6979 /* AOP_TYPE(right) == AOP_CRY */
6981 symbol *lbl = newiTempLabel(NULL);
6982 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6983 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6984 pic16_emitcode("cpl","c");
6985 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6988 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6989 pic16_outBitC(result);
6993 genIfxJump (ifx,"c");
6996 /* if the result is used in an arithmetic operation
6997 then put the result in place */
6998 pic16_outBitC(result);
7001 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7002 gencjne(left,right,result,ifx);
7005 gencjne(left,right,newiTempLabel(NULL));
7007 if(IC_TRUE(ifx)->key)
7008 gencjne(left,right,IC_TRUE(ifx)->key);
7010 gencjne(left,right,IC_FALSE(ifx)->key);
7014 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7015 pic16_aopPut(AOP(result),"a",0);
7020 genIfxJump (ifx,"a");
7024 /* if the result is used in an arithmetic operation
7025 then put the result in place */
7027 if (AOP_TYPE(result) != AOP_CRY)
7028 pic16_outAcc(result);
7030 /* leave the result in acc */
7034 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7035 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7036 pic16_freeAsmop(result,NULL,ic,TRUE);
7040 /*-----------------------------------------------------------------*/
7041 /* ifxForOp - returns the icode containing the ifx for operand */
7042 /*-----------------------------------------------------------------*/
7043 static iCode *ifxForOp ( operand *op, iCode *ic )
7047 /* if true symbol then needs to be assigned */
7048 if (IS_TRUE_SYMOP(op))
7051 /* if this has register type condition and
7052 the next instruction is ifx with the same operand
7053 and live to of the operand is upto the ifx only then */
7055 && ic->next->op == IFX
7056 && IC_COND(ic->next)->key == op->key
7057 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7059 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7065 ic->next->op == IFX &&
7066 IC_COND(ic->next)->key == op->key) {
7067 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7072 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7074 ic->next->op == IFX)
7075 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7078 ic->next->op == IFX &&
7079 IC_COND(ic->next)->key == op->key) {
7080 DEBUGpic16_emitcode ("; "," key is okay");
7081 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7082 OP_SYMBOL(op)->liveTo,
7087 /* the code below is completely untested
7088 * it just allows ulong2fs.c compile -- VR */
7091 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7092 __FILE__, __FUNCTION__, __LINE__);
7094 /* if this has register type condition and
7095 the next instruction is ifx with the same operand
7096 and live to of the operand is upto the ifx only then */
7098 ic->next->op == IFX &&
7099 IC_COND(ic->next)->key == op->key &&
7100 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7104 ic->next->op == IFX &&
7105 IC_COND(ic->next)->key == op->key) {
7106 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7110 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7111 __FILE__, __FUNCTION__, __LINE__);
7113 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7118 /*-----------------------------------------------------------------*/
7119 /* genAndOp - for && operation */
7120 /*-----------------------------------------------------------------*/
7121 static void genAndOp (iCode *ic)
7123 operand *left,*right, *result;
7128 /* note here that && operations that are in an
7129 if statement are taken away by backPatchLabels
7130 only those used in arthmetic operations remain */
7131 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7132 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7133 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7135 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7137 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7138 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7139 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7141 /* if both are bit variables */
7142 /* if (AOP_TYPE(left) == AOP_CRY && */
7143 /* AOP_TYPE(right) == AOP_CRY ) { */
7144 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7145 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7146 /* pic16_outBitC(result); */
7148 /* tlbl = newiTempLabel(NULL); */
7149 /* pic16_toBoolean(left); */
7150 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7151 /* pic16_toBoolean(right); */
7152 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7153 /* pic16_outBitAcc(result); */
7156 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7157 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7158 pic16_freeAsmop(result,NULL,ic,TRUE);
7162 /*-----------------------------------------------------------------*/
7163 /* genOrOp - for || operation */
7164 /*-----------------------------------------------------------------*/
7167 modified this code, but it doesn't appear to ever get called
7170 static void genOrOp (iCode *ic)
7172 operand *left,*right, *result;
7177 /* note here that || operations that are in an
7178 if statement are taken away by backPatchLabels
7179 only those used in arthmetic operations remain */
7180 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7181 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7182 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7184 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7186 /* if both are bit variables */
7187 if (AOP_TYPE(left) == AOP_CRY &&
7188 AOP_TYPE(right) == AOP_CRY ) {
7189 pic16_emitcode("clrc","");
7190 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7191 AOP(left)->aopu.aop_dir,
7192 AOP(left)->aopu.aop_dir);
7193 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7194 AOP(right)->aopu.aop_dir,
7195 AOP(right)->aopu.aop_dir);
7196 pic16_emitcode("setc","");
7199 tlbl = newiTempLabel(NULL);
7200 pic16_toBoolean(left);
7202 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7203 pic16_toBoolean(right);
7204 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
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);
7214 /*-----------------------------------------------------------------*/
7215 /* isLiteralBit - test if lit == 2^n */
7216 /*-----------------------------------------------------------------*/
7217 static int isLiteralBit(unsigned long lit)
7219 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7220 0x100L,0x200L,0x400L,0x800L,
7221 0x1000L,0x2000L,0x4000L,0x8000L,
7222 0x10000L,0x20000L,0x40000L,0x80000L,
7223 0x100000L,0x200000L,0x400000L,0x800000L,
7224 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7225 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7229 for(idx = 0; idx < 32; idx++)
7235 /*-----------------------------------------------------------------*/
7236 /* continueIfTrue - */
7237 /*-----------------------------------------------------------------*/
7238 static void continueIfTrue (iCode *ic)
7242 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7246 /*-----------------------------------------------------------------*/
7248 /*-----------------------------------------------------------------*/
7249 static void jumpIfTrue (iCode *ic)
7253 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7257 /*-----------------------------------------------------------------*/
7258 /* jmpTrueOrFalse - */
7259 /*-----------------------------------------------------------------*/
7260 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7262 // ugly but optimized by peephole
7265 symbol *nlbl = newiTempLabel(NULL);
7266 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7267 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7268 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7269 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7271 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7272 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7277 /*-----------------------------------------------------------------*/
7278 /* genAnd - code for and */
7279 /*-----------------------------------------------------------------*/
7280 static void genAnd (iCode *ic, iCode *ifx)
7282 operand *left, *right, *result;
7284 unsigned long lit = 0L;
7290 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7291 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7292 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7294 resolveIfx(&rIfx,ifx);
7296 /* if left is a literal & right is not then exchange them */
7297 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7298 AOP_NEEDSACC(left)) {
7299 operand *tmp = right ;
7304 /* if result = right then exchange them */
7305 if(pic16_sameRegs(AOP(result),AOP(right))){
7306 operand *tmp = right ;
7311 /* if right is bit then exchange them */
7312 if (AOP_TYPE(right) == AOP_CRY &&
7313 AOP_TYPE(left) != AOP_CRY){
7314 operand *tmp = right ;
7318 if(AOP_TYPE(right) == AOP_LIT)
7319 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7321 size = AOP_SIZE(result);
7323 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7326 // result = bit & yy;
7327 if (AOP_TYPE(left) == AOP_CRY){
7328 // c = bit & literal;
7329 if(AOP_TYPE(right) == AOP_LIT){
7331 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7334 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7337 if(size && (AOP_TYPE(result) == AOP_CRY)){
7338 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7341 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7345 pic16_emitcode("clr","c");
7348 if (AOP_TYPE(right) == AOP_CRY){
7350 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7351 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7354 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7356 pic16_emitcode("rrc","a");
7357 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7363 pic16_outBitC(result);
7365 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7366 genIfxJump(ifx, "c");
7370 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7371 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7372 if((AOP_TYPE(right) == AOP_LIT) &&
7373 (AOP_TYPE(result) == AOP_CRY) &&
7374 (AOP_TYPE(left) != AOP_CRY)){
7375 int posbit = isLiteralBit(lit);
7379 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7382 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7388 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7389 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7391 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7392 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7395 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7396 size = AOP_SIZE(left);
7399 int bp = posbit, ofs=0;
7406 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7407 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7411 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7412 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7414 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7421 symbol *tlbl = newiTempLabel(NULL);
7422 int sizel = AOP_SIZE(left);
7428 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7430 /* patch provided by Aaron Colwell */
7431 if((posbit = isLiteralBit(bytelit)) != 0) {
7432 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7433 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7434 (posbit-1),0, PO_GPR_REGISTER));
7436 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7437 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7439 if (bytelit == 0xff) {
7440 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7441 * a peephole could optimize it out -- VR */
7442 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7445 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7448 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7449 pic16_popGetLabel(tlbl->key));
7453 /* old code, left here for reference -- VR 09/2004 */
7454 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7456 if((posbit = isLiteralBit(bytelit)) != 0)
7457 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7459 if(bytelit != 0x0FFL)
7460 pic16_emitcode("anl","a,%s",
7461 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7462 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7468 // bit = left & literal
7471 pic16_emitpLabel(tlbl->key);
7473 // if(left & literal)
7476 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7479 pic16_emitpLabel(tlbl->key);
7484 pic16_outBitC(result);
7488 /* if left is same as result */
7489 if(pic16_sameRegs(AOP(result),AOP(left))){
7491 for(;size--; offset++,lit>>=8) {
7492 if(AOP_TYPE(right) == AOP_LIT){
7493 switch(lit & 0xff) {
7495 /* and'ing with 0 has clears the result */
7496 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7497 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7500 /* and'ing with 0xff is a nop when the result and left are the same */
7505 int p = pic16_my_powof2( (~lit) & 0xff );
7507 /* only one bit is set in the literal, so use a bcf instruction */
7508 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7509 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7512 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7513 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7514 if(know_W != (lit&0xff))
7515 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7517 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7522 if (AOP_TYPE(left) == AOP_ACC) {
7523 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7525 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7526 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7533 // left & result in different registers
7534 if(AOP_TYPE(result) == AOP_CRY){
7536 // if(size), result in bit
7537 // if(!size && ifx), conditional oper: if(left & right)
7538 symbol *tlbl = newiTempLabel(NULL);
7539 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7541 pic16_emitcode("setb","c");
7543 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7544 pic16_emitcode("anl","a,%s",
7545 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7546 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7551 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7552 pic16_outBitC(result);
7554 jmpTrueOrFalse(ifx, tlbl);
7556 for(;(size--);offset++) {
7558 // result = left & right
7559 if(AOP_TYPE(right) == AOP_LIT){
7560 int t = (lit >> (offset*8)) & 0x0FFL;
7563 pic16_emitcode("clrf","%s",
7564 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7565 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7568 pic16_emitcode("movf","%s,w",
7569 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7570 pic16_emitcode("movwf","%s",
7571 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7573 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7576 pic16_emitcode("movlw","0x%x",t);
7577 pic16_emitcode("andwf","%s,w",
7578 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7579 pic16_emitcode("movwf","%s",
7580 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7583 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7584 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7589 if (AOP_TYPE(left) == AOP_ACC) {
7590 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7591 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7593 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7594 pic16_emitcode("andwf","%s,w",
7595 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7596 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7597 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7599 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7600 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7606 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7607 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7608 pic16_freeAsmop(result,NULL,ic,TRUE);
7611 /*-----------------------------------------------------------------*/
7612 /* genOr - code for or */
7613 /*-----------------------------------------------------------------*/
7614 static void genOr (iCode *ic, iCode *ifx)
7616 operand *left, *right, *result;
7618 unsigned long lit = 0L;
7620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7622 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7623 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7624 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7626 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7628 /* if left is a literal & right is not then exchange them */
7629 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7630 AOP_NEEDSACC(left)) {
7631 operand *tmp = right ;
7636 /* if result = right then exchange them */
7637 if(pic16_sameRegs(AOP(result),AOP(right))){
7638 operand *tmp = right ;
7643 /* if right is bit then exchange them */
7644 if (AOP_TYPE(right) == AOP_CRY &&
7645 AOP_TYPE(left) != AOP_CRY){
7646 operand *tmp = right ;
7651 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7653 if(AOP_TYPE(right) == AOP_LIT)
7654 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7656 size = AOP_SIZE(result);
7660 if (AOP_TYPE(left) == AOP_CRY){
7661 if(AOP_TYPE(right) == AOP_LIT){
7662 // c = bit & literal;
7664 // lit != 0 => result = 1
7665 if(AOP_TYPE(result) == AOP_CRY){
7667 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7668 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7669 // AOP(result)->aopu.aop_dir,
7670 // AOP(result)->aopu.aop_dir);
7672 continueIfTrue(ifx);
7676 // lit == 0 => result = left
7677 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7679 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7682 if (AOP_TYPE(right) == AOP_CRY){
7683 if(pic16_sameRegs(AOP(result),AOP(left))){
7685 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7686 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7687 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7689 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7690 AOP(result)->aopu.aop_dir,
7691 AOP(result)->aopu.aop_dir);
7692 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7693 AOP(right)->aopu.aop_dir,
7694 AOP(right)->aopu.aop_dir);
7695 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7696 AOP(result)->aopu.aop_dir,
7697 AOP(result)->aopu.aop_dir);
7699 if( AOP_TYPE(result) == AOP_ACC) {
7700 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7701 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7702 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7707 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7708 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7709 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7710 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7712 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7713 AOP(result)->aopu.aop_dir,
7714 AOP(result)->aopu.aop_dir);
7715 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7716 AOP(right)->aopu.aop_dir,
7717 AOP(right)->aopu.aop_dir);
7718 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7719 AOP(left)->aopu.aop_dir,
7720 AOP(left)->aopu.aop_dir);
7721 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7722 AOP(result)->aopu.aop_dir,
7723 AOP(result)->aopu.aop_dir);
7728 symbol *tlbl = newiTempLabel(NULL);
7729 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7732 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7733 if( AOP_TYPE(right) == AOP_ACC) {
7734 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7736 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7737 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7742 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7743 pic16_emitcode(";XXX setb","c");
7744 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7745 AOP(left)->aopu.aop_dir,tlbl->key+100);
7746 pic16_toBoolean(right);
7747 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7748 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7749 jmpTrueOrFalse(ifx, tlbl);
7753 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7760 pic16_outBitC(result);
7762 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7763 genIfxJump(ifx, "c");
7767 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7768 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7769 if((AOP_TYPE(right) == AOP_LIT) &&
7770 (AOP_TYPE(result) == AOP_CRY) &&
7771 (AOP_TYPE(left) != AOP_CRY)){
7773 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7776 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7778 continueIfTrue(ifx);
7781 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7782 // lit = 0, result = boolean(left)
7784 pic16_emitcode(";XXX setb","c");
7785 pic16_toBoolean(right);
7787 symbol *tlbl = newiTempLabel(NULL);
7788 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7790 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7792 genIfxJump (ifx,"a");
7796 pic16_outBitC(result);
7800 /* if left is same as result */
7801 if(pic16_sameRegs(AOP(result),AOP(left))){
7803 for(;size--; offset++,lit>>=8) {
7804 if(AOP_TYPE(right) == AOP_LIT){
7805 if((lit & 0xff) == 0)
7806 /* or'ing with 0 has no effect */
7809 int p = pic16_my_powof2(lit & 0xff);
7811 /* only one bit is set in the literal, so use a bsf instruction */
7812 pic16_emitpcode(POC_BSF,
7813 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7815 if(know_W != (lit & 0xff))
7816 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7817 know_W = lit & 0xff;
7818 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7823 if (AOP_TYPE(left) == AOP_ACC) {
7824 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7825 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7827 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7828 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7830 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7831 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7837 // left & result in different registers
7838 if(AOP_TYPE(result) == AOP_CRY){
7840 // if(size), result in bit
7841 // if(!size && ifx), conditional oper: if(left | right)
7842 symbol *tlbl = newiTempLabel(NULL);
7843 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7844 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7848 pic16_emitcode(";XXX setb","c");
7850 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7851 pic16_emitcode(";XXX orl","a,%s",
7852 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7853 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7858 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7859 pic16_outBitC(result);
7861 jmpTrueOrFalse(ifx, tlbl);
7862 } else for(;(size--);offset++){
7864 // result = left & right
7865 if(AOP_TYPE(right) == AOP_LIT){
7866 int t = (lit >> (offset*8)) & 0x0FFL;
7869 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7870 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7872 pic16_emitcode("movf","%s,w",
7873 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7874 pic16_emitcode("movwf","%s",
7875 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7878 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7879 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7880 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7882 pic16_emitcode("movlw","0x%x",t);
7883 pic16_emitcode("iorwf","%s,w",
7884 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7885 pic16_emitcode("movwf","%s",
7886 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7892 // faster than result <- left, anl result,right
7893 // and better if result is SFR
7894 if (AOP_TYPE(left) == AOP_ACC) {
7895 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7896 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7899 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7901 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 pic16_emitcode("iorwf","%s,w",
7903 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7906 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7911 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7912 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7913 pic16_freeAsmop(result,NULL,ic,TRUE);
7916 /*-----------------------------------------------------------------*/
7917 /* genXor - code for xclusive or */
7918 /*-----------------------------------------------------------------*/
7919 static void genXor (iCode *ic, iCode *ifx)
7921 operand *left, *right, *result;
7923 unsigned long lit = 0L;
7925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7927 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7928 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7929 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7931 /* if left is a literal & right is not ||
7932 if left needs acc & right does not */
7933 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7934 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7935 operand *tmp = right ;
7940 /* if result = right then exchange them */
7941 if(pic16_sameRegs(AOP(result),AOP(right))){
7942 operand *tmp = right ;
7947 /* if right is bit then exchange them */
7948 if (AOP_TYPE(right) == AOP_CRY &&
7949 AOP_TYPE(left) != AOP_CRY){
7950 operand *tmp = right ;
7954 if(AOP_TYPE(right) == AOP_LIT)
7955 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7957 size = AOP_SIZE(result);
7961 if (AOP_TYPE(left) == AOP_CRY){
7962 if(AOP_TYPE(right) == AOP_LIT){
7963 // c = bit & literal;
7965 // lit>>1 != 0 => result = 1
7966 if(AOP_TYPE(result) == AOP_CRY){
7968 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7969 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7971 continueIfTrue(ifx);
7974 pic16_emitcode("setb","c");
7978 // lit == 0, result = left
7979 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7981 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7983 // lit == 1, result = not(left)
7984 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7985 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7986 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7987 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7990 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7991 pic16_emitcode("cpl","c");
7998 symbol *tlbl = newiTempLabel(NULL);
7999 if (AOP_TYPE(right) == AOP_CRY){
8001 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8004 int sizer = AOP_SIZE(right);
8006 // if val>>1 != 0, result = 1
8007 pic16_emitcode("setb","c");
8009 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8011 // test the msb of the lsb
8012 pic16_emitcode("anl","a,#0xfe");
8013 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8017 pic16_emitcode("rrc","a");
8019 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8020 pic16_emitcode("cpl","c");
8021 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8026 pic16_outBitC(result);
8028 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8029 genIfxJump(ifx, "c");
8033 if(pic16_sameRegs(AOP(result),AOP(left))){
8034 /* if left is same as result */
8035 for(;size--; offset++) {
8036 if(AOP_TYPE(right) == AOP_LIT){
8037 int t = (lit >> (offset*8)) & 0x0FFL;
8041 if (IS_AOP_PREG(left)) {
8042 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8043 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8044 pic16_aopPut(AOP(result),"a",offset);
8046 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8047 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8048 pic16_emitcode("xrl","%s,%s",
8049 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8050 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8053 if (AOP_TYPE(left) == AOP_ACC)
8054 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8056 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8057 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8059 if (IS_AOP_PREG(left)) {
8060 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8061 pic16_aopPut(AOP(result),"a",offset);
8063 pic16_emitcode("xrl","%s,a",
8064 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8070 // left & result in different registers
8071 if(AOP_TYPE(result) == AOP_CRY){
8073 // if(size), result in bit
8074 // if(!size && ifx), conditional oper: if(left ^ right)
8075 symbol *tlbl = newiTempLabel(NULL);
8076 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8078 pic16_emitcode("setb","c");
8080 if((AOP_TYPE(right) == AOP_LIT) &&
8081 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8082 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8084 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8085 pic16_emitcode("xrl","a,%s",
8086 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8088 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8093 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8094 pic16_outBitC(result);
8096 jmpTrueOrFalse(ifx, tlbl);
8097 } else for(;(size--);offset++){
8099 // result = left & right
8100 if(AOP_TYPE(right) == AOP_LIT){
8101 int t = (lit >> (offset*8)) & 0x0FFL;
8104 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8105 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8106 pic16_emitcode("movf","%s,w",
8107 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8108 pic16_emitcode("movwf","%s",
8109 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8112 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8113 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8114 pic16_emitcode("comf","%s,w",
8115 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8116 pic16_emitcode("movwf","%s",
8117 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8120 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8121 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8122 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8123 pic16_emitcode("movlw","0x%x",t);
8124 pic16_emitcode("xorwf","%s,w",
8125 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8126 pic16_emitcode("movwf","%s",
8127 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8133 // faster than result <- left, anl result,right
8134 // and better if result is SFR
8135 if (AOP_TYPE(left) == AOP_ACC) {
8136 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8137 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8139 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8140 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8141 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8142 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8144 if ( AOP_TYPE(result) != AOP_ACC){
8145 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8146 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8152 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8153 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8154 pic16_freeAsmop(result,NULL,ic,TRUE);
8157 /*-----------------------------------------------------------------*/
8158 /* genInline - write the inline code out */
8159 /*-----------------------------------------------------------------*/
8160 static void genInline (iCode *ic)
8162 char *buffer, *bp, *bp1;
8164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8166 _G.inLine += (!options.asmpeep);
8168 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8169 strcpy(buffer,IC_INLINE(ic));
8171 while((bp1=strstr(bp, "\\n"))) {
8179 /* This is an experimental code for #pragma inline
8180 and is temporarily disabled for 2.5.0 release */
8188 cbuf = Safe_strdup(buffer);
8189 cblen = strlen(buffer)+1;
8190 memset(cbuf, 0, cblen);
8195 if(*bp != '%')*bp1++ = *bp++;
8201 if(i>elementsInSet(asmInlineMap))break;
8204 s = indexSet(asmInlineMap, i);
8205 DEBUGpc("searching symbol s = `%s'", s);
8206 sym = findSym(SymbolTab, NULL, s);
8209 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8211 strcat(bp1, sym->rname);
8217 if(strlen(bp1) > cblen - 16) {
8218 int i = strlen(cbuf);
8220 cbuf = realloc(cbuf, cblen);
8221 memset(cbuf+i, 0, 50);
8227 buffer = Safe_strdup( cbuf );
8234 /* emit each line as a code */
8240 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8248 /* print label, use this special format with NULL directive
8249 * to denote that the argument should not be indented with tab */
8250 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8253 /* advance to end of line (prevent splitting of comments at ':' */
8254 while (*bp && *bp != '\n') {
8262 if ((bp1 != bp) && *bp1)
8263 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8268 _G.inLine -= (!options.asmpeep);
8271 /*-----------------------------------------------------------------*/
8272 /* genRRC - rotate right with carry */
8273 /*-----------------------------------------------------------------*/
8274 static void genRRC (iCode *ic)
8276 operand *left , *result ;
8277 int size, offset = 0, same;
8279 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8281 /* rotate right with carry */
8283 result=IC_RESULT(ic);
8284 pic16_aopOp (left,ic,FALSE);
8285 pic16_aopOp (result,ic,TRUE);
8287 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8289 same = pic16_sameRegs(AOP(result),AOP(left));
8291 size = AOP_SIZE(result);
8293 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8295 /* get the lsb and put it into the carry */
8296 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8303 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8305 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8306 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8312 pic16_freeAsmop(left,NULL,ic,TRUE);
8313 pic16_freeAsmop(result,NULL,ic,TRUE);
8316 /*-----------------------------------------------------------------*/
8317 /* genRLC - generate code for rotate left with carry */
8318 /*-----------------------------------------------------------------*/
8319 static void genRLC (iCode *ic)
8321 operand *left , *result ;
8322 int size, offset = 0;
8325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8326 /* rotate right with carry */
8328 result=IC_RESULT(ic);
8329 pic16_aopOp (left,ic,FALSE);
8330 pic16_aopOp (result,ic,TRUE);
8332 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8334 same = pic16_sameRegs(AOP(result),AOP(left));
8336 /* move it to the result */
8337 size = AOP_SIZE(result);
8339 /* get the msb and put it into the carry */
8340 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8347 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8349 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8350 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8357 pic16_freeAsmop(left,NULL,ic,TRUE);
8358 pic16_freeAsmop(result,NULL,ic,TRUE);
8362 /* gpasm can get the highest order bit with HIGH/UPPER
8363 * so the following probably is not needed -- VR */
8365 /*-----------------------------------------------------------------*/
8366 /* genGetHbit - generates code get highest order bit */
8367 /*-----------------------------------------------------------------*/
8368 static void genGetHbit (iCode *ic)
8370 operand *left, *result;
8372 result=IC_RESULT(ic);
8373 pic16_aopOp (left,ic,FALSE);
8374 pic16_aopOp (result,ic,FALSE);
8376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8377 /* get the highest order byte into a */
8378 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8379 if(AOP_TYPE(result) == AOP_CRY){
8380 pic16_emitcode("rlc","a");
8381 pic16_outBitC(result);
8384 pic16_emitcode("rl","a");
8385 pic16_emitcode("anl","a,#0x01");
8386 pic16_outAcc(result);
8390 pic16_freeAsmop(left,NULL,ic,TRUE);
8391 pic16_freeAsmop(result,NULL,ic,TRUE);
8395 /*-----------------------------------------------------------------*/
8396 /* AccRol - rotate left accumulator by known count */
8397 /*-----------------------------------------------------------------*/
8398 static void AccRol (int shCount)
8400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8401 shCount &= 0x0007; // shCount : 0..7
8406 pic16_emitcode("rl","a");
8409 pic16_emitcode("rl","a");
8410 pic16_emitcode("rl","a");
8413 pic16_emitcode("swap","a");
8414 pic16_emitcode("rr","a");
8417 pic16_emitcode("swap","a");
8420 pic16_emitcode("swap","a");
8421 pic16_emitcode("rl","a");
8424 pic16_emitcode("rr","a");
8425 pic16_emitcode("rr","a");
8428 pic16_emitcode("rr","a");
8434 /*-----------------------------------------------------------------*/
8435 /* AccLsh - left shift accumulator by known count */
8436 /*-----------------------------------------------------------------*/
8437 static void AccLsh (int shCount, int doMask)
8439 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8445 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8449 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8452 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8453 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8456 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8459 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8460 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8471 /* no masking is required in genPackBits */
8472 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8476 /*-----------------------------------------------------------------*/
8477 /* AccRsh - right shift accumulator by known count */
8478 /*-----------------------------------------------------------------*/
8479 static void AccRsh (int shCount, int andmask)
8481 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8486 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8489 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8490 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8493 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8494 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8497 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8500 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8501 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8504 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8515 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8519 /*-----------------------------------------------------------------*/
8520 /* AccSRsh - signed right shift accumulator by known count */
8521 /*-----------------------------------------------------------------*/
8522 static void AccSRsh (int shCount)
8525 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8528 pic16_emitcode("mov","c,acc.7");
8529 pic16_emitcode("rrc","a");
8530 } else if(shCount == 2){
8531 pic16_emitcode("mov","c,acc.7");
8532 pic16_emitcode("rrc","a");
8533 pic16_emitcode("mov","c,acc.7");
8534 pic16_emitcode("rrc","a");
8536 tlbl = newiTempLabel(NULL);
8537 /* rotate right accumulator */
8538 AccRol(8 - shCount);
8539 /* and kill the higher order bits */
8540 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8541 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8542 pic16_emitcode("orl","a,#0x%02x",
8543 (unsigned char)~SRMask[shCount]);
8544 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8550 /*-----------------------------------------------------------------*/
8551 /* shiftR1Left2Result - shift right one byte from left to result */
8552 /*-----------------------------------------------------------------*/
8553 static void shiftR1Left2ResultSigned (operand *left, int offl,
8554 operand *result, int offr,
8559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8561 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8565 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8567 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8569 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8576 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8578 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8580 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8581 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8583 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8584 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8590 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8592 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8593 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8596 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8597 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8598 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8600 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8601 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8603 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8607 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8608 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8609 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8610 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8611 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8615 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8617 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8618 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8620 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8621 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8622 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8623 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8629 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8630 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8631 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8632 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8633 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8634 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8636 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8637 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8638 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8639 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8640 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8646 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8647 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8648 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8649 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8653 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8661 /*-----------------------------------------------------------------*/
8662 /* shiftR1Left2Result - shift right one byte from left to result */
8663 /*-----------------------------------------------------------------*/
8664 static void shiftR1Left2Result (operand *left, int offl,
8665 operand *result, int offr,
8666 int shCount, int sign)
8670 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8672 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8674 /* Copy the msb into the carry if signed. */
8676 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8686 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8688 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8689 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8698 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8706 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8709 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8713 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8715 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8719 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8720 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8721 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8725 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8726 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8729 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8734 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8735 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8736 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8737 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8738 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8743 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8744 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8745 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8754 /*-----------------------------------------------------------------*/
8755 /* shiftL1Left2Result - shift left one byte from left to result */
8756 /*-----------------------------------------------------------------*/
8757 static void shiftL1Left2Result (operand *left, int offl,
8758 operand *result, int offr, int shCount)
8763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8765 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8766 DEBUGpic16_emitcode ("; ***","same = %d",same);
8767 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8769 /* shift left accumulator */
8770 //AccLsh(shCount, 1); // don't comment out just yet...
8771 // pic16_aopPut(AOP(result),"a",offr);
8775 /* Shift left 1 bit position */
8776 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8778 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8780 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8786 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8787 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8792 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8793 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8795 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8798 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8799 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8800 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8803 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8804 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8805 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8806 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8810 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8811 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8812 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8813 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8816 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8817 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8818 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8822 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8827 /*-----------------------------------------------------------------*/
8828 /* movLeft2Result - move byte from left to result */
8829 /*-----------------------------------------------------------------*/
8830 static void movLeft2Result (operand *left, int offl,
8831 operand *result, int offr)
8834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8835 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8836 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8838 if (*l == '@' && (IS_AOP_PREG(result))) {
8839 pic16_emitcode("mov","a,%s",l);
8840 pic16_aopPut(AOP(result),"a",offr);
8842 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8848 /*-----------------------------------------------------------------*/
8849 /* shiftL2Left2Result - shift left two bytes from left to result */
8850 /*-----------------------------------------------------------------*/
8851 static void shiftL2Left2Result (operand *left, int offl,
8852 operand *result, int offr, int shCount)
8854 int same = pic16_sameRegs(AOP(result), AOP(left));
8857 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8859 if (same && (offl != offr)) { // shift bytes
8862 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8863 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8865 } else { // just treat as different later on
8878 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8884 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8892 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8893 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8894 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8895 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8896 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8899 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8900 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8904 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8905 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8907 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8909 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8910 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8911 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8912 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8916 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8917 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8918 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8919 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8920 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8930 /* note, use a mov/add for the shift since the mov has a
8931 chance of getting optimized out */
8932 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8934 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8940 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8948 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8953 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8958 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8963 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8964 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8966 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8979 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8980 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8987 /*-----------------------------------------------------------------*/
8988 /* shiftR2Left2Result - shift right two bytes from left to result */
8989 /*-----------------------------------------------------------------*/
8990 static void shiftR2Left2Result (operand *left, int offl,
8991 operand *result, int offr,
8992 int shCount, int sign)
8994 int same = pic16_sameRegs(AOP(result), AOP(left));
8996 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8998 if (same && (offl != offr)) { // shift right bytes
9001 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9002 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9004 } else { // just treat as different later on
9016 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9021 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9025 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9026 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9027 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9035 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9036 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9044 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9048 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9049 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9050 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9052 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9053 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9056 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9058 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9059 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9060 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9064 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9065 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9070 pic16_emitpcode(POC_BTFSC,
9071 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9072 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9084 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9085 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9088 pic16_emitpcode(POC_BTFSC,
9089 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9090 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9092 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9093 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9094 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9095 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9098 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9099 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9100 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9101 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9104 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9106 pic16_emitpcode(POC_BTFSC,
9107 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9108 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9110 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9111 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9119 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9120 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9124 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9126 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9131 /*-----------------------------------------------------------------*/
9132 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9133 /*-----------------------------------------------------------------*/
9134 static void shiftLLeftOrResult (operand *left, int offl,
9135 operand *result, int offr, int shCount)
9137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9139 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9140 /* shift left accumulator */
9142 /* or with result */
9143 /* back to result */
9144 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9147 /*-----------------------------------------------------------------*/
9148 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9149 /*-----------------------------------------------------------------*/
9150 static void shiftRLeftOrResult (operand *left, int offl,
9151 operand *result, int offr, int shCount)
9153 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9155 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9156 /* shift right accumulator */
9158 /* or with result */
9159 /* back to result */
9160 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9163 /*-----------------------------------------------------------------*/
9164 /* genlshOne - left shift a one byte quantity by known count */
9165 /*-----------------------------------------------------------------*/
9166 static void genlshOne (operand *result, operand *left, int shCount)
9168 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9169 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9172 /*-----------------------------------------------------------------*/
9173 /* genlshTwo - left shift two bytes by known amount != 0 */
9174 /*-----------------------------------------------------------------*/
9175 static void genlshTwo (operand *result,operand *left, int shCount)
9179 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9180 size = pic16_getDataSize(result);
9182 /* if shCount >= 8 */
9188 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9190 movLeft2Result(left, LSB, result, MSB16);
9192 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9195 /* 1 <= shCount <= 7 */
9198 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9200 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9204 /*-----------------------------------------------------------------*/
9205 /* shiftLLong - shift left one long from left to result */
9206 /* offr = LSB or MSB16 */
9207 /*-----------------------------------------------------------------*/
9208 static void shiftLLong (operand *left, operand *result, int offr )
9210 int size = AOP_SIZE(result);
9211 int same = pic16_sameRegs(AOP(left),AOP(result));
9214 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9216 if (same && (offr == MSB16)) { //shift one byte
9217 for(i=size-1;i>=MSB16;i--) {
9218 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9219 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9222 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9225 if (size > LSB+offr ){
9227 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9229 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9230 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9234 if(size > MSB16+offr){
9236 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9238 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9239 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9243 if(size > MSB24+offr){
9245 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9247 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9248 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9252 if(size > MSB32+offr){
9254 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9256 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9257 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9261 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9265 /*-----------------------------------------------------------------*/
9266 /* genlshFour - shift four byte by a known amount != 0 */
9267 /*-----------------------------------------------------------------*/
9268 static void genlshFour (operand *result, operand *left, int shCount)
9272 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9273 size = AOP_SIZE(result);
9275 /* if shifting more that 3 bytes */
9276 if (shCount >= 24 ) {
9279 /* lowest order of left goes to the highest
9280 order of the destination */
9281 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9283 movLeft2Result(left, LSB, result, MSB32);
9285 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9286 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9287 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9292 /* more than two bytes */
9293 else if ( shCount >= 16 ) {
9294 /* lower order two bytes goes to higher order two bytes */
9296 /* if some more remaining */
9298 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9300 movLeft2Result(left, MSB16, result, MSB32);
9301 movLeft2Result(left, LSB, result, MSB24);
9303 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9304 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9308 /* if more than 1 byte */
9309 else if ( shCount >= 8 ) {
9310 /* lower order three bytes goes to higher order three bytes */
9314 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9316 movLeft2Result(left, LSB, result, MSB16);
9318 else{ /* size = 4 */
9320 movLeft2Result(left, MSB24, result, MSB32);
9321 movLeft2Result(left, MSB16, result, MSB24);
9322 movLeft2Result(left, LSB, result, MSB16);
9323 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9325 else if(shCount == 1)
9326 shiftLLong(left, result, MSB16);
9328 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9329 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9330 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9331 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9336 /* 1 <= shCount <= 7 */
9337 else if(shCount <= 3)
9339 shiftLLong(left, result, LSB);
9340 while(--shCount >= 1)
9341 shiftLLong(result, result, LSB);
9343 /* 3 <= shCount <= 7, optimize */
9345 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9346 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9347 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9351 /*-----------------------------------------------------------------*/
9352 /* genLeftShiftLiteral - left shifting by known count */
9353 /*-----------------------------------------------------------------*/
9354 void pic16_genLeftShiftLiteral (operand *left,
9359 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9363 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9364 pic16_freeAsmop(right,NULL,ic,TRUE);
9366 pic16_aopOp(left,ic,FALSE);
9367 pic16_aopOp(result,ic,TRUE);
9369 size = getSize(operandType(result));
9372 pic16_emitcode("; shift left ","result %d, left %d",size,
9376 /* I suppose that the left size >= result size */
9379 movLeft2Result(left, size, result, size);
9383 else if(shCount >= (size * 8))
9385 pic16_aopPut(AOP(result),zero,size);
9389 genlshOne (result,left,shCount);
9394 genlshTwo (result,left,shCount);
9398 genlshFour (result,left,shCount);
9402 pic16_freeAsmop(left,NULL,ic,TRUE);
9403 pic16_freeAsmop(result,NULL,ic,TRUE);
9406 /*-----------------------------------------------------------------*
9407 * genMultiAsm - repeat assembly instruction for size of register.
9408 * if endian == 1, then the high byte (i.e base address + size of
9409 * register) is used first else the low byte is used first;
9410 *-----------------------------------------------------------------*/
9411 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9416 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9429 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9435 #if !(USE_GENERIC_SIGNED_SHIFT)
9436 /*-----------------------------------------------------------------*/
9437 /* genLeftShift - generates code for left shifting */
9438 /*-----------------------------------------------------------------*/
9439 static void genLeftShift (iCode *ic)
9441 operand *left,*right, *result;
9444 symbol *tlbl , *tlbl1;
9447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9449 right = IC_RIGHT(ic);
9451 result = IC_RESULT(ic);
9453 pic16_aopOp(right,ic,FALSE);
9455 /* if the shift count is known then do it
9456 as efficiently as possible */
9457 if (AOP_TYPE(right) == AOP_LIT) {
9458 pic16_genLeftShiftLiteral (left,right,result,ic);
9462 /* shift count is unknown then we have to form
9463 * a loop. Get the loop count in WREG : Note: we take
9464 * only the lower order byte since shifting
9465 * more than 32 bits make no sense anyway, ( the
9466 * largest size of an object can be only 32 bits ) */
9468 pic16_aopOp(left,ic,FALSE);
9469 pic16_aopOp(result,ic,FALSE);
9471 /* now move the left to the result if they are not the
9472 * same, and if size > 1,
9473 * and if right is not same to result (!!!) -- VR */
9474 if (!pic16_sameRegs(AOP(left),AOP(result))
9475 && (AOP_SIZE(result) > 1)) {
9477 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9479 size = AOP_SIZE(result);
9484 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9485 if (*l == '@' && (IS_AOP_PREG(result))) {
9487 pic16_emitcode("mov","a,%s",l);
9488 pic16_aopPut(AOP(result),"a",offset);
9492 /* we don't know if left is a literal or a register, take care -- VR */
9493 pic16_mov2f(AOP(result), AOP(left), offset);
9499 size = AOP_SIZE(result);
9501 /* if it is only one byte then */
9503 if(optimized_for_speed) {
9504 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9505 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9506 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9508 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9509 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9510 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9511 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9512 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9513 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9514 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9515 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9518 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9520 tlbl = newiTempLabel(NULL);
9523 /* this is already done, why change it? */
9524 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9525 pic16_mov2f(AOP(result), AOP(left), 0);
9529 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9530 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9531 pic16_emitpLabel(tlbl->key);
9532 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9533 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9535 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9540 if (pic16_sameRegs(AOP(left),AOP(result))) {
9542 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9544 tlbl = newiTempLabel(NULL);
9545 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9546 genMultiAsm(POC_RRCF, result, size,1);
9547 pic16_emitpLabel(tlbl->key);
9548 genMultiAsm(POC_RLCF, result, size,0);
9549 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9551 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9555 //tlbl = newiTempLabel(NULL);
9557 //tlbl1 = newiTempLabel(NULL);
9559 //reAdjustPreg(AOP(result));
9561 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9562 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9563 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9565 //pic16_emitcode("add","a,acc");
9566 //pic16_aopPut(AOP(result),"a",offset++);
9568 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9570 // pic16_emitcode("rlc","a");
9571 // pic16_aopPut(AOP(result),"a",offset++);
9573 //reAdjustPreg(AOP(result));
9575 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9576 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9579 tlbl = newiTempLabel(NULL);
9580 tlbl1= newiTempLabel(NULL);
9582 size = AOP_SIZE(result);
9585 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9587 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9589 /* offset should be 0, 1 or 3 */
9591 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9593 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9595 pic16_emitpcode(POC_MOVWF, pctemp);
9598 pic16_emitpLabel(tlbl->key);
9601 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9603 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9605 pic16_emitpcode(POC_DECFSZ, pctemp);
9606 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9607 pic16_emitpLabel(tlbl1->key);
9609 pic16_popReleaseTempReg(pctemp,1);
9613 pic16_freeAsmop (right,NULL,ic,TRUE);
9614 pic16_freeAsmop(left,NULL,ic,TRUE);
9615 pic16_freeAsmop(result,NULL,ic,TRUE);
9621 #error old code (left here for reference)
9622 /*-----------------------------------------------------------------*/
9623 /* genLeftShift - generates code for left shifting */
9624 /*-----------------------------------------------------------------*/
9625 static void genLeftShift (iCode *ic)
9627 operand *left,*right, *result;
9630 symbol *tlbl , *tlbl1;
9633 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9635 right = IC_RIGHT(ic);
9637 result = IC_RESULT(ic);
9639 pic16_aopOp(right,ic,FALSE);
9641 /* if the shift count is known then do it
9642 as efficiently as possible */
9643 if (AOP_TYPE(right) == AOP_LIT) {
9644 pic16_genLeftShiftLiteral (left,right,result,ic);
9648 /* shift count is unknown then we have to form
9649 a loop get the loop count in B : Note: we take
9650 only the lower order byte since shifting
9651 more that 32 bits make no sense anyway, ( the
9652 largest size of an object can be only 32 bits ) */
9655 pic16_aopOp(left,ic,FALSE);
9656 pic16_aopOp(result,ic,FALSE);
9658 /* now move the left to the result if they are not the
9660 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9661 AOP_SIZE(result) > 1) {
9663 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9665 size = AOP_SIZE(result);
9668 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9669 if (*l == '@' && (IS_AOP_PREG(result))) {
9671 pic16_emitcode("mov","a,%s",l);
9672 pic16_aopPut(AOP(result),"a",offset);
9675 /* we don't know if left is a literal or a register, take care -- VR */
9676 pic16_mov2f(AOP(result), AOP(left), offset);
9682 size = AOP_SIZE(result);
9684 /* if it is only one byte then */
9686 if(optimized_for_speed) {
9687 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9688 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9689 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9690 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9692 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9693 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9694 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9695 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9696 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9697 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9698 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9703 tlbl = newiTempLabel(NULL);
9704 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9705 pic16_mov2f(AOP(result), AOP(left), 0);
9707 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9708 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9711 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9712 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9713 pic16_emitpLabel(tlbl->key);
9714 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9715 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9717 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9722 if (pic16_sameRegs(AOP(left),AOP(result))) {
9724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9726 tlbl = newiTempLabel(NULL);
9727 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9728 genMultiAsm(POC_RRCF, result, size,1);
9729 pic16_emitpLabel(tlbl->key);
9730 genMultiAsm(POC_RLCF, result, size,0);
9731 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9733 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9737 //tlbl = newiTempLabel(NULL);
9739 //tlbl1 = newiTempLabel(NULL);
9741 //reAdjustPreg(AOP(result));
9743 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9744 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9745 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9747 //pic16_emitcode("add","a,acc");
9748 //pic16_aopPut(AOP(result),"a",offset++);
9750 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9752 // pic16_emitcode("rlc","a");
9753 // pic16_aopPut(AOP(result),"a",offset++);
9755 //reAdjustPreg(AOP(result));
9757 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9758 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9761 tlbl = newiTempLabel(NULL);
9762 tlbl1= newiTempLabel(NULL);
9764 size = AOP_SIZE(result);
9767 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9769 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9771 /* offset should be 0, 1 or 3 */
9773 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9775 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9777 pic16_emitpcode(POC_MOVWF, pctemp);
9780 pic16_emitpLabel(tlbl->key);
9783 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9787 pic16_emitpcode(POC_DECFSZ, pctemp);
9788 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9789 pic16_emitpLabel(tlbl1->key);
9791 pic16_popReleaseTempReg(pctemp,1);
9795 pic16_freeAsmop (right,NULL,ic,TRUE);
9796 pic16_freeAsmop(left,NULL,ic,TRUE);
9797 pic16_freeAsmop(result,NULL,ic,TRUE);
9801 /*-----------------------------------------------------------------*/
9802 /* genrshOne - right shift a one byte quantity by known count */
9803 /*-----------------------------------------------------------------*/
9804 static void genrshOne (operand *result, operand *left,
9805 int shCount, int sign)
9807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9808 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9811 /*-----------------------------------------------------------------*/
9812 /* genrshTwo - right shift two bytes by known amount != 0 */
9813 /*-----------------------------------------------------------------*/
9814 static void genrshTwo (operand *result,operand *left,
9815 int shCount, int sign)
9817 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9818 /* if shCount >= 8 */
9822 shiftR1Left2Result(left, MSB16, result, LSB,
9825 movLeft2Result(left, MSB16, result, LSB);
9827 pic16_addSign (result, 1, sign);
9830 /* 1 <= shCount <= 7 */
9832 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9835 /*-----------------------------------------------------------------*/
9836 /* shiftRLong - shift right one long from left to result */
9837 /* offl = LSB or MSB16 */
9838 /*-----------------------------------------------------------------*/
9839 static void shiftRLong (operand *left, int offl,
9840 operand *result, int sign)
9842 int size = AOP_SIZE(result);
9843 int same = pic16_sameRegs(AOP(left),AOP(result));
9845 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9847 if (same && (offl == MSB16)) { //shift one byte right
9848 for(i=MSB16;i<size;i++) {
9849 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9850 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9855 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9861 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9863 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9864 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9868 /* add sign of "a" */
9869 pic16_addSign(result, MSB32, sign);
9873 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9875 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9876 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9880 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9882 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9883 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9887 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9890 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9891 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9896 /*-----------------------------------------------------------------*/
9897 /* genrshFour - shift four byte by a known amount != 0 */
9898 /*-----------------------------------------------------------------*/
9899 static void genrshFour (operand *result, operand *left,
9900 int shCount, int sign)
9902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9903 /* if shifting more that 3 bytes */
9904 if(shCount >= 24 ) {
9907 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9909 movLeft2Result(left, MSB32, result, LSB);
9911 pic16_addSign(result, MSB16, sign);
9913 else if(shCount >= 16){
9916 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9918 movLeft2Result(left, MSB24, result, LSB);
9919 movLeft2Result(left, MSB32, result, MSB16);
9921 pic16_addSign(result, MSB24, sign);
9923 else if(shCount >= 8){
9926 shiftRLong(left, MSB16, result, sign);
9927 else if(shCount == 0){
9928 movLeft2Result(left, MSB16, result, LSB);
9929 movLeft2Result(left, MSB24, result, MSB16);
9930 movLeft2Result(left, MSB32, result, MSB24);
9931 pic16_addSign(result, MSB32, sign);
9933 else{ //shcount >= 2
9934 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9935 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9936 /* the last shift is signed */
9937 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9938 pic16_addSign(result, MSB32, sign);
9941 else{ /* 1 <= shCount <= 7 */
9943 shiftRLong(left, LSB, result, sign);
9945 shiftRLong(result, LSB, result, sign);
9948 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9949 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9950 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9955 /*-----------------------------------------------------------------*/
9956 /* genRightShiftLiteral - right shifting by known count */
9957 /*-----------------------------------------------------------------*/
9958 static void genRightShiftLiteral (operand *left,
9964 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9967 pic16_freeAsmop(right,NULL,ic,TRUE);
9969 pic16_aopOp(left,ic,FALSE);
9970 pic16_aopOp(result,ic,TRUE);
9972 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9975 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9979 lsize = pic16_getDataSize(left);
9980 res_size = pic16_getDataSize(result);
9981 /* test the LEFT size !!! */
9983 /* I suppose that the left size >= result size */
9985 assert (res_size <= lsize);
9986 while (res_size--) {
9987 pic16_mov2f (AOP(result), AOP(left), res_size);
9991 else if(shCount >= (lsize * 8)){
9994 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9996 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9997 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10002 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10003 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10004 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10011 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10016 switch (res_size) {
10018 genrshOne (result,left,shCount,sign);
10022 genrshTwo (result,left,shCount,sign);
10026 genrshFour (result,left,shCount,sign);
10034 pic16_freeAsmop(left,NULL,ic,TRUE);
10035 pic16_freeAsmop(result,NULL,ic,TRUE);
10038 #if !(USE_GENERIC_SIGNED_SHIFT)
10039 /*-----------------------------------------------------------------*/
10040 /* genSignedRightShift - right shift of signed number */
10041 /*-----------------------------------------------------------------*/
10042 static void genSignedRightShift (iCode *ic)
10044 operand *right, *left, *result;
10047 symbol *tlbl, *tlbl1 ;
10050 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10052 /* we do it the hard way put the shift count in b
10053 and loop thru preserving the sign */
10054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10056 right = IC_RIGHT(ic);
10057 left = IC_LEFT(ic);
10058 result = IC_RESULT(ic);
10060 pic16_aopOp(right,ic,FALSE);
10061 pic16_aopOp(left,ic,FALSE);
10062 pic16_aopOp(result,ic,FALSE);
10065 if ( AOP_TYPE(right) == AOP_LIT) {
10066 genRightShiftLiteral (left,right,result,ic,1);
10069 /* shift count is unknown then we have to form
10070 a loop get the loop count in B : Note: we take
10071 only the lower order byte since shifting
10072 more that 32 bits make no sense anyway, ( the
10073 largest size of an object can be only 32 bits ) */
10075 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10076 //pic16_emitcode("inc","b");
10077 //pic16_freeAsmop (right,NULL,ic,TRUE);
10078 //pic16_aopOp(left,ic,FALSE);
10079 //pic16_aopOp(result,ic,FALSE);
10081 /* now move the left to the result if they are not the
10083 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10084 AOP_SIZE(result) > 1) {
10086 size = AOP_SIZE(result);
10090 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10091 if (*l == '@' && IS_AOP_PREG(result)) {
10093 pic16_emitcode("mov","a,%s",l);
10094 pic16_aopPut(AOP(result),"a",offset);
10096 pic16_aopPut(AOP(result),l,offset);
10098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10099 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10105 /* mov the highest order bit to OVR */
10106 tlbl = newiTempLabel(NULL);
10107 tlbl1= newiTempLabel(NULL);
10109 size = AOP_SIZE(result);
10112 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10114 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10116 /* offset should be 0, 1 or 3 */
10117 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10119 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10121 pic16_emitpcode(POC_MOVWF, pctemp);
10124 pic16_emitpLabel(tlbl->key);
10126 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10127 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10130 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10133 pic16_emitpcode(POC_DECFSZ, pctemp);
10134 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10135 pic16_emitpLabel(tlbl1->key);
10137 pic16_popReleaseTempReg(pctemp,1);
10139 size = AOP_SIZE(result);
10141 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10142 pic16_emitcode("rlc","a");
10143 pic16_emitcode("mov","ov,c");
10144 /* if it is only one byte then */
10146 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10148 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10149 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10150 pic16_emitcode("mov","c,ov");
10151 pic16_emitcode("rrc","a");
10152 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10153 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10154 pic16_aopPut(AOP(result),"a",0);
10158 reAdjustPreg(AOP(result));
10159 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10160 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10161 pic16_emitcode("mov","c,ov");
10163 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10165 pic16_emitcode("rrc","a");
10166 pic16_aopPut(AOP(result),"a",offset--);
10168 reAdjustPreg(AOP(result));
10169 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10170 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10175 pic16_freeAsmop(left,NULL,ic,TRUE);
10176 pic16_freeAsmop(result,NULL,ic,TRUE);
10177 pic16_freeAsmop(right,NULL,ic,TRUE);
10181 #if !(USE_GENERIC_SIGNED_SHIFT)
10182 #warning This implementation of genRightShift() is incomplete!
10183 /*-----------------------------------------------------------------*/
10184 /* genRightShift - generate code for right shifting */
10185 /*-----------------------------------------------------------------*/
10186 static void genRightShift (iCode *ic)
10188 operand *right, *left, *result;
10192 symbol *tlbl, *tlbl1 ;
10194 /* if signed then we do it the hard way preserve the
10195 sign bit moving it inwards */
10196 letype = getSpec(operandType(IC_LEFT(ic)));
10197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10199 if (!SPEC_USIGN(letype)) {
10200 genSignedRightShift (ic);
10204 /* signed & unsigned types are treated the same : i.e. the
10205 signed is NOT propagated inwards : quoting from the
10206 ANSI - standard : "for E1 >> E2, is equivalent to division
10207 by 2**E2 if unsigned or if it has a non-negative value,
10208 otherwise the result is implementation defined ", MY definition
10209 is that the sign does not get propagated */
10211 right = IC_RIGHT(ic);
10212 left = IC_LEFT(ic);
10213 result = IC_RESULT(ic);
10215 pic16_aopOp(right,ic,FALSE);
10217 /* if the shift count is known then do it
10218 as efficiently as possible */
10219 if (AOP_TYPE(right) == AOP_LIT) {
10220 genRightShiftLiteral (left,right,result,ic, 0);
10224 /* shift count is unknown then we have to form
10225 a loop get the loop count in B : Note: we take
10226 only the lower order byte since shifting
10227 more that 32 bits make no sense anyway, ( the
10228 largest size of an object can be only 32 bits ) */
10230 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10231 pic16_emitcode("inc","b");
10232 pic16_aopOp(left,ic,FALSE);
10233 pic16_aopOp(result,ic,FALSE);
10235 /* now move the left to the result if they are not the
10237 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10238 AOP_SIZE(result) > 1) {
10240 size = AOP_SIZE(result);
10243 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10244 if (*l == '@' && IS_AOP_PREG(result)) {
10246 pic16_emitcode("mov","a,%s",l);
10247 pic16_aopPut(AOP(result),"a",offset);
10249 pic16_aopPut(AOP(result),l,offset);
10254 tlbl = newiTempLabel(NULL);
10255 tlbl1= newiTempLabel(NULL);
10256 size = AOP_SIZE(result);
10259 /* if it is only one byte then */
10262 tlbl = newiTempLabel(NULL);
10263 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10264 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10268 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10269 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10270 pic16_emitpLabel(tlbl->key);
10271 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10272 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10274 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10279 reAdjustPreg(AOP(result));
10280 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10281 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10284 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10286 pic16_emitcode("rrc","a");
10287 pic16_aopPut(AOP(result),"a",offset--);
10289 reAdjustPreg(AOP(result));
10291 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10292 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10295 pic16_freeAsmop(left,NULL,ic,TRUE);
10296 pic16_freeAsmop (right,NULL,ic,TRUE);
10297 pic16_freeAsmop(result,NULL,ic,TRUE);
10301 #if (USE_GENERIC_SIGNED_SHIFT)
10302 /*-----------------------------------------------------------------*/
10303 /* genGenericShift - generates code for left or right shifting */
10304 /*-----------------------------------------------------------------*/
10305 static void genGenericShift (iCode *ic, int isShiftLeft) {
10306 operand *left,*right, *result;
10308 int sign, signedCount;
10309 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10310 PIC_OPCODE pos_shift, neg_shift;
10314 right = IC_RIGHT(ic);
10315 left = IC_LEFT(ic);
10316 result = IC_RESULT(ic);
10318 pic16_aopOp(right,ic,FALSE);
10319 pic16_aopOp(left,ic,FALSE);
10320 pic16_aopOp(result,ic,TRUE);
10322 sign = !SPEC_USIGN(operandType (left));
10323 signedCount = !SPEC_USIGN(operandType (right));
10325 /* if the shift count is known then do it
10326 as efficiently as possible */
10327 if (AOP_TYPE(right) == AOP_LIT) {
10328 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10329 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10330 // we should modify right->aopu.aop_lit here!
10331 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10332 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10334 pic16_genLeftShiftLiteral (left,right,result,ic);
10336 genRightShiftLiteral (left,right,result,ic, sign);
10339 } // if (right is literal)
10341 /* shift count is unknown then we have to form a loop.
10342 * Note: we take only the lower order byte since shifting
10343 * more than 32 bits make no sense anyway, ( the
10344 * largest size of an object can be only 32 bits )
10345 * Note: we perform arithmetic shifts if the left operand is
10346 * signed and we do an (effective) right shift, i. e. we
10347 * shift in the sign bit from the left. */
10349 label_complete = newiTempLabel ( NULL );
10350 label_loop_pos = newiTempLabel ( NULL );
10351 label_loop_neg = NULL;
10352 label_negative = NULL;
10353 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10354 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10357 // additional labels needed
10358 label_loop_neg = newiTempLabel ( NULL );
10359 label_negative = newiTempLabel ( NULL );
10362 // copy source to result -- this will effectively truncate the left operand to the size of result!
10363 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10364 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10365 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10366 pic16_mov2f (AOP(result),AOP(left), offset);
10369 // if result is longer than left, fill with zeros (or sign)
10370 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10371 if (sign && AOP_SIZE(left) > 0) {
10372 // shift signed operand -- fill with sign
10373 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10374 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10375 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10376 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10377 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10380 // shift unsigned operand -- fill result with zeros
10381 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10382 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10385 } // if (size mismatch)
10387 pic16_mov2w (AOP(right), 0);
10388 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10389 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10392 // perform a shift by one (shift count is positive)
10393 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10394 // 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])
10395 pic16_emitpLabel (label_loop_pos->key);
10397 if (sign && (pos_shift == POC_RRCF)) {
10398 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10401 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10402 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10403 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10405 // perform a shift by one (shift count is positive)
10406 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10407 // 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])
10408 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10409 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10411 pic16_emitpLabel (label_loop_pos->key);
10412 if (sign && (pos_shift == POC_RRCF)) {
10413 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10416 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10417 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10418 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10419 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10423 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10425 pic16_emitpLabel (label_negative->key);
10426 // perform a shift by -1 (shift count is negative)
10427 // 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)
10429 pic16_emitpLabel (label_loop_neg->key);
10430 if (sign && (neg_shift == POC_RRCF)) {
10431 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10434 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10435 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10436 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10437 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10438 } // if (signedCount)
10440 pic16_emitpLabel (label_complete->key);
10443 pic16_freeAsmop (right,NULL,ic,TRUE);
10444 pic16_freeAsmop(left,NULL,ic,TRUE);
10445 pic16_freeAsmop(result,NULL,ic,TRUE);
10448 static void genLeftShift (iCode *ic) {
10449 genGenericShift (ic, 1);
10452 static void genRightShift (iCode *ic) {
10453 genGenericShift (ic, 0);
10458 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10459 void pic16_loadFSR0(operand *op, int lit)
10461 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10462 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10464 assert (!OP_SYMBOL(op)->remat);
10465 // set up FSR0 with address of result
10466 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10471 /*----------------------------------------------------------------*/
10472 /* pic16_derefPtr - move one byte from the location ptr points to */
10473 /* to WREG (doWrite == 0) or one byte from WREG */
10474 /* to the location ptr points to (doWrite != 0) */
10475 /*----------------------------------------------------------------*/
10476 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10478 if (!IS_PTR(operandType(ptr)))
10480 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10481 else pic16_mov2w (AOP(ptr), 0);
10485 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10486 /* We might determine pointer type right here: */
10487 p_type = DCL_TYPE(operandType(ptr));
10492 if (!fsr0_setup || !*fsr0_setup)
10494 pic16_loadFSR0( ptr, 0 );
10495 if (fsr0_setup) *fsr0_setup = 1;
10498 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10500 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10504 if (AOP(ptr)->aopu.aop_reg[2]) {
10505 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10506 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10507 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10508 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10509 pic16_mov2w(AOP(ptr), 2);
10510 pic16_callGenericPointerRW(doWrite, 1);
10512 // data pointer (just 2 byte given)
10513 if (!fsr0_setup || !*fsr0_setup)
10515 pic16_loadFSR0( ptr, 0 );
10516 if (fsr0_setup) *fsr0_setup = 1;
10519 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10521 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10526 assert (0 && "invalid pointer type specified");
10531 /*-----------------------------------------------------------------*/
10532 /* genUnpackBits - generates code for unpacking bits */
10533 /*-----------------------------------------------------------------*/
10534 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10537 sym_link *etype, *letype;
10538 int blen=0, bstr=0;
10543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10544 etype = getSpec(operandType(result));
10545 letype = getSpec(operandType(left));
10547 // if(IS_BITFIELD(etype)) {
10548 blen = SPEC_BLEN(etype);
10549 bstr = SPEC_BSTR(etype);
10552 lbstr = SPEC_BSTR( letype );
10554 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10555 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10558 if((blen == 1) && (bstr < 8)
10559 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10560 /* it is a single bit, so use the appropriate bit instructions */
10561 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10563 same = pic16_sameRegs(AOP(left),AOP(result));
10564 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10565 pic16_emitpcode(POC_CLRF, op);
10567 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10568 /* workaround to reduce the extra lfsr instruction */
10569 pic16_emitpcode(POC_BTFSC,
10570 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10572 assert (PIC_IS_DATA_PTR (operandType(left)));
10573 pic16_loadFSR0 (left, 0);
10574 pic16_emitpcode(POC_BTFSC,
10575 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10578 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10579 /* unsigned bitfields result in either 0 or 1 */
10580 pic16_emitpcode(POC_INCF, op);
10582 /* signed bitfields result in either 0 or -1 */
10583 pic16_emitpcode(POC_DECF, op);
10586 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10589 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10595 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10596 // access symbol directly
10597 pic16_mov2w (AOP(left), 0);
10599 pic16_derefPtr (left, ptype, 0, NULL);
10602 /* if we have bitdisplacement then it fits */
10603 /* into this byte completely or if length is */
10604 /* less than a byte */
10605 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10607 /* shift right acc */
10610 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10611 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10613 /* VR -- normally I would use the following, but since we use the hack,
10614 * to avoid the masking from AccRsh, why not mask it right now? */
10617 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10620 /* extend signed bitfields to 8 bits */
10621 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10623 assert (blen + bstr > 0);
10624 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10625 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10630 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10634 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10635 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10642 static void genDataPointerGet(operand *left,
10646 int size, offset = 0, leoffset=0 ;
10648 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10649 pic16_aopOp(result, ic, TRUE);
10653 size = AOP_SIZE(result);
10654 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10658 /* The following tests may save a redudant movff instruction when
10659 * accessing unions */
10661 /* if they are the same */
10662 if (operandsEqu (left, result)) {
10663 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10669 /* if they are the same registers */
10670 if (pic16_sameRegs(AOP(left),AOP(result))) {
10671 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10677 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10678 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10679 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10686 if ( AOP_TYPE(left) == AOP_PCODE) {
10687 fprintf(stderr,"genDataPointerGet %s, %d\n",
10688 AOP(left)->aopu.pcop->name,
10689 (AOP(left)->aopu.pcop->type == PO_DIR)?
10690 PCOR(AOP(left)->aopu.pcop)->instance:
10691 PCOI(AOP(left)->aopu.pcop)->offset);
10695 if(AOP(left)->aopu.pcop->type == PO_DIR)
10696 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10698 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10701 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10703 // pic16_DumpOp("(result)",result);
10704 if(is_LitAOp(AOP(result))) {
10705 pic16_mov2w(AOP(left), offset); // patch 8
10706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10708 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10709 pic16_popGet(AOP(left), offset), //patch 8
10710 pic16_popGet(AOP(result), offset)));
10718 pic16_freeAsmop(result,NULL,ic,TRUE);
10723 /*-----------------------------------------------------------------*/
10724 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10725 /*-----------------------------------------------------------------*/
10726 static void genNearPointerGet (operand *left,
10730 // asmop *aop = NULL;
10731 //regs *preg = NULL ;
10732 sym_link *rtype, *retype;
10733 sym_link *ltype, *letype;
10737 rtype = operandType(result);
10738 retype= getSpec(rtype);
10739 ltype = operandType(left);
10740 letype= getSpec(ltype);
10742 pic16_aopOp(left,ic,FALSE);
10744 // pic16_DumpOp("(left)",left);
10745 // pic16_DumpOp("(result)",result);
10747 /* if left is rematerialisable and
10748 * result is not bit variable type and
10749 * the left is pointer to data space i.e
10750 * lower 128 bytes of space */
10752 if (AOP_TYPE(left) == AOP_PCODE
10753 && !IS_BITFIELD(retype)
10754 && DCL_TYPE(ltype) == POINTER) {
10756 genDataPointerGet (left,result,ic);
10757 pic16_freeAsmop(left, NULL, ic, TRUE);
10761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10762 pic16_aopOp (result,ic,TRUE);
10764 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10767 if(IS_BITFIELD( retype )
10768 && (SPEC_BLEN(operandType(result))==1)
10772 int bitstrt, bytestrt;
10774 /* if this is bitfield of size 1, see if we are checking the value
10775 * of a single bit in an if-statement,
10776 * if yes, then don't generate usual code, but execute the
10777 * genIfx directly -- VR */
10781 /* CHECK: if next iCode is IFX
10782 * and current result operand is nextic's conditional operand
10783 * and current result operand live ranges ends at nextic's key number
10785 if((nextic->op == IFX)
10786 && (result == IC_COND(nextic))
10787 && (OP_LIVETO(result) == nextic->seq)
10788 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10790 /* everything is ok then */
10791 /* find a way to optimize the genIfx iCode */
10793 bytestrt = SPEC_BSTR(operandType(result))/8;
10794 bitstrt = SPEC_BSTR(operandType(result))%8;
10796 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10798 genIfxpCOpJump(nextic, jop);
10800 pic16_freeAsmop(left, NULL, ic, TRUE);
10801 pic16_freeAsmop(result, NULL, ic, TRUE);
10807 /* if bitfield then unpack the bits */
10808 if (IS_BITFIELD(letype))
10809 genUnpackBits (result, left, NULL, POINTER);
10811 /* we have can just get the values */
10812 int size = AOP_SIZE(result);
10815 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10817 pic16_loadFSR0( left, 0 );
10821 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10822 pic16_popGet(AOP(result), offset++)));
10824 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10825 pic16_popGet(AOP(result), offset++)));
10831 /* now some housekeeping stuff */
10833 /* we had to allocate for this iCode */
10834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10835 pic16_freeAsmop(NULL,aop,ic,TRUE);
10837 /* we did not allocate which means left
10838 * already in a pointer register, then
10839 * if size > 0 && this could be used again
10840 * we have to point it back to where it
10842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10843 if (AOP_SIZE(result) > 1
10844 && !OP_SYMBOL(left)->remat
10845 && ( OP_SYMBOL(left)->liveTo > ic->seq
10847 // int size = AOP_SIZE(result) - 1;
10849 // pic16_emitcode("dec","%s",rname);
10855 pic16_freeAsmop(left,NULL,ic,TRUE);
10856 pic16_freeAsmop(result,NULL,ic,TRUE);
10859 /*-----------------------------------------------------------------*/
10860 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10861 /*-----------------------------------------------------------------*/
10862 static void genPagedPointerGet (operand *left,
10867 regs *preg = NULL ;
10869 sym_link *rtype, *retype;
10871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10873 rtype = operandType(result);
10874 retype= getSpec(rtype);
10876 pic16_aopOp(left,ic,FALSE);
10878 /* if the value is already in a pointer register
10879 then don't need anything more */
10880 if (!AOP_INPREG(AOP(left))) {
10881 /* otherwise get a free pointer register */
10883 preg = getFreePtr(ic,&aop,FALSE);
10884 pic16_emitcode("mov","%s,%s",
10886 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10887 rname = preg->name ;
10889 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10891 pic16_freeAsmop(left,NULL,ic,TRUE);
10892 pic16_aopOp (result,ic,TRUE);
10894 /* if bitfield then unpack the bits */
10895 if (IS_BITFIELD(retype))
10896 genUnpackBits (result,left,rname,PPOINTER);
10898 /* we have can just get the values */
10899 int size = AOP_SIZE(result);
10904 pic16_emitcode("movx","a,@%s",rname);
10905 pic16_aopPut(AOP(result),"a",offset);
10910 pic16_emitcode("inc","%s",rname);
10914 /* now some housekeeping stuff */
10916 /* we had to allocate for this iCode */
10917 pic16_freeAsmop(NULL,aop,ic,TRUE);
10919 /* we did not allocate which means left
10920 already in a pointer register, then
10921 if size > 0 && this could be used again
10922 we have to point it back to where it
10924 if (AOP_SIZE(result) > 1 &&
10925 !OP_SYMBOL(left)->remat &&
10926 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10928 int size = AOP_SIZE(result) - 1;
10930 pic16_emitcode("dec","%s",rname);
10935 pic16_freeAsmop(result,NULL,ic,TRUE);
10941 /* This code is not adjusted to PIC16 and fails utterly.
10942 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10944 /*-----------------------------------------------------------------*/
10945 /* genFarPointerGet - gget value from far space */
10946 /*-----------------------------------------------------------------*/
10947 static void genFarPointerGet (operand *left,
10948 operand *result, iCode *ic)
10951 sym_link *retype = getSpec(operandType(result));
10953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10955 pic16_aopOp(left,ic,FALSE);
10957 /* if the operand is already in dptr
10958 then we do nothing else we move the value to dptr */
10959 if (AOP_TYPE(left) != AOP_STR) {
10960 /* if this is remateriazable */
10961 if (AOP_TYPE(left) == AOP_IMMD)
10962 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10963 else { /* we need to get it byte by byte */
10964 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10965 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10966 if (options.model == MODEL_FLAT24)
10968 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10972 /* so dptr know contains the address */
10973 pic16_freeAsmop(left,NULL,ic,TRUE);
10974 pic16_aopOp(result,ic,TRUE);
10976 /* if bit then unpack */
10977 if (IS_BITFIELD(retype))
10978 genUnpackBits(result,left,"dptr",FPOINTER);
10980 size = AOP_SIZE(result);
10984 pic16_emitcode("movx","a,@dptr");
10985 pic16_aopPut(AOP(result),"a",offset++);
10987 pic16_emitcode("inc","dptr");
10991 pic16_freeAsmop(result,NULL,ic,TRUE);
10996 /*-----------------------------------------------------------------*/
10997 /* genCodePointerGet - get value from code space */
10998 /*-----------------------------------------------------------------*/
10999 static void genCodePointerGet (operand *left,
11000 operand *result, iCode *ic)
11003 sym_link *retype = getSpec(operandType(result));
11005 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11007 pic16_aopOp(left,ic,FALSE);
11009 /* if the operand is already in dptr
11010 then we do nothing else we move the value to dptr */
11011 if (AOP_TYPE(left) != AOP_STR) {
11012 /* if this is remateriazable */
11013 if (AOP_TYPE(left) == AOP_IMMD)
11014 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11015 else { /* we need to get it byte by byte */
11016 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11017 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11018 if (options.model == MODEL_FLAT24)
11020 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11024 /* so dptr know contains the address */
11025 pic16_freeAsmop(left,NULL,ic,TRUE);
11026 pic16_aopOp(result,ic,FALSE);
11028 /* if bit then unpack */
11029 if (IS_BITFIELD(retype))
11030 genUnpackBits(result,left,"dptr",CPOINTER);
11032 size = AOP_SIZE(result);
11036 pic16_emitcode("clr","a");
11037 pic16_emitcode("movc","a,@a+dptr");
11038 pic16_aopPut(AOP(result),"a",offset++);
11040 pic16_emitcode("inc","dptr");
11044 pic16_freeAsmop(result,NULL,ic,TRUE);
11049 /*-----------------------------------------------------------------*/
11050 /* genGenPointerGet - gget value from generic pointer space */
11051 /*-----------------------------------------------------------------*/
11052 static void genGenPointerGet (operand *left,
11053 operand *result, iCode *ic)
11055 int size, offset, lit;
11056 sym_link *retype = getSpec(operandType(result));
11058 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11059 pic16_aopOp(left,ic,FALSE);
11060 pic16_aopOp(result,ic,FALSE);
11061 size = AOP_SIZE(result);
11063 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11065 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11067 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11068 // load FSR0 from immediate
11069 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11071 // pic16_loadFSR0( left );
11076 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11078 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11085 else { /* we need to get it byte by byte */
11086 // set up FSR0 with address from left
11087 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11088 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11094 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11096 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11103 /* if bit then unpack */
11104 if (IS_BITFIELD(retype))
11105 genUnpackBits(result,left,"BAD",GPOINTER);
11108 pic16_freeAsmop(left,NULL,ic,TRUE);
11109 pic16_freeAsmop(result,NULL,ic,TRUE);
11115 /*-----------------------------------------------------------------*/
11116 /* genGenPointerGet - gget value from generic pointer space */
11117 /*-----------------------------------------------------------------*/
11118 static void genGenPointerGet (operand *left,
11119 operand *result, iCode *ic)
11121 int size, offset, lit;
11122 sym_link *letype = getSpec(operandType(left));
11124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11125 pic16_aopOp(left,ic,FALSE);
11126 pic16_aopOp(result,ic,TRUE);
11127 size = AOP_SIZE(result);
11129 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11131 /* if bit then unpack */
11132 if (IS_BITFIELD(letype)) {
11133 genUnpackBits(result,left,"BAD",GPOINTER);
11137 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11139 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11140 // load FSR0 from immediate
11141 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11143 werror(W_POSSBUG2, __FILE__, __LINE__);
11148 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11150 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11157 } else { /* we need to get it byte by byte */
11159 /* set up WREG:PRODL:FSR0L with address from left */
11160 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11161 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11162 pic16_mov2w(AOP(left), 2);
11163 pic16_callGenericPointerRW(0, size);
11165 assignResultValue(result, 1);
11171 pic16_freeAsmop(left,NULL,ic,TRUE);
11172 pic16_freeAsmop(result,NULL,ic,TRUE);
11175 /*-----------------------------------------------------------------*/
11176 /* genConstPointerGet - get value from const generic pointer space */
11177 /*-----------------------------------------------------------------*/
11178 static void genConstPointerGet (operand *left,
11179 operand *result, iCode *ic)
11181 //sym_link *retype = getSpec(operandType(result));
11182 // symbol *albl = newiTempLabel(NULL); // patch 15
11183 // symbol *blbl = newiTempLabel(NULL); //
11184 // PIC_OPCODE poc; // patch 15
11188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11189 pic16_aopOp(left,ic,FALSE);
11190 pic16_aopOp(result,ic,TRUE);
11191 size = AOP_SIZE(result);
11193 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11195 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11197 // set up table pointer
11198 if( (AOP_TYPE(left) == AOP_PCODE)
11199 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11200 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11202 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11203 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11204 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11205 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11206 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11207 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11209 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11210 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11211 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11215 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11216 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11220 pic16_freeAsmop(left,NULL,ic,TRUE);
11221 pic16_freeAsmop(result,NULL,ic,TRUE);
11225 /*-----------------------------------------------------------------*/
11226 /* genPointerGet - generate code for pointer get */
11227 /*-----------------------------------------------------------------*/
11228 static void genPointerGet (iCode *ic)
11230 operand *left, *result ;
11231 sym_link *type, *etype;
11236 left = IC_LEFT(ic);
11237 result = IC_RESULT(ic) ;
11239 /* depending on the type of pointer we need to
11240 move it to the correct pointer register */
11241 type = operandType(left);
11242 etype = getSpec(type);
11245 if (IS_PTR_CONST(type))
11247 if (IS_CODEPTR(type))
11249 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11251 /* if left is of type of pointer then it is simple */
11252 if (IS_PTR(type) && !IS_FUNC(type->next))
11253 p_type = DCL_TYPE(type);
11255 /* we have to go by the storage class */
11256 p_type = PTR_TYPE(SPEC_OCLS(etype));
11258 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11260 if (SPEC_OCLS(etype)->codesp ) {
11261 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11262 //p_type = CPOINTER ;
11264 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11265 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11266 /*p_type = FPOINTER ;*/
11268 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11269 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11270 /* p_type = PPOINTER; */
11272 if (SPEC_OCLS(etype) == idata ) {
11273 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11274 /* p_type = IPOINTER; */
11276 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11277 /* p_type = POINTER ; */
11281 /* now that we have the pointer type we assign
11282 the pointer values */
11287 genNearPointerGet (left,result,ic);
11291 genPagedPointerGet(left,result,ic);
11295 /* PICs do not support FAR pointers... */
11296 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11298 genFarPointerGet (left,result,ic);
11303 genConstPointerGet (left,result,ic);
11304 //pic16_emitcodePointerGet (left,result,ic);
11309 if (IS_PTR_CONST(type))
11310 genConstPointerGet (left,result,ic);
11313 genGenPointerGet (left,result,ic);
11317 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11318 "genPointerGet: illegal pointer type");
11323 /*-----------------------------------------------------------------*/
11324 /* genPackBits - generates code for packed bit storage */
11325 /*-----------------------------------------------------------------*/
11326 static void genPackBits (sym_link *etype , operand *result,
11328 char *rname, int p_type)
11334 int shifted_and_masked = 0;
11335 unsigned long lit = (unsigned long)-1;
11338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11339 blen = SPEC_BLEN(etype);
11340 bstr = SPEC_BSTR(etype);
11342 retype = getSpec(operandType(right));
11344 if(AOP_TYPE(right) == AOP_LIT) {
11345 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11347 if((blen == 1) && (bstr < 8)) {
11348 /* it is a single bit, so use the appropriate bit instructions */
11350 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11352 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11353 /* workaround to reduce the extra lfsr instruction */
11355 pic16_emitpcode(POC_BSF,
11356 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11358 pic16_emitpcode(POC_BCF,
11359 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11362 if (PIC_IS_DATA_PTR(operandType(result))) {
11363 pic16_loadFSR0(result, 0);
11364 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11365 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11367 /* get old value */
11368 pic16_derefPtr (result, p_type, 0, NULL);
11369 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11370 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11371 /* write back new value */
11372 pic16_derefPtr (result, p_type, 1, NULL);
11378 /* IORLW below is more efficient */
11379 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11380 lit = (lit & ((1UL << blen) - 1)) << bstr;
11381 shifted_and_masked = 1;
11384 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11385 && IS_BITFIELD(retype)
11386 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11390 rblen = SPEC_BLEN( retype );
11391 rbstr = SPEC_BSTR( retype );
11393 if(IS_BITFIELD(etype)) {
11394 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11395 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11397 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11400 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11402 if(IS_BITFIELD(etype)) {
11403 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11405 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11408 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11412 /* move right to W */
11413 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11416 /* if the bit length is less than or */
11417 /* it exactly fits a byte then */
11418 if((shCnt=SPEC_BSTR(etype))
11419 || SPEC_BLEN(etype) <= 8 ) {
11420 int fsr0_setup = 0;
11422 if (blen != 8 || bstr != 0) {
11423 // we need to combine the value with the old value
11424 if(!shifted_and_masked)
11426 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11428 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11429 SPEC_BSTR(etype), SPEC_BLEN(etype));
11431 /* shift left acc, do NOT mask the result again */
11434 /* using PRODH as a temporary register here */
11435 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11438 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11439 || IS_DIRECT(result)) {
11440 /* access symbol directly */
11441 pic16_mov2w (AOP(result), 0);
11443 /* get old value */
11444 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11447 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11448 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11449 (unsigned char)(0xff >> (8-bstr))) ));
11450 if (!shifted_and_masked) {
11451 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11453 /* We have the shifted and masked (literal) right value in `lit' */
11455 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11457 } // if (blen != 8 || bstr != 0)
11459 /* write new value back */
11460 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11461 || IS_DIRECT(result)) {
11462 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11464 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11473 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11474 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11479 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11480 rLen = SPEC_BLEN(etype)-8;
11482 /* now generate for lengths greater than one byte */
11486 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11492 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11498 pic16_emitcode("movx","@dptr,a");
11503 DEBUGpic16_emitcode(";lcall","__gptrput");
11511 pic16_mov2w(AOP(right), offset++);
11514 /* last last was not complete */
11516 /* save the byte & read byte */
11519 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11520 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11525 pic16_emitcode ("mov","b,a");
11526 pic16_emitcode("movx","a,@dptr");
11530 pic16_emitcode ("push","b");
11531 pic16_emitcode ("push","acc");
11532 pic16_emitcode ("lcall","__gptrget");
11533 pic16_emitcode ("pop","b");
11539 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11540 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11541 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11542 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11543 // pic16_emitcode ("orl","a,b");
11546 // if (p_type == GPOINTER)
11547 // pic16_emitcode("pop","b");
11552 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11553 // pic16_emitcode("mov","@%s,a",rname);
11557 pic16_emitcode("movx","@dptr,a");
11561 DEBUGpic16_emitcode(";lcall","__gptrput");
11568 // pic16_freeAsmop(right, NULL, ic, TRUE);
11571 /*-----------------------------------------------------------------*/
11572 /* genDataPointerSet - remat pointer to data space */
11573 /*-----------------------------------------------------------------*/
11574 static void genDataPointerSet(operand *right,
11578 int size, offset = 0, resoffset=0 ;
11580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11581 pic16_aopOp(right,ic,FALSE);
11583 size = AOP_SIZE(right);
11585 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11588 if ( AOP_TYPE(result) == AOP_PCODE) {
11589 fprintf(stderr,"genDataPointerSet %s, %d\n",
11590 AOP(result)->aopu.pcop->name,
11591 (AOP(result)->aopu.pcop->type == PO_DIR)?
11592 PCOR(AOP(result)->aopu.pcop)->instance:
11593 PCOI(AOP(result)->aopu.pcop)->offset);
11597 if(AOP(result)->aopu.pcop->type == PO_DIR)
11598 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11601 if (AOP_TYPE(right) == AOP_LIT) {
11604 if(!IS_FLOAT(operandType( right )))
11605 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11608 unsigned long lit_int;
11612 /* take care if literal is a float */
11613 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11614 lit = info.lit_int;
11617 lit = lit >> (8*offset);
11618 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11620 pic16_mov2w(AOP(right), offset);
11621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11627 pic16_freeAsmop(right,NULL,ic,TRUE);
11632 /*-----------------------------------------------------------------*/
11633 /* genNearPointerSet - pic16_emitcode for near pointer put */
11634 /*-----------------------------------------------------------------*/
11635 static void genNearPointerSet (operand *right,
11641 sym_link *ptype = operandType(result);
11642 sym_link *resetype;
11644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11645 retype= getSpec(operandType(right));
11646 resetype = getSpec(operandType(result));
11648 pic16_aopOp(result,ic,FALSE);
11650 /* if the result is rematerializable &
11651 * in data space & not a bit variable */
11653 /* and result is not a bit variable */
11654 if (AOP_TYPE(result) == AOP_PCODE
11655 // && AOP_TYPE(result) == AOP_IMMD
11656 && DCL_TYPE(ptype) == POINTER
11657 && !IS_BITFIELD(retype)
11658 && !IS_BITFIELD(resetype)) {
11660 genDataPointerSet (right,result,ic);
11661 pic16_freeAsmop(result,NULL,ic,TRUE);
11665 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11666 pic16_aopOp(right,ic,FALSE);
11667 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11669 /* if bitfield then unpack the bits */
11670 if (IS_BITFIELD(resetype)) {
11671 genPackBits (resetype, result, right, NULL, POINTER);
11673 /* we have can just get the values */
11674 int size = AOP_SIZE(right);
11677 pic16_loadFSR0(result, 0);
11679 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11681 if (AOP_TYPE(right) == AOP_LIT) {
11682 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11684 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11686 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11688 } else { // no literal
11690 pic16_emitpcode(POC_MOVFF,
11691 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11692 pic16_popCopyReg(&pic16_pc_postinc0)));
11694 pic16_emitpcode(POC_MOVFF,
11695 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11696 pic16_popCopyReg(&pic16_pc_indf0)));
11703 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11704 /* now some housekeeping stuff */
11706 /* we had to allocate for this iCode */
11707 pic16_freeAsmop(NULL,aop,ic,TRUE);
11709 /* we did not allocate which means left
11710 * already in a pointer register, then
11711 * if size > 0 && this could be used again
11712 * we have to point it back to where it
11714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11715 if (AOP_SIZE(right) > 1
11716 && !OP_SYMBOL(result)->remat
11717 && ( OP_SYMBOL(result)->liveTo > ic->seq
11720 int size = AOP_SIZE(right) - 1;
11723 pic16_emitcode("decf","fsr0,f");
11724 //pic16_emitcode("dec","%s",rname);
11728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11731 pic16_freeAsmop(right,NULL,ic,TRUE);
11732 pic16_freeAsmop(result,NULL,ic,TRUE);
11735 /*-----------------------------------------------------------------*/
11736 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11737 /*-----------------------------------------------------------------*/
11738 static void genPagedPointerSet (operand *right,
11743 regs *preg = NULL ;
11747 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11749 retype= getSpec(operandType(right));
11751 pic16_aopOp(result,ic,FALSE);
11753 /* if the value is already in a pointer register
11754 then don't need anything more */
11755 if (!AOP_INPREG(AOP(result))) {
11756 /* otherwise get a free pointer register */
11758 preg = getFreePtr(ic,&aop,FALSE);
11759 pic16_emitcode("mov","%s,%s",
11761 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11762 rname = preg->name ;
11764 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11766 pic16_freeAsmop(result,NULL,ic,TRUE);
11767 pic16_aopOp (right,ic,FALSE);
11769 /* if bitfield then unpack the bits */
11770 if (IS_BITFIELD(retype))
11771 genPackBits (retype,result,right,rname,PPOINTER);
11773 /* we have can just get the values */
11774 int size = AOP_SIZE(right);
11778 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11781 pic16_emitcode("movx","@%s,a",rname);
11784 pic16_emitcode("inc","%s",rname);
11790 /* now some housekeeping stuff */
11792 /* we had to allocate for this iCode */
11793 pic16_freeAsmop(NULL,aop,ic,TRUE);
11795 /* we did not allocate which means left
11796 already in a pointer register, then
11797 if size > 0 && this could be used again
11798 we have to point it back to where it
11800 if (AOP_SIZE(right) > 1 &&
11801 !OP_SYMBOL(result)->remat &&
11802 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11804 int size = AOP_SIZE(right) - 1;
11806 pic16_emitcode("dec","%s",rname);
11811 pic16_freeAsmop(right,NULL,ic,TRUE);
11817 /* This code is not adjusted to PIC16 and fails utterly...
11818 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11820 /*-----------------------------------------------------------------*/
11821 /* genFarPointerSet - set value from far space */
11822 /*-----------------------------------------------------------------*/
11823 static void genFarPointerSet (operand *right,
11824 operand *result, iCode *ic)
11827 sym_link *retype = getSpec(operandType(right));
11829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11830 pic16_aopOp(result,ic,FALSE);
11832 /* if the operand is already in dptr
11833 then we do nothing else we move the value to dptr */
11834 if (AOP_TYPE(result) != AOP_STR) {
11835 /* if this is remateriazable */
11836 if (AOP_TYPE(result) == AOP_IMMD)
11837 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11838 else { /* we need to get it byte by byte */
11839 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11840 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11841 if (options.model == MODEL_FLAT24)
11843 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11847 /* so dptr know contains the address */
11848 pic16_freeAsmop(result,NULL,ic,TRUE);
11849 pic16_aopOp(right,ic,FALSE);
11851 /* if bit then unpack */
11852 if (IS_BITFIELD(retype))
11853 genPackBits(retype,result,right,"dptr",FPOINTER);
11855 size = AOP_SIZE(right);
11859 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11861 pic16_emitcode("movx","@dptr,a");
11863 pic16_emitcode("inc","dptr");
11867 pic16_freeAsmop(right,NULL,ic,TRUE);
11871 /*-----------------------------------------------------------------*/
11872 /* genGenPointerSet - set value from generic pointer space */
11873 /*-----------------------------------------------------------------*/
11875 static void genGenPointerSet (operand *right,
11876 operand *result, iCode *ic)
11878 int i, size, offset, lit;
11879 sym_link *retype = getSpec(operandType(right));
11881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11883 pic16_aopOp(result,ic,FALSE);
11884 pic16_aopOp(right,ic,FALSE);
11885 size = AOP_SIZE(right);
11888 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11890 /* if the operand is already in dptr
11891 then we do nothing else we move the value to dptr */
11892 if (AOP_TYPE(result) != AOP_STR) {
11893 /* if this is remateriazable */
11894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11895 // WARNING: anythig until "else" is untested!
11896 if (AOP_TYPE(result) == AOP_IMMD) {
11897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11898 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11899 // load FSR0 from immediate
11900 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11904 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11906 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11912 else { /* we need to get it byte by byte */
11913 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11914 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11916 // set up FSR0 with address of result
11917 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11918 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11920 /* hack hack! see if this the FSR. If so don't load W */
11921 if(AOP_TYPE(right) != AOP_ACC) {
11923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11925 if(AOP_TYPE(right) == AOP_LIT)
11928 // note: pic16_popGet handles sign extension
11929 for(i=0;i<size;i++) {
11930 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11932 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11934 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11939 for(i=0;i<size;i++) {
11941 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11942 pic16_popCopyReg(&pic16_pc_postinc0)));
11944 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11945 pic16_popCopyReg(&pic16_pc_indf0)));
11951 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11952 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11954 } // if (AOP_TYPE(result) != AOP_IMMD)
11956 } // if (AOP_TYPE(result) != AOP_STR)
11957 /* so dptr know contains the address */
11960 /* if bit then unpack */
11961 if (IS_BITFIELD(retype))
11962 genPackBits(retype,result,right,"dptr",GPOINTER);
11964 size = AOP_SIZE(right);
11967 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11969 // set up FSR0 with address of result
11970 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11971 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11974 if (AOP_TYPE(right) == AOP_LIT) {
11975 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11977 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11979 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11981 } else { // no literal
11983 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11985 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11993 pic16_freeAsmop(right,NULL,ic,TRUE);
11994 pic16_freeAsmop(result,NULL,ic,TRUE);
11998 static void genGenPointerSet (operand *right,
11999 operand *result, iCode *ic)
12002 sym_link *retype = getSpec(operandType(result));
12004 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12006 pic16_aopOp(result,ic,FALSE);
12007 pic16_aopOp(right,ic,FALSE);
12008 size = AOP_SIZE(right);
12010 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12013 /* if bit then unpack */
12014 if (IS_BITFIELD(retype)) {
12015 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12016 genPackBits(retype,result,right,"dptr",GPOINTER);
12020 size = AOP_SIZE(right);
12022 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12025 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12027 /* value of right+0 is placed on stack, which will be retrieved
12028 * by the support function this restoring the stack. The important
12029 * thing is that there is no need to manually restore stack pointer
12031 pushaop(AOP(right), 0);
12032 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12033 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12034 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12035 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12037 /* load address to write to in WREG:FSR0H:FSR0L */
12038 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12039 pic16_popCopyReg(&pic16_pc_fsr0l)));
12040 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12041 pic16_popCopyReg(&pic16_pc_prodl)));
12042 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12044 pic16_callGenericPointerRW(1, size);
12047 pic16_freeAsmop(right,NULL,ic,TRUE);
12048 pic16_freeAsmop(result,NULL,ic,TRUE);
12051 /*-----------------------------------------------------------------*/
12052 /* genPointerSet - stores the value into a pointer location */
12053 /*-----------------------------------------------------------------*/
12054 static void genPointerSet (iCode *ic)
12056 operand *right, *result ;
12057 sym_link *type, *etype;
12062 right = IC_RIGHT(ic);
12063 result = IC_RESULT(ic) ;
12065 /* depending on the type of pointer we need to
12066 move it to the correct pointer register */
12067 type = operandType(result);
12068 etype = getSpec(type);
12070 /* if left is of type of pointer then it is simple */
12071 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12072 p_type = DCL_TYPE(type);
12075 /* we have to go by the storage class */
12076 p_type = PTR_TYPE(SPEC_OCLS(etype));
12078 /* if (SPEC_OCLS(etype)->codesp ) { */
12079 /* p_type = CPOINTER ; */
12082 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12083 /* p_type = FPOINTER ; */
12085 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12086 /* p_type = PPOINTER ; */
12088 /* if (SPEC_OCLS(etype) == idata ) */
12089 /* p_type = IPOINTER ; */
12091 /* p_type = POINTER ; */
12094 /* now that we have the pointer type we assign
12095 the pointer values */
12100 genNearPointerSet (right,result,ic);
12104 genPagedPointerSet (right,result,ic);
12108 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12110 genFarPointerSet (right,result,ic);
12115 genGenPointerSet (right,result,ic);
12119 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12120 "genPointerSet: illegal pointer type");
12124 /*-----------------------------------------------------------------*/
12125 /* genIfx - generate code for Ifx statement */
12126 /*-----------------------------------------------------------------*/
12127 static void genIfx (iCode *ic, iCode *popIc)
12129 operand *cond = IC_COND(ic);
12134 pic16_aopOp(cond,ic,FALSE);
12136 /* get the value into acc */
12137 if (AOP_TYPE(cond) != AOP_CRY)
12138 pic16_toBoolean(cond);
12141 /* the result is now in the accumulator */
12142 pic16_freeAsmop(cond,NULL,ic,TRUE);
12144 /* if there was something to be popped then do it */
12148 /* if the condition is a bit variable */
12149 if (isbit && IS_ITEMP(cond) &&
12151 genIfxJump(ic,"c");
12152 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12154 if (isbit && !IS_ITEMP(cond))
12155 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12157 genIfxJump(ic,"a");
12162 /*-----------------------------------------------------------------*/
12163 /* genAddrOf - generates code for address of */
12164 /*-----------------------------------------------------------------*/
12165 static void genAddrOf (iCode *ic)
12167 operand *result, *left;
12169 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12170 pCodeOp *pcop0, *pcop1, *pcop2;
12174 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12176 sym = OP_SYMBOL( IC_LEFT(ic) );
12179 /* get address of symbol on stack */
12180 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12182 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12183 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12186 // operands on stack are accessible via "FSR2 + index" with index
12187 // starting at 2 for arguments and growing from 0 downwards for
12188 // local variables (index == 0 is not assigned so we add one here)
12190 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12192 assert (soffs < 0);
12195 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12196 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12197 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12198 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12199 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12200 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12201 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12207 // if(pic16_debug_verbose) {
12208 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12209 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12212 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12213 size = AOP_SIZE(IC_RESULT(ic));
12215 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12216 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12217 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12220 pic16_emitpcode(POC_MOVLW, pcop0);
12221 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12222 pic16_emitpcode(POC_MOVLW, pcop1);
12223 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12224 pic16_emitpcode(POC_MOVLW, pcop2);
12225 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12228 pic16_emitpcode(POC_MOVLW, pcop0);
12229 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12230 pic16_emitpcode(POC_MOVLW, pcop1);
12231 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12233 pic16_emitpcode(POC_MOVLW, pcop0);
12234 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12237 pic16_freeAsmop(left, NULL, ic, FALSE);
12239 pic16_freeAsmop(result,NULL,ic,TRUE);
12244 /*-----------------------------------------------------------------*/
12245 /* genFarFarAssign - assignment when both are in far space */
12246 /*-----------------------------------------------------------------*/
12247 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12249 int size = AOP_SIZE(right);
12252 /* first push the right side on to the stack */
12254 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12256 pic16_emitcode ("push","acc");
12259 pic16_freeAsmop(right,NULL,ic,FALSE);
12260 /* now assign DPTR to result */
12261 pic16_aopOp(result,ic,FALSE);
12262 size = AOP_SIZE(result);
12264 pic16_emitcode ("pop","acc");
12265 pic16_aopPut(AOP(result),"a",--offset);
12267 pic16_freeAsmop(result,NULL,ic,FALSE);
12272 /*-----------------------------------------------------------------*/
12273 /* genAssign - generate code for assignment */
12274 /*-----------------------------------------------------------------*/
12275 static void genAssign (iCode *ic)
12277 operand *result, *right;
12278 sym_link *restype, *rtype;
12279 int size, offset,know_W;
12280 unsigned long lit = 0L;
12282 result = IC_RESULT(ic);
12283 right = IC_RIGHT(ic) ;
12287 /* if they are the same */
12288 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12291 /* reversed order operands are aopOp'ed so that result operand
12292 * is effective in case right is a stack symbol. This maneauver
12293 * allows to use the _G.resDirect flag later */
12294 pic16_aopOp(result,ic,TRUE);
12295 pic16_aopOp(right,ic,FALSE);
12297 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12299 /* if they are the same registers */
12300 if (pic16_sameRegs(AOP(right),AOP(result)))
12303 /* if the result is a bit */
12304 if (AOP_TYPE(result) == AOP_CRY) {
12305 /* if the right size is a literal then
12306 we know what the value is */
12307 if (AOP_TYPE(right) == AOP_LIT) {
12309 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12310 pic16_popGet(AOP(result),0));
12312 if (((int) operandLitValue(right)))
12313 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12314 AOP(result)->aopu.aop_dir,
12315 AOP(result)->aopu.aop_dir);
12317 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12318 AOP(result)->aopu.aop_dir,
12319 AOP(result)->aopu.aop_dir);
12323 /* the right is also a bit variable */
12324 if (AOP_TYPE(right) == AOP_CRY) {
12325 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12326 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12327 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12329 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12330 AOP(result)->aopu.aop_dir,
12331 AOP(result)->aopu.aop_dir);
12332 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12333 AOP(right)->aopu.aop_dir,
12334 AOP(right)->aopu.aop_dir);
12335 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12336 AOP(result)->aopu.aop_dir,
12337 AOP(result)->aopu.aop_dir);
12341 /* we need to or */
12342 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12343 pic16_toBoolean(right);
12345 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12346 //pic16_aopPut(AOP(result),"a",0);
12350 /* bit variables done */
12352 size = AOP_SIZE(result);
12353 restype = operandType(result);
12354 rtype = operandType(right);
12357 if(AOP_TYPE(right) == AOP_LIT) {
12358 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12360 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12362 /* patch tag for literals that are cast to pointers */
12363 if (IS_CODEPTR(restype)) {
12364 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12365 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12367 if (IS_GENPTR(restype))
12369 if (IS_CODEPTR(rtype)) {
12370 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12371 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12372 } else if (PIC_IS_DATA_PTR(rtype)) {
12373 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12374 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12375 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12376 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12377 } else if (IS_PTR(rtype)) {
12378 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12379 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12385 unsigned long lit_int;
12390 if(IS_FIXED16X16(operandType(right))) {
12391 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12393 /* take care if literal is a float */
12394 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12395 lit = info.lit_int;
12400 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12401 // sizeof(unsigned long int), sizeof(float));
12404 if (AOP_TYPE(right) == AOP_REG) {
12405 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12407 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12412 /* when do we have to read the program memory?
12413 * - if right itself is a symbol in code space
12414 * (we don't care what it points to if it's a pointer)
12415 * - AND right is not a function (we would want its address)
12417 if(AOP_TYPE(right) != AOP_LIT
12418 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12419 && !IS_FUNC(OP_SYM_TYPE(right))
12420 && !IS_ITEMP(right))
12422 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12423 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12425 // set up table pointer
12426 if(is_LitOp(right)) {
12427 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12428 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12429 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12430 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12431 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12432 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12433 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12435 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12436 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12437 pic16_popCopyReg(&pic16_pc_tblptrl)));
12438 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12439 pic16_popCopyReg(&pic16_pc_tblptrh)));
12440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12441 pic16_popCopyReg(&pic16_pc_tblptru)));
12444 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12445 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12447 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12448 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12449 pic16_popGet(AOP(result),offset)));
12453 /* FIXME: for pointers we need to extend differently (according
12454 * to pointer type DATA/CODE/EEPROM/... :*/
12455 size = getSize(OP_SYM_TYPE(right));
12456 if(AOP_SIZE(result) > size) {
12457 size = AOP_SIZE(result) - size;
12459 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12467 /* VR - What is this?! */
12468 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12470 if(aopIdx(AOP(result),0) == 4) {
12472 /* this is a workaround to save value of right into wreg too,
12473 * value of wreg is going to be used later */
12474 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12476 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12480 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12486 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12487 if(AOP_TYPE(right) == AOP_LIT) {
12489 if(know_W != (lit&0xff))
12490 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12492 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12494 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12498 } else if (AOP_TYPE(right) == AOP_CRY) {
12499 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12501 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12502 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12503 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12505 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12506 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12507 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12511 if(!_G.resDirect) /* use this aopForSym feature */
12512 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12519 pic16_freeAsmop (right,NULL,ic,FALSE);
12520 pic16_freeAsmop (result,NULL,ic,TRUE);
12523 /*-----------------------------------------------------------------*/
12524 /* genJumpTab - generates code for jump table */
12525 /*-----------------------------------------------------------------*/
12526 static void genJumpTab (iCode *ic)
12531 pCodeOp *jt_offs_hi;
12536 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12537 /* get the condition into accumulator */
12538 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12540 /* multiply by three */
12541 pic16_emitcode("add","a,acc");
12542 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12544 jtab = newiTempLabel(NULL);
12545 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12546 pic16_emitcode("jmp","@a+dptr");
12547 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12550 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12551 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12553 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12554 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12555 pic16_emitpLabel(jtab->key);
12559 jt_offs = pic16_popGetTempReg(0);
12560 jt_offs_hi = pic16_popGetTempReg(1);
12561 jt_label = pic16_popGetLabel (jtab->key);
12562 //fprintf (stderr, "Creating jump table...\n");
12564 // calculate offset into jump table (idx * sizeof (GOTO))
12565 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12566 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12567 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12568 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12569 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12570 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12571 pic16_emitpcode(POC_MOVWF , jt_offs);
12573 // prepare PCLATx (set to first entry in jump table)
12574 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12575 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12576 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12577 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12578 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12580 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12581 pic16_emitpcode(POC_ADDWF , jt_offs);
12582 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12583 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12585 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12587 // release temporaries and prepare jump into table (new PCL --> WREG)
12588 pic16_emitpcode(POC_MOVFW , jt_offs);
12589 pic16_popReleaseTempReg (jt_offs_hi, 1);
12590 pic16_popReleaseTempReg (jt_offs, 0);
12592 // jump into the table
12593 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12595 pic16_emitpLabelFORCE(jtab->key);
12598 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12599 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12601 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12602 /* now generate the jump labels */
12603 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12604 jtab = setNextItem(IC_JTLABELS(ic))) {
12605 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12606 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12609 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12613 /*-----------------------------------------------------------------*/
12614 /* genMixedOperation - gen code for operators between mixed types */
12615 /*-----------------------------------------------------------------*/
12617 TSD - Written for the PIC port - but this unfortunately is buggy.
12618 This routine is good in that it is able to efficiently promote
12619 types to different (larger) sizes. Unfortunately, the temporary
12620 variables that are optimized out by this routine are sometimes
12621 used in other places. So until I know how to really parse the
12622 iCode tree, I'm going to not be using this routine :(.
12624 static int genMixedOperation (iCode *ic)
12627 operand *result = IC_RESULT(ic);
12628 sym_link *ctype = operandType(IC_LEFT(ic));
12629 operand *right = IC_RIGHT(ic);
12635 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12637 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12643 nextright = IC_RIGHT(nextic);
12644 nextleft = IC_LEFT(nextic);
12645 nextresult = IC_RESULT(nextic);
12647 pic16_aopOp(right,ic,FALSE);
12648 pic16_aopOp(result,ic,FALSE);
12649 pic16_aopOp(nextright, nextic, FALSE);
12650 pic16_aopOp(nextleft, nextic, FALSE);
12651 pic16_aopOp(nextresult, nextic, FALSE);
12653 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12655 operand *t = right;
12659 pic16_emitcode(";remove right +","");
12661 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12663 operand *t = right;
12667 pic16_emitcode(";remove left +","");
12671 big = AOP_SIZE(nextleft);
12672 small = AOP_SIZE(nextright);
12674 switch(nextic->op) {
12677 pic16_emitcode(";optimize a +","");
12678 /* if unsigned or not an integral type */
12679 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12680 pic16_emitcode(";add a bit to something","");
12683 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12685 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12686 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12687 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12689 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12697 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12698 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12699 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12702 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12704 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12705 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12706 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12707 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12708 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12711 pic16_emitcode("rlf","known_zero,w");
12718 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12719 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12720 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12722 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12732 pic16_freeAsmop(right,NULL,ic,TRUE);
12733 pic16_freeAsmop(result,NULL,ic,TRUE);
12734 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12735 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12737 nextic->generated = 1;
12744 /*-----------------------------------------------------------------*/
12745 /* genCast - gen code for casting */
12746 /*-----------------------------------------------------------------*/
12747 static void genCast (iCode *ic)
12749 operand *result = IC_RESULT(ic);
12750 sym_link *ctype = operandType(IC_LEFT(ic));
12751 sym_link *rtype = operandType(IC_RIGHT(ic));
12752 sym_link *restype = operandType(IC_RESULT(ic));
12753 operand *right = IC_RIGHT(ic);
12759 /* if they are equivalent then do nothing */
12760 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12763 pic16_aopOp(result,ic,FALSE);
12764 pic16_aopOp(right,ic,FALSE) ;
12766 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12769 /* if the result is a bit */
12770 if (AOP_TYPE(result) == AOP_CRY) {
12772 /* if the right size is a literal then
12773 * we know what the value is */
12774 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12776 if (AOP_TYPE(right) == AOP_LIT) {
12777 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12778 pic16_popGet(AOP(result),0));
12780 if (((int) operandLitValue(right)))
12781 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12782 AOP(result)->aopu.aop_dir,
12783 AOP(result)->aopu.aop_dir);
12785 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12786 AOP(result)->aopu.aop_dir,
12787 AOP(result)->aopu.aop_dir);
12791 /* the right is also a bit variable */
12792 if (AOP_TYPE(right) == AOP_CRY) {
12794 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12796 pic16_emitcode("clrc","");
12797 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12798 AOP(right)->aopu.aop_dir,
12799 AOP(right)->aopu.aop_dir);
12800 pic16_aopPut(AOP(result),"c",0);
12804 /* we need to or */
12805 if (AOP_TYPE(right) == AOP_REG) {
12806 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12807 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12808 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12810 pic16_toBoolean(right);
12811 pic16_aopPut(AOP(result),"a",0);
12815 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12818 size = AOP_SIZE(result);
12820 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12822 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12823 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12824 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12827 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12832 if(IS_BITFIELD(getSpec(restype))
12833 && IS_BITFIELD(getSpec(rtype))) {
12834 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12837 /* port from pic14 to cope with generic pointers */
12838 if (PIC_IS_TAGGED(restype))
12840 operand *result = IC_RESULT(ic);
12841 //operand *left = IC_LEFT(ic);
12842 operand *right = IC_RIGHT(ic);
12845 /* copy common part */
12846 int max, size = AOP_SIZE(result);
12847 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12848 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12853 pic16_mov2w (AOP(right), size);
12854 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12857 /* upcast into generic pointer type? */
12858 if (IS_GENPTR(restype)
12859 && !PIC_IS_TAGGED(rtype)
12860 && (AOP_SIZE(result) > max))
12862 /* determine appropriate tag for right */
12863 if (PIC_IS_DATA_PTR(rtype))
12864 tag = GPTR_TAG_DATA;
12865 else if (IS_CODEPTR(rtype))
12866 tag = GPTR_TAG_CODE;
12867 else if (PIC_IS_DATA_PTR(ctype)) {
12868 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12869 tag = GPTR_TAG_DATA;
12870 } else if (IS_CODEPTR(ctype)) {
12871 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12872 tag = GPTR_TAG_CODE;
12873 } else if (IS_PTR(rtype)) {
12874 PERFORM_ONCE(weirdcast,
12875 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12877 tag = GPTR_TAG_DATA;
12879 PERFORM_ONCE(weirdcast,
12880 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12882 tag = GPTR_TAG_DATA;
12885 assert (AOP_SIZE(result) == 3);
12886 /* zero-extend address... */
12887 for (size = max; size < AOP_SIZE(result)-1; size++)
12888 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12889 /* ...and add tag */
12890 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12891 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12892 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12893 for (size = max; size < AOP_SIZE(result)-1; size++)
12894 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12895 /* add __code tag */
12896 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12897 } else if (AOP_SIZE(result) > max) {
12898 /* extend non-pointers */
12899 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12900 pic16_addSign(result, max, 0);
12905 /* if they are the same size : or less */
12906 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12908 /* if they are in the same place */
12909 if (pic16_sameRegs(AOP(right),AOP(result)))
12912 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12914 if (IS_PTR_CONST(rtype))
12916 if (IS_CODEPTR(rtype))
12918 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12921 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12923 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12925 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12928 if(AOP_TYPE(right) == AOP_IMMD) {
12929 pCodeOp *pcop0, *pcop1, *pcop2;
12930 symbol *sym = OP_SYMBOL( right );
12932 size = AOP_SIZE(result);
12934 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12936 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12938 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12941 pic16_emitpcode(POC_MOVLW, pcop0);
12942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12943 pic16_emitpcode(POC_MOVLW, pcop1);
12944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12945 pic16_emitpcode(POC_MOVLW, pcop2);
12946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12949 pic16_emitpcode(POC_MOVLW, pcop0);
12950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12951 pic16_emitpcode(POC_MOVLW, pcop1);
12952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12954 pic16_emitpcode(POC_MOVLW, pcop0);
12955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12959 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12960 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12962 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12964 if(AOP_SIZE(result) <2)
12965 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12967 /* if they in different places then copy */
12968 size = AOP_SIZE(result);
12971 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12979 /* if the result is of type pointer */
12980 if (IS_PTR(ctype)) {
12982 sym_link *type = operandType(right);
12983 sym_link *etype = getSpec(type);
12985 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12987 /* pointer to generic pointer */
12988 if (IS_GENPTR(ctype)) {
12992 p_type = DCL_TYPE(type);
12994 /* we have to go by the storage class */
12995 p_type = PTR_TYPE(SPEC_OCLS(etype));
12997 /* if (SPEC_OCLS(etype)->codesp ) */
12998 /* p_type = CPOINTER ; */
13000 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13001 /* p_type = FPOINTER ; */
13003 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13004 /* p_type = PPOINTER; */
13006 /* if (SPEC_OCLS(etype) == idata ) */
13007 /* p_type = IPOINTER ; */
13009 /* p_type = POINTER ; */
13012 /* the first two bytes are known */
13013 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13014 size = GPTRSIZE - 1;
13017 if(offset < AOP_SIZE(right)) {
13018 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13019 pic16_mov2f(AOP(result), AOP(right), offset);
13021 if ((AOP_TYPE(right) == AOP_PCODE) &&
13022 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13023 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13027 pic16_aopPut(AOP(result),
13028 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13033 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13036 /* the last byte depending on type */
13041 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13045 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13049 pic16_emitcode(";BUG!? ","%d",__LINE__);
13054 if (GPTRSIZE > AOP_SIZE(right)) {
13055 // assume __data pointer... THIS MIGHT BE WRONG!
13056 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13058 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13063 /* this should never happen */
13064 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13065 "got unknown pointer type");
13068 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13074 /* just copy the pointers */
13075 size = AOP_SIZE(result);
13078 pic16_aopPut(AOP(result),
13079 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13088 /* so we now know that the size of destination is greater
13089 than the size of the source.
13090 Now, if the next iCode is an operator then we might be
13091 able to optimize the operation without performing a cast.
13093 if(genMixedOperation(ic))
13096 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13098 /* we move to result for the size of source */
13099 size = AOP_SIZE(right);
13104 pic16_mov2f(AOP(result), AOP(right), offset);
13108 /* now depending on the sign of the destination */
13109 size = AOP_SIZE(result) - AOP_SIZE(right);
13110 /* if unsigned or not an integral type */
13111 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13113 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13115 /* we need to extend the sign :( */
13118 /* Save one instruction of casting char to int */
13119 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13120 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13121 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13123 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13126 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13128 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13130 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13133 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13138 pic16_freeAsmop(right,NULL,ic,TRUE);
13139 pic16_freeAsmop(result,NULL,ic,TRUE);
13143 /*-----------------------------------------------------------------*/
13144 /* genDjnz - generate decrement & jump if not zero instrucion */
13145 /*-----------------------------------------------------------------*/
13146 static int genDjnz (iCode *ic, iCode *ifx)
13148 symbol *lbl, *lbl1;
13149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13154 /* if the if condition has a false label
13155 then we cannot save */
13159 /* if the minus is not of the form
13161 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13162 !IS_OP_LITERAL(IC_RIGHT(ic)))
13165 if (operandLitValue(IC_RIGHT(ic)) != 1)
13168 /* if the size of this greater than one then no
13170 if (getSize(operandType(IC_RESULT(ic))) > 1)
13173 /* otherwise we can save BIG */
13174 lbl = newiTempLabel(NULL);
13175 lbl1= newiTempLabel(NULL);
13177 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13179 if (IS_AOP_PREG(IC_RESULT(ic))) {
13180 pic16_emitcode("dec","%s",
13181 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13182 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13183 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13187 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13188 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13190 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13191 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13195 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13196 ifx->generated = 1;
13200 /*-----------------------------------------------------------------*/
13201 /* genReceive - generate code for a receive iCode */
13202 /*-----------------------------------------------------------------*/
13203 static void genReceive (iCode *ic)
13209 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13210 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13212 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13214 if (isOperandInFarSpace(IC_RESULT(ic))
13215 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13216 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13218 int size = getSize(operandType(IC_RESULT(ic)));
13219 int offset = pic16_fReturnSizePic - size;
13223 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13224 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13228 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13230 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13231 size = AOP_SIZE(IC_RESULT(ic));
13234 pic16_emitcode ("pop","acc");
13235 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13238 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13240 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13243 /* set pseudo stack pointer to where it should be - dw*/
13244 GpsuedoStkPtr = ic->parmBytes;
13246 /* setting GpsuedoStkPtr has side effects here: */
13247 assignResultValue(IC_RESULT(ic), 0);
13250 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13253 /*-----------------------------------------------------------------*/
13254 /* genDummyRead - generate code for dummy read of volatiles */
13255 /*-----------------------------------------------------------------*/
13257 genDummyRead (iCode * ic)
13263 if (op && IS_SYMOP(op)) {
13264 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13265 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13268 pic16_aopOp (op, ic, FALSE);
13269 for (i=0; i < AOP_SIZE(op); i++) {
13270 // may need to protect this from the peepholer -- this is not nice but works...
13271 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13272 pic16_mov2w (AOP(op),i);
13273 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13275 pic16_freeAsmop (op, NULL, ic, TRUE);
13277 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13281 /*-----------------------------------------------------------------*/
13282 /* genpic16Code - generate code for pic16 based controllers */
13283 /*-----------------------------------------------------------------*/
13285 * At this point, ralloc.c has gone through the iCode and attempted
13286 * to optimize in a way suitable for a PIC. Now we've got to generate
13287 * PIC instructions that correspond to the iCode.
13289 * Once the instructions are generated, we'll pass through both the
13290 * peep hole optimizer and the pCode optimizer.
13291 *-----------------------------------------------------------------*/
13293 void genpic16Code (iCode *lic)
13298 lineHead = lineCurr = NULL;
13300 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13301 pic16_addpBlock(pb);
13304 /* if debug information required */
13305 if (options.debug && currFunc) {
13307 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13312 for (ic = lic ; ic ; ic = ic->next ) {
13314 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13315 if ( cln != ic->lineno ) {
13316 if ( options.debug ) {
13317 debugFile->writeCLine (ic);
13320 if(!options.noCcodeInAsm) {
13321 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13322 printCLine(ic->filename, ic->lineno)));
13328 if(options.iCodeInAsm) {
13331 /* insert here code to print iCode as comment */
13332 l = Safe_strdup(printILine(ic));
13333 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13336 /* if the result is marked as
13337 * spilt and rematerializable or code for
13338 * this has already been generated then
13340 if (resultRemat(ic) || ic->generated )
13343 /* depending on the operation */
13362 /* IPOP happens only when trying to restore a
13363 * spilt live range, if there is an ifx statement
13364 * following this pop then the if statement might
13365 * be using some of the registers being popped which
13366 * would destroy the contents of the register so
13367 * we need to check for this condition and handle it */
13369 && ic->next->op == IFX
13370 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13371 genIfx (ic->next,ic);
13389 genEndFunction (ic);
13405 pic16_genPlus (ic) ;
13409 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13410 pic16_genMinus (ic);
13426 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13430 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13436 /* note these two are xlated by algebraic equivalence
13437 * during parsing SDCC.y */
13438 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13439 "got '>=' or '<=' shouldn't have come here");
13443 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13455 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13459 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13463 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13487 genRightShift (ic);
13490 case GET_VALUE_AT_ADDRESS:
13495 if (POINTER_SET(ic))
13522 addSet(&_G.sendSet,ic);
13525 case DUMMY_READ_VOLATILE:
13535 /* now we are ready to call the
13536 peep hole optimizer */
13537 if (!options.nopeep)
13538 peepHole (&lineHead);
13540 /* now do the actual printing */
13541 printLine (lineHead, codeOutFile);
13544 DFPRINTF((stderr,"printing pBlock\n\n"));
13545 pic16_printpBlock(stdout,pb);