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 "{FRAME POINTER} + index" with index
733 // starting at 2 for arguments and growing from 0 downwards for
734 // local variables (index == 0 is not assigned so we add one here)
736 int soffs = sym->stack;
742 if(1 && ic->op == SEND) {
743 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
744 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
745 pic16_popCopyReg( pic16_frame_plusw ),
746 pic16_popCopyReg(pic16_stack_postdec )));
748 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
749 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
750 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
756 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
763 /* now assign the address of the variable to
764 the pointer register */
765 if (aop->type != AOP_STK) {
769 pic16_emitcode("push","acc");
771 pic16_emitcode("mov","a,_bp");
772 pic16_emitcode("add","a,#0x%02x",
774 ((char)(sym->stack - _G.nRegsSaved )) :
775 ((char)sym->stack)) & 0xff);
776 pic16_emitcode("mov","%s,a",
777 aop->aopu.aop_ptr->name);
780 pic16_emitcode("pop","acc");
782 pic16_emitcode("mov","%s,#%s",
783 aop->aopu.aop_ptr->name,
785 aop->paged = space->paged;
787 aop->aopu.aop_stk = sym->stack;
795 if (sym->onStack && options.stack10bit)
797 /* It's on the 10 bit stack, which is located in
801 //DEBUGpic16_emitcode(";","%d",__LINE__);
804 pic16_emitcode("push","acc");
806 pic16_emitcode("mov","a,_bp");
807 pic16_emitcode("add","a,#0x%02x",
809 ((char)(sym->stack - _G.nRegsSaved )) :
810 ((char)sym->stack)) & 0xff);
813 pic16_emitcode ("mov","dpx1,#0x40");
814 pic16_emitcode ("mov","dph1,#0x00");
815 pic16_emitcode ("mov","dpl1, a");
819 pic16_emitcode("pop","acc");
821 sym->aop = aop = newAsmop(AOP_DPTR2);
822 aop->size = getSize(sym->type);
828 /* special case for a function */
829 if (IS_FUNC(sym->type)) {
830 sym->aop = aop = newAsmop(AOP_PCODE);
831 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
832 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
833 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
834 PCOI(aop->aopu.pcop)->index = 0;
835 aop->size = FPTRSIZE;
836 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
843 //DEBUGpic16_emitcode(";","%d",__LINE__);
844 /* if in bit space */
845 if (IN_BITSPACE(space)) {
846 sym->aop = aop = newAsmop (AOP_CRY);
847 aop->aopu.aop_dir = sym->rname ;
848 aop->size = getSize(sym->type);
849 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
852 /* if it is in direct space */
853 if (IN_DIRSPACE(space)) {
854 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 (AOP_DIR) = %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);
1557 return aop->aopu.aop_reg[offset]->name;
1560 return aop->aopu.aop_dir;
1563 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1564 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1566 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1567 rs = Safe_strdup("WREG");
1571 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1572 rs = Safe_calloc(1,strlen(s)+1);
1577 aop->coff = offset ;
1579 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1582 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1583 aop->type = AOP_ACC;
1584 return Safe_strdup("WREG");
1586 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1588 return aop->aopu.aop_str[offset];
1592 pCodeOp *pcop = aop->aopu.pcop;
1593 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1595 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1596 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1598 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1600 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1603 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1606 rs = Safe_calloc(1,strlen(s)+1);
1612 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1614 sprintf(s,"(%s + %d)",
1618 sprintf(s,"%s",aop->aopu.aop_dir);
1619 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1620 rs = Safe_calloc(1,strlen(s)+1);
1626 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1630 // pCodeOp *pcop = aop->aop
1635 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1636 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1637 "aopget got unsupported aop->type");
1643 /* lock has the following meaning: When allocating temporary registers
1644 * for stack variables storage, the value of the temporary register is
1645 * saved on stack. Its value is restored at the end. This procedure is
1646 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1647 * a possibility that before a call to pic16_aopOp, a temporary register
1648 * is allocated for a while and it is freed after some time, this will
1649 * mess the stack and values will not be restored properly. So use lock=1
1650 * to allocate temporary registers used internally by the programmer, and
1651 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1652 * to inform the compiler developer about a possible bug. This is an internal
1653 * feature for developing the compiler -- VR */
1655 int _TempReg_lock = 0;
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetTempReg(int lock)
1664 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1666 // werror(W_POSSBUG2, __FILE__, __LINE__);
1669 _TempReg_lock += lock;
1674 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1675 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1676 PCOR(pcop)->r->wasUsed=1;
1677 PCOR(pcop)->r->isFree=0;
1679 /* push value on stack */
1680 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1688 /*-----------------------------------------------------------------*/
1689 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1690 /* is not part of f, but don't save if */
1692 /*-----------------------------------------------------------------*/
1693 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1699 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1702 // werror(W_POSSBUG2, __FILE__, __LINE__);
1705 _TempReg_lock += lock;
1710 i = bitVectFirstBit(f);
1713 /* bypass registers that are used by function */
1714 if(!bitVectBitValue(f, i)) {
1716 /* bypass registers that are already allocated for stack access */
1717 if(!bitVectBitValue(v, i)) {
1719 // debugf("getting register rIdx = %d\n", i);
1720 /* ok, get the operand */
1721 pcop = pic16_newpCodeOpReg( i );
1723 /* should never by NULL */
1724 assert( pcop != NULL );
1728 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1731 PCOR(pcop)->r->wasUsed=1;
1732 PCOR(pcop)->r->isFree=0;
1738 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1740 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1741 /* already used in previous steps, break */
1748 /* caller takes care of the following */
1749 // bitVectSetBit(v, i);
1752 /* push value on stack */
1753 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1754 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1770 /*-----------------------------------------------------------------*/
1771 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1772 /*-----------------------------------------------------------------*/
1773 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1777 _TempReg_lock -= lock;
1779 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1780 PCOR(pcop)->r->isFree = 1;
1782 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1785 /*-----------------------------------------------------------------*/
1786 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1787 /*-----------------------------------------------------------------*/
1788 pCodeOp *pic16_popGetLabel(unsigned int key)
1791 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1796 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1799 /*-----------------------------------------------------------------*/
1800 /* pic16_popCopyReg - copy a pcode operator */
1801 /*-----------------------------------------------------------------*/
1802 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1806 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1807 memcpy (pcor, pc, sizeof (pCodeOpReg));
1808 pcor->r->wasUsed = 1;
1810 //pcor->pcop.type = pc->pcop.type;
1812 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1813 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1815 pcor->pcop.name = NULL;
1818 //pcor->rIdx = pc->rIdx;
1819 //pcor->r->wasUsed=1;
1820 //pcor->instance = pc->instance;
1822 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1827 /*-----------------------------------------------------------------*/
1828 /* pic16_popGetLit - asm operator to pcode operator conversion */
1829 /*-----------------------------------------------------------------*/
1830 pCodeOp *pic16_popGetLit(int lit)
1832 return pic16_newpCodeOpLit(lit);
1835 /*-----------------------------------------------------------------*/
1836 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1837 /*-----------------------------------------------------------------*/
1838 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1840 return pic16_newpCodeOpLit2(lit, arg2);
1844 /*-----------------------------------------------------------------*/
1845 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1846 /*-----------------------------------------------------------------*/
1847 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1849 return pic16_newpCodeOpImmd(name, offset,index, 0);
1853 /*-----------------------------------------------------------------*/
1854 /* pic16_popGet - asm operator to pcode operator conversion */
1855 /*-----------------------------------------------------------------*/
1856 pCodeOp *pic16_popGetWithString(char *str)
1862 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1866 pcop = pic16_newpCodeOp(str,PO_STR);
1871 /*-----------------------------------------------------------------*/
1872 /* pic16_popRegFromString - */
1873 /*-----------------------------------------------------------------*/
1874 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1877 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1878 pcop->type = PO_DIR;
1880 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1881 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1886 pcop->name = Safe_calloc(1,strlen(str)+1);
1887 strcpy(pcop->name,str);
1889 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1891 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1893 /* make sure that register doesn't exist,
1894 * and operand isn't NULL
1895 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1896 if((PCOR(pcop)->r == NULL)
1898 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1899 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1900 // __FUNCTION__, __LINE__, str, size, offset);
1902 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1903 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1906 PCOR(pcop)->instance = offset;
1911 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1915 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1917 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1918 PCOR(pcop)->rIdx = rIdx;
1919 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1921 PCOR(pcop)->r->isFree = 0;
1922 PCOR(pcop)->r->wasUsed = 1;
1924 pcop->type = PCOR(pcop)->r->pc_type;
1929 /*---------------------------------------------------------------------------------*/
1930 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1932 /*---------------------------------------------------------------------------------*/
1933 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1938 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1940 /* comment the following check, so errors to throw up */
1941 // if(!pcop2)return NULL;
1943 temp = pic16_popGet(aop_dst, offset);
1944 pcop2->pcop2 = temp;
1951 /*--------------------------------------------------------------------------------.-*/
1952 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1953 /* VR 030601 , adapted by Hans Dorn */
1954 /*--------------------------------------------------------------------------------.-*/
1955 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1959 pcop2 = (pCodeOpReg2 *)src;
1967 /*---------------------------------------------------------------------------------*/
1968 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1969 /* movff instruction */
1970 /*---------------------------------------------------------------------------------*/
1971 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1976 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1977 pcop2->pcop2 = pic16_popCopyReg(dst);
1979 /* the pCodeOp may be already allocated */
1980 pcop2 = (pCodeOpReg2 *)(src);
1981 pcop2->pcop2 = (pCodeOp *)(dst);
1988 /*-----------------------------------------------------------------*/
1989 /* pic16_popGet - asm operator to pcode operator conversion */
1990 /*-----------------------------------------------------------------*/
1991 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1993 //char *s = buffer ;
1998 /* offset is greater than
2001 // if (offset > (aop->size - 1) &&
2002 // aop->type != AOP_LIT)
2003 // return NULL; //zero;
2005 /* depending on type */
2006 switch (aop->type) {
2012 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2013 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2020 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2021 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2022 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2023 PCOR(pcop)->r->wasUsed = 1;
2024 PCOR(pcop)->r->isFree = 0;
2026 PCOR(pcop)->instance = offset;
2027 pcop->type = PCOR(pcop)->r->pc_type;
2031 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2032 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2035 /* pCodeOp is already allocated from aopForSym */
2036 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2037 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2043 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2045 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2047 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2049 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2050 PCOR(pcop)->rIdx = rIdx;
2051 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2052 PCOR(pcop)->r->wasUsed=1;
2053 PCOR(pcop)->r->isFree=0;
2055 PCOR(pcop)->instance = offset;
2056 pcop->type = PCOR(pcop)->r->pc_type;
2057 // rs = aop->aopu.aop_reg[offset]->name;
2058 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2062 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2063 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2069 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2070 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2074 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2075 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2081 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2082 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2084 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2086 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2087 // pcop->type = PO_GPR_REGISTER;
2088 PCOR(pcop)->rIdx = rIdx;
2089 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2090 PCOR(pcop)->r->wasUsed=1;
2091 PCOR(pcop)->r->isFree=0;
2093 PCOR(pcop)->instance = offset;
2094 pcop->type = PCOR(pcop)->r->pc_type;
2096 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2097 rs = aop->aopu.aop_reg[offset]->name;
2098 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2103 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2105 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2106 PCOR(pcop)->instance = offset;
2107 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2108 //if(PCOR(pcop)->r == NULL)
2109 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2113 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2114 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2117 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2118 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2121 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2122 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2123 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2124 pcop->type = PCOR(pcop)->r->pc_type;
2125 pcop->name = PCOR(pcop)->r->name;
2131 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2133 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2134 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2135 switch( aop->aopu.pcop->type ) {
2136 case PO_DIR: PCOR(pcop)->instance += offset; break;
2137 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2142 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2143 assert( 0 ); /* should never reach here */;
2148 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2149 "pic16_popGet got unsupported aop->type");
2152 /*-----------------------------------------------------------------*/
2153 /* pic16_aopPut - puts a string for a aop */
2154 /*-----------------------------------------------------------------*/
2155 void pic16_aopPut (asmop *aop, char *s, int offset)
2162 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2164 if (aop->size && offset > ( aop->size - 1)) {
2165 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2166 "pic16_aopPut got offset > aop->size");
2170 /* will assign value to value */
2171 /* depending on where it is ofcourse */
2172 switch (aop->type) {
2175 sprintf(d,"(%s + %d)",
2176 aop->aopu.aop_dir,offset);
2177 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2180 sprintf(d,"%s",aop->aopu.aop_dir);
2183 DEBUGpic16_emitcode(";","%d",__LINE__);
2185 pic16_emitcode("movf","%s,w",s);
2186 pic16_emitcode("movwf","%s",d);
2189 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2190 if(offset >= aop->size) {
2191 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2194 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2197 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2204 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2205 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2208 strcmp(s,"r0") == 0 ||
2209 strcmp(s,"r1") == 0 ||
2210 strcmp(s,"r2") == 0 ||
2211 strcmp(s,"r3") == 0 ||
2212 strcmp(s,"r4") == 0 ||
2213 strcmp(s,"r5") == 0 ||
2214 strcmp(s,"r6") == 0 ||
2215 strcmp(s,"r7") == 0 )
2216 pic16_emitcode("mov","%s,%s ; %d",
2217 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2221 if(strcmp(s,"W")==0 )
2222 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2224 pic16_emitcode("movwf","%s",
2225 aop->aopu.aop_reg[offset]->name);
2227 if(strcmp(s,zero)==0) {
2228 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2230 } else if(strcmp(s,"W")==0) {
2231 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2232 pcop->type = PO_GPR_REGISTER;
2234 PCOR(pcop)->rIdx = -1;
2235 PCOR(pcop)->r = NULL;
2237 DEBUGpic16_emitcode(";","%d",__LINE__);
2238 pcop->name = Safe_strdup(s);
2239 pic16_emitpcode(POC_MOVFW,pcop);
2240 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2241 } else if(strcmp(s,one)==0) {
2242 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2243 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2245 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2253 if (aop->type == AOP_DPTR2)
2259 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2260 "pic16_aopPut writting to code space");
2264 while (offset > aop->coff) {
2266 pic16_emitcode ("inc","dptr");
2269 while (offset < aop->coff) {
2271 pic16_emitcode("lcall","__decdptr");
2276 /* if not in accumulater */
2279 pic16_emitcode ("movx","@dptr,a");
2281 if (aop->type == AOP_DPTR2)
2289 while (offset > aop->coff) {
2291 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2293 while (offset < aop->coff) {
2295 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2301 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2306 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2308 if (strcmp(s,"r0") == 0 ||
2309 strcmp(s,"r1") == 0 ||
2310 strcmp(s,"r2") == 0 ||
2311 strcmp(s,"r3") == 0 ||
2312 strcmp(s,"r4") == 0 ||
2313 strcmp(s,"r5") == 0 ||
2314 strcmp(s,"r6") == 0 ||
2315 strcmp(s,"r7") == 0 ) {
2317 sprintf(buffer,"a%s",s);
2318 pic16_emitcode("mov","@%s,%s",
2319 aop->aopu.aop_ptr->name,buffer);
2321 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2326 if (strcmp(s,"a") == 0)
2327 pic16_emitcode("push","acc");
2329 pic16_emitcode("push","%s",s);
2334 /* if bit variable */
2335 if (!aop->aopu.aop_dir) {
2336 pic16_emitcode("clr","a");
2337 pic16_emitcode("rlc","a");
2340 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2343 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2346 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2348 lbl = newiTempLabel(NULL);
2350 if (strcmp(s,"a")) {
2353 pic16_emitcode("clr","c");
2354 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2355 pic16_emitcode("cpl","c");
2356 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2357 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2364 if (strcmp(aop->aopu.aop_str[offset],s))
2365 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2370 if (!offset && (strcmp(s,"acc") == 0))
2373 if (strcmp(aop->aopu.aop_str[offset],s))
2374 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2378 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2379 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2380 // "pic16_aopPut got unsupported aop->type");
2386 /*-----------------------------------------------------------------*/
2387 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2388 /*-----------------------------------------------------------------*/
2389 void pic16_mov2w (asmop *aop, int offset)
2391 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2394 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2396 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2399 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2401 if(is_LitAOp(src)) {
2402 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2403 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2405 if(pic16_sameRegsOfs(src, dst, offset))return;
2406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2407 pic16_popGet(dst, offset)));
2411 static void pic16_movLit2f(pCodeOp *pc, int lit)
2413 if (0 == (lit & 0x00ff))
2415 pic16_emitpcode (POC_CLRF, pc);
2416 } else if (0xff == (lit & 0x00ff))
2418 pic16_emitpcode (POC_SETF, pc);
2420 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2421 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2425 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2427 if(is_LitAOp(src)) {
2428 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2429 pic16_emitpcode(POC_MOVWF, dst);
2431 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2435 void pic16_testStackOverflow(void)
2437 #define GSTACK_TEST_NAME "_gstack_test"
2439 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2444 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2445 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2446 // strcpy(sym->rname, GSTACK_TEST_NAME);
2447 checkAddSym(&externs, sym);
2452 /* push pcop into stack */
2453 void pic16_pushpCodeOp(pCodeOp *pcop)
2455 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2456 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2457 if(pic16_options.gstack)
2458 pic16_testStackOverflow();
2462 /* pop pcop from stack */
2463 void pic16_poppCodeOp(pCodeOp *pcop)
2465 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2466 if(pic16_options.gstack)
2467 pic16_testStackOverflow();
2471 /*-----------------------------------------------------------------*/
2472 /* pushw - pushes wreg to stack */
2473 /*-----------------------------------------------------------------*/
2476 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2477 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2478 if(pic16_options.gstack)
2479 pic16_testStackOverflow();
2483 /*-----------------------------------------------------------------*/
2484 /* pushaop - pushes aop to stack */
2485 /*-----------------------------------------------------------------*/
2486 void pushaop(asmop *aop, int offset)
2488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2490 if(is_LitAOp(aop)) {
2491 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2492 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2494 pic16_emitpcode(POC_MOVFF,
2495 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2498 if(pic16_options.gstack)
2499 pic16_testStackOverflow();
2502 /*-----------------------------------------------------------------*/
2503 /* popaop - pops aop from stack */
2504 /*-----------------------------------------------------------------*/
2505 void popaop(asmop *aop, int offset)
2507 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2508 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2509 if(pic16_options.gstack)
2510 pic16_testStackOverflow();
2513 void popaopidx(asmop *aop, int offset, int index)
2517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2519 if(STACK_MODEL_LARGE)ofs++;
2521 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2522 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2523 if(pic16_options.gstack)
2524 pic16_testStackOverflow();
2527 #if !(USE_GENERIC_SIGNED_SHIFT)
2528 /*-----------------------------------------------------------------*/
2529 /* reAdjustPreg - points a register back to where it should */
2530 /*-----------------------------------------------------------------*/
2531 static void reAdjustPreg (asmop *aop)
2535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2537 if ((size = aop->size) <= 1)
2540 switch (aop->type) {
2544 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2548 if (aop->type == AOP_DPTR2)
2554 pic16_emitcode("lcall","__decdptr");
2557 if (aop->type == AOP_DPTR2)
2569 /*-----------------------------------------------------------------*/
2570 /* opIsGptr: returns non-zero if the passed operand is */
2571 /* a generic pointer type. */
2572 /*-----------------------------------------------------------------*/
2573 static int opIsGptr(operand *op)
2575 sym_link *type = operandType(op);
2577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2578 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2586 /*-----------------------------------------------------------------*/
2587 /* pic16_getDataSize - get the operand data size */
2588 /*-----------------------------------------------------------------*/
2589 int pic16_getDataSize(operand *op)
2591 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2594 return AOP_SIZE(op);
2596 // tsd- in the pic port, the genptr size is 1, so this code here
2597 // fails. ( in the 8051 port, the size was 4).
2600 size = AOP_SIZE(op);
2601 if (size == GPTRSIZE)
2603 sym_link *type = operandType(op);
2604 if (IS_GENPTR(type))
2606 /* generic pointer; arithmetic operations
2607 * should ignore the high byte (pointer type).
2610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2617 /*-----------------------------------------------------------------*/
2618 /* pic16_outAcc - output Acc */
2619 /*-----------------------------------------------------------------*/
2620 void pic16_outAcc(operand *result)
2623 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2624 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2627 size = pic16_getDataSize(result);
2629 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2632 /* unsigned or positive */
2634 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2639 /*-----------------------------------------------------------------*/
2640 /* pic16_outBitC - output a bit C */
2641 /* Move to result the value of Carry flag -- VR */
2642 /*-----------------------------------------------------------------*/
2643 void pic16_outBitC(operand *result)
2647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2649 /* if the result is bit */
2650 if (AOP_TYPE(result) == AOP_CRY) {
2651 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2652 pic16_aopPut(AOP(result),"c",0);
2655 i = AOP_SIZE(result);
2657 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2659 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_outBitOp - output a bit from Op */
2665 /* Move to result the value of set/clr op -- VR */
2666 /*-----------------------------------------------------------------*/
2667 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2673 /* if the result is bit */
2674 if (AOP_TYPE(result) == AOP_CRY) {
2675 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2676 pic16_aopPut(AOP(result),"c",0);
2679 i = AOP_SIZE(result);
2681 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2683 pic16_emitpcode(POC_RRCF, pcop);
2684 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2688 /*-----------------------------------------------------------------*/
2689 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2690 /*-----------------------------------------------------------------*/
2691 void pic16_toBoolean(operand *oper)
2693 int size = AOP_SIZE(oper) - 1;
2696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2698 if ( AOP_TYPE(oper) != AOP_ACC) {
2699 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2702 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2706 /*-----------------------------------------------------------------*/
2707 /* genUminusFloat - unary minus for floating points */
2708 /*-----------------------------------------------------------------*/
2709 static void genUminusFloat(operand *op,operand *result)
2711 int size ,offset =0 ;
2714 /* for this we just need to flip the
2715 first it then copy the rest in place */
2716 size = AOP_SIZE(op);
2717 assert( size == AOP_SIZE(result) );
2720 pic16_mov2f(AOP(result), AOP(op), offset);
2724 /* toggle the MSB's highest bit */
2725 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2728 /*-----------------------------------------------------------------*/
2729 /* genUminus - unary minus code generation */
2730 /*-----------------------------------------------------------------*/
2731 static void genUminus (iCode *ic)
2734 sym_link *optype, *rtype;
2741 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2742 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2744 /* if both in bit space then special case */
2745 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2746 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2748 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2749 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2750 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2754 optype = operandType(IC_LEFT(ic));
2755 rtype = operandType(IC_RESULT(ic));
2758 /* if float then do float stuff */
2759 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2760 if(IS_FIXED(optype))
2761 debugf("implement fixed16x16 type\n", 0);
2763 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2767 /* otherwise subtract from zero by taking the 2's complement */
2768 size = AOP_SIZE(IC_LEFT(ic));
2769 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2770 label = newiTempLabel ( NULL );
2772 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2773 for (i=size-1; i > 0; i--) {
2774 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2776 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2777 for (i=1; i < size; i++) {
2778 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2779 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2782 for (i=size-1; i >= 0; i--) {
2783 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2784 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2787 for (i=0; i < size-2; i++) {
2788 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2789 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2791 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2793 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2796 pic16_emitpLabel (label->key);
2799 /* release the aops */
2800 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2801 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2805 /*-----------------------------------------------------------------*/
2806 /* saveRegisters - will look for a call and save the registers */
2807 /*-----------------------------------------------------------------*/
2808 static void saveRegisters(iCode *lic)
2815 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2817 for (ic = lic ; ic ; ic = ic->next)
2818 if (ic->op == CALL || ic->op == PCALL)
2822 fprintf(stderr,"found parameter push with no function call\n");
2826 /* if the registers have been saved already then
2828 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2831 /* find the registers in use at this time
2832 and push them away to safety */
2833 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2837 if (options.useXstack) {
2838 if (bitVectBitValue(rsave,R0_IDX))
2839 pic16_emitcode("mov","b,r0");
2840 pic16_emitcode("mov","r0,%s",spname);
2841 for (i = 0 ; i < pic16_nRegs ; i++) {
2842 if (bitVectBitValue(rsave,i)) {
2844 pic16_emitcode("mov","a,b");
2846 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2847 pic16_emitcode("movx","@r0,a");
2848 pic16_emitcode("inc","r0");
2851 pic16_emitcode("mov","%s,r0",spname);
2852 if (bitVectBitValue(rsave,R0_IDX))
2853 pic16_emitcode("mov","r0,b");
2855 //for (i = 0 ; i < pic16_nRegs ; i++) {
2856 // if (bitVectBitValue(rsave,i))
2857 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2860 dtype = operandType(IC_LEFT(ic));
2861 if (currFunc && dtype &&
2862 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2863 IFFUNC_ISISR(currFunc->type) &&
2866 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2869 /*-----------------------------------------------------------------*/
2870 /* unsaveRegisters - pop the pushed registers */
2871 /*-----------------------------------------------------------------*/
2872 static void unsaveRegisters (iCode *ic)
2877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2878 /* find the registers in use at this time
2879 and push them away to safety */
2880 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2883 if (options.useXstack) {
2884 pic16_emitcode("mov","r0,%s",spname);
2885 for (i = pic16_nRegs ; i >= 0 ; i--) {
2886 if (bitVectBitValue(rsave,i)) {
2887 pic16_emitcode("dec","r0");
2888 pic16_emitcode("movx","a,@r0");
2890 pic16_emitcode("mov","b,a");
2892 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2896 pic16_emitcode("mov","%s,r0",spname);
2897 if (bitVectBitValue(rsave,R0_IDX))
2898 pic16_emitcode("mov","r0,b");
2900 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2901 // if (bitVectBitValue(rsave,i))
2902 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2909 /*-----------------------------------------------------------------*/
2911 /*-----------------------------------------------------------------*/
2912 static void pushSide(operand * oper, int size)
2915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2917 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2918 if (AOP_TYPE(oper) != AOP_REG &&
2919 AOP_TYPE(oper) != AOP_DIR &&
2921 pic16_emitcode("mov","a,%s",l);
2922 pic16_emitcode("push","acc");
2924 pic16_emitcode("push","%s",l);
2929 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2931 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2932 pic16_emitpcode(POC_MOVFW, src);
2933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2935 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2936 src, pic16_popGet(AOP(op), offset)));
2941 /*-----------------------------------------------------------------*/
2942 /* assignResultValue - assign results to oper, rescall==1 is */
2943 /* called from genCall() or genPcall() */
2944 /*-----------------------------------------------------------------*/
2945 static void assignResultValue(operand * oper, int rescall)
2947 int size = AOP_SIZE(oper);
2951 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2952 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2955 /* assign result from a call/pcall function() */
2957 /* function results are stored in a special order,
2958 * see top of file with Function return policy, or manual */
2961 /* 8-bits, result in WREG */
2962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2965 /* 16-bits, result in PRODL:WREG */
2966 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2970 /* 24-bits, result in PRODH:PRODL:WREG */
2971 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2975 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2976 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2980 /* >32-bits, result on stack, and FSR0 points to beginning.
2981 * Fix stack when done */
2983 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2985 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2986 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2988 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2994 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2995 if(STACK_MODEL_LARGE) {
2997 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3001 int areg = 0; /* matching argument register */
3003 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3004 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3007 /* its called from genReceive (probably) -- VR */
3008 /* I hope this code will not be called from somewhere else in the future!
3009 * We manually set the pseudo stack pointer in genReceive. - dw
3011 if(!GpsuedoStkPtr && _G.useWreg) {
3012 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3014 /* The last byte in the assignment is in W */
3015 if(areg <= GpsuedoStkPtr) {
3017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3019 // debugf("receive from WREG\n", 0);
3021 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3024 _G.stack_lat = AOP_SIZE(oper)-1;
3029 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3030 // debugf("receive from STACK\n", 0);
3037 /*-----------------------------------------------------------------*/
3038 /* genIpush - generate code for pushing this gets a little complex */
3039 /*-----------------------------------------------------------------*/
3040 static void genIpush (iCode *ic)
3042 // int size, offset=0;
3045 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3048 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3050 /* send to stack as normal */
3051 addSet(&_G.sendSet,ic);
3052 // addSetHead(&_G.sendSet,ic);
3053 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3058 int size, offset = 0 ;
3062 /* if this is not a parm push : ie. it is spill push
3063 and spill push is always done on the local stack */
3064 if (!ic->parmPush) {
3066 /* and the item is spilt then do nothing */
3067 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3070 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3071 size = AOP_SIZE(IC_LEFT(ic));
3072 /* push it on the stack */
3074 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3079 pic16_emitcode("push","%s",l);
3084 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3088 /*-----------------------------------------------------------------*/
3089 /* genIpop - recover the registers: can happen only for spilling */
3090 /*-----------------------------------------------------------------*/
3091 static void genIpop (iCode *ic)
3094 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3099 /* if the temp was not pushed then */
3100 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3103 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3104 size = AOP_SIZE(IC_LEFT(ic));
3107 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3110 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3115 /*-----------------------------------------------------------------*/
3116 /* unsaverbank - restores the resgister bank from stack */
3117 /*-----------------------------------------------------------------*/
3118 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3120 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3126 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3128 if (options.useXstack) {
3130 r = getFreePtr(ic,&aop,FALSE);
3133 pic16_emitcode("mov","%s,_spx",r->name);
3134 pic16_emitcode("movx","a,@%s",r->name);
3135 pic16_emitcode("mov","psw,a");
3136 pic16_emitcode("dec","%s",r->name);
3139 pic16_emitcode ("pop","psw");
3142 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3143 if (options.useXstack) {
3144 pic16_emitcode("movx","a,@%s",r->name);
3145 //pic16_emitcode("mov","(%s+%d),a",
3146 // regspic16[i].base,8*bank+regspic16[i].offset);
3147 pic16_emitcode("dec","%s",r->name);
3150 pic16_emitcode("pop",""); //"(%s+%d)",
3151 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3154 if (options.useXstack) {
3156 pic16_emitcode("mov","_spx,%s",r->name);
3157 pic16_freeAsmop(NULL,aop,ic,TRUE);
3163 /*-----------------------------------------------------------------*/
3164 /* saverbank - saves an entire register bank on the stack */
3165 /*-----------------------------------------------------------------*/
3166 static void saverbank (int bank, iCode *ic, bool pushPsw)
3168 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3175 if (options.useXstack) {
3178 r = getFreePtr(ic,&aop,FALSE);
3179 pic16_emitcode("mov","%s,_spx",r->name);
3183 for (i = 0 ; i < pic16_nRegs ;i++) {
3184 if (options.useXstack) {
3185 pic16_emitcode("inc","%s",r->name);
3186 //pic16_emitcode("mov","a,(%s+%d)",
3187 // regspic16[i].base,8*bank+regspic16[i].offset);
3188 pic16_emitcode("movx","@%s,a",r->name);
3190 pic16_emitcode("push","");// "(%s+%d)",
3191 //regspic16[i].base,8*bank+regspic16[i].offset);
3195 if (options.useXstack) {
3196 pic16_emitcode("mov","a,psw");
3197 pic16_emitcode("movx","@%s,a",r->name);
3198 pic16_emitcode("inc","%s",r->name);
3199 pic16_emitcode("mov","_spx,%s",r->name);
3200 pic16_freeAsmop (NULL,aop,ic,TRUE);
3203 pic16_emitcode("push","psw");
3205 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3213 static int wparamCmp(void *p1, void *p2)
3215 return (!strcmp((char *)p1, (char *)p2));
3218 int inWparamList(char *s)
3220 return isinSetWith(wparamList, s, wparamCmp);
3224 /*-----------------------------------------------------------------*/
3225 /* genCall - generates a call statement */
3226 /*-----------------------------------------------------------------*/
3227 static void genCall (iCode *ic)
3237 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3238 /* if caller saves & we have not saved then */
3239 // if (!ic->regsSaved)
3240 // saveRegisters(ic);
3242 /* initialise stackParms for IPUSH pushes */
3243 // stackParms = psuedoStkPtr;
3244 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3245 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3246 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3249 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3252 /* if send set is not empty the assign */
3255 int psuedoStkPtr=-1;
3256 int firstTimeThruLoop = 1;
3259 /* reverse sendSet if function is not reentrant */
3260 if(!IFFUNC_ISREENT(ftype))
3261 _G.sendSet = reverseSet(_G.sendSet);
3263 /* First figure how many parameters are getting passed */
3267 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3271 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3272 size = AOP_SIZE(IC_LEFT(sic));
3276 /* pass the last byte through WREG */
3280 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3281 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3282 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3284 if(!firstTimeThruLoop) {
3285 /* If this is not the first time we've been through the loop
3286 * then we need to save the parameter in a temporary
3287 * register. The last byte of the last parameter is
3291 // --psuedoStkPtr; // sanity check
3295 firstTimeThruLoop=0;
3297 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3302 /* all arguments are passed via stack */
3306 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3307 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3308 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3310 // pushaop(AOP(IC_LEFT(sic)), size);
3311 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3318 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3322 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3323 pushw(); /* save last parameter to stack if functions has varargs */
3327 } else use_wreg = 0;
3329 _G.stackRegSet = _G.sendSet;
3334 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3338 /* if we need to assign a result value */
3339 if ((IS_ITEMP(IC_RESULT(ic))
3340 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3341 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3342 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3345 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3348 assignResultValue(IC_RESULT(ic), 1);
3350 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3351 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3353 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3356 if(!stackParms && ic->parmBytes) {
3357 stackParms = ic->parmBytes;
3360 stackParms -= use_wreg;
3363 if(stackParms == 1) {
3364 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3366 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3367 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3369 if(STACK_MODEL_LARGE) {
3371 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3376 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3379 /* adjust the stack for parameters if required */
3380 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3383 /* if register bank was saved then pop them */
3385 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3387 /* if we hade saved some registers then unsave them */
3388 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3389 unsaveRegisters (ic);
3395 /*-----------------------------------------------------------------*/
3396 /* genPcall - generates a call by pointer statement */
3397 /* new version, created from genCall - HJD */
3398 /*-----------------------------------------------------------------*/
3399 static void genPcall (iCode *ic)
3403 symbol *retlbl = newiTempLabel(NULL);
3404 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3408 fntype = operandType( IC_LEFT(ic) )->next;
3410 /* if send set is not empty the assign */
3413 int psuedoStkPtr=-1;
3415 /* reverse sendSet if function is not reentrant */
3416 if(!IFFUNC_ISREENT(fntype))
3417 _G.sendSet = reverseSet(_G.sendSet);
3421 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3424 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3425 size = AOP_SIZE(IC_LEFT(sic));
3428 /* all parameters are passed via stack, since WREG is clobbered
3429 * by the calling sequence */
3431 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3432 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3433 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3435 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3439 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3442 _G.stackRegSet = _G.sendSet;
3446 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3448 // push return address
3449 // push $ on return stack, then replace with retlbl
3451 /* Thanks to Thorsten Klose for pointing out that the following
3452 * snippet should be interrupt safe */
3453 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3454 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3456 pic16_emitpcodeNULLop(POC_PUSH);
3458 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3459 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3460 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3461 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3462 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3463 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3466 /* restore interrupt control register */
3467 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3468 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3470 /* make the call by writing the pointer into pc */
3471 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3472 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3474 // note: MOVFF to PCL not allowed
3475 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3476 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3479 /* return address is here: (X) */
3480 pic16_emitpLabelFORCE(retlbl->key);
3482 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3485 /* if we need assign a result value */
3486 if ((IS_ITEMP(IC_RESULT(ic))
3487 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3488 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3489 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3492 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3495 assignResultValue(IC_RESULT(ic), 1);
3497 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3500 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3503 // stackParms -= use_wreg;
3506 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3507 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3508 if(STACK_MODEL_LARGE) {
3510 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3515 /*-----------------------------------------------------------------*/
3516 /* resultRemat - result is rematerializable */
3517 /*-----------------------------------------------------------------*/
3518 static int resultRemat (iCode *ic)
3520 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3521 if (SKIP_IC(ic) || ic->op == IFX)
3524 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3525 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3526 if (sym->remat && !POINTER_SET(ic))
3533 #if defined(__BORLANDC__) || defined(_MSC_VER)
3534 #define STRCASECMP stricmp
3536 #define STRCASECMP strcasecmp
3540 /*-----------------------------------------------------------------*/
3541 /* inExcludeList - return 1 if the string is in exclude Reg list */
3542 /*-----------------------------------------------------------------*/
3543 static bool inExcludeList(char *s)
3545 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3549 if (options.excludeRegs[i] &&
3550 STRCASECMP(options.excludeRegs[i],"none") == 0)
3553 for ( i = 0 ; options.excludeRegs[i]; i++) {
3554 if (options.excludeRegs[i] &&
3555 STRCASECMP(s,options.excludeRegs[i]) == 0)
3562 /*-----------------------------------------------------------------*/
3563 /* genFunction - generated code for function entry */
3564 /*-----------------------------------------------------------------*/
3565 static void genFunction (iCode *ic)
3571 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3573 pic16_labelOffset += (max_key+4);
3578 ftype = operandType(IC_LEFT(ic));
3579 sym = OP_SYMBOL(IC_LEFT(ic));
3581 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3582 /* create an absolute section at the interrupt vector:
3583 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3588 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3590 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3591 sprintf(asymname, "ivec_%s", sym->name);
3593 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3595 /* when an interrupt is declared as naked, do not emit the special
3596 * wrapper segment at vector address. The user should take care for
3597 * this instead. -- VR */
3599 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3600 asym = newSymbol(asymname, 0);
3601 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3602 pic16_addpBlock( apb );
3604 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3605 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3606 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3607 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3608 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3610 /* mark the end of this tiny function */
3611 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3613 sprintf(asymname, "%s", sym->rname);
3619 abSym = Safe_calloc(1, sizeof(absSym));
3620 strcpy(abSym->name, asymname);
3622 switch( FUNC_INTNO(sym->type) ) {
3623 case 0: abSym->address = 0x000000; break;
3624 case 1: abSym->address = 0x000008; break;
3625 case 2: abSym->address = 0x000018; break;
3628 // fprintf(stderr, "no interrupt number is given\n");
3629 abSym->address = -1; break;
3632 /* relocate interrupt vectors if needed */
3633 if(abSym->address != -1)
3634 abSym->address += pic16_options.ivt_loc;
3636 addSet(&absSymSet, abSym);
3640 /* create the function header */
3641 pic16_emitcode(";","-----------------------------------------");
3642 pic16_emitcode(";"," function %s",sym->name);
3643 pic16_emitcode(";","-----------------------------------------");
3645 pic16_emitcode("","%s:",sym->rname);
3646 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3651 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3652 if(!strcmp(ab->name, sym->rname)) {
3653 pic16_pBlockConvert2Absolute(pb);
3659 if(IFFUNC_ISNAKED(ftype)) {
3660 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3664 /* if critical function then turn interrupts off */
3665 if (IFFUNC_ISCRITICAL(ftype)) {
3666 //pic16_emitcode("clr","ea");
3669 currFunc = sym; /* update the currFunc symbol */
3670 _G.fregsUsed = sym->regsUsed;
3671 _G.sregsAlloc = newBitVect(128);
3674 /* if this is an interrupt service routine then
3675 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3676 if (IFFUNC_ISISR(sym->type)) {
3677 _G.usefastretfie = 1; /* use shadow registers by default */
3679 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3680 if(!FUNC_ISSHADOWREGS(sym->type)) {
3681 /* do not save WREG,STATUS,BSR for high priority interrupts
3682 * because they are stored in the hardware shadow registers already */
3683 _G.usefastretfie = 0;
3684 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3685 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3686 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3689 /* these should really be optimized somehow, because not all
3690 * interrupt handlers modify them */
3691 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3692 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3693 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3694 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3696 // pic16_pBlockConvert2ISR(pb);
3699 /* emit code to setup stack frame if user enabled,
3700 * and function is not main() */
3702 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3703 if(strcmp(sym->name, "main")) {
3705 || !options.ommitFramePtr
3707 || IFFUNC_ARGS(sym->type)
3708 || FUNC_HASSTACKPARM(sym->etype)
3710 /* setup the stack frame */
3711 if(STACK_MODEL_LARGE)
3712 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3713 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3715 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3716 if(STACK_MODEL_LARGE)
3717 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3721 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3724 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3726 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3727 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3729 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3732 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3733 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3740 /* if callee-save to be used for this function
3741 * then save the registers being used in this function */
3742 // if (IFFUNC_CALLEESAVES(sym->type))
3743 if(strcmp(sym->name, "main")) {
3746 /* if any registers used */
3747 if (sym->regsUsed) {
3748 /* save the registers used */
3749 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3750 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3751 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3752 if (bitVectBitValue(sym->regsUsed,i)) {
3753 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3756 if(!pic16_regWithIdx(i)->wasUsed) {
3757 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3758 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3759 pic16_regWithIdx(i)->wasUsed = 1;
3763 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3767 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3768 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3771 /*-----------------------------------------------------------------*/
3772 /* genEndFunction - generates epilogue for functions */
3773 /*-----------------------------------------------------------------*/
3774 static void genEndFunction (iCode *ic)
3776 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3780 if(IFFUNC_ISNAKED(sym->type)) {
3781 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3787 /* add code for ISCRITICAL */
3788 if(IFFUNC_ISCRITICAL(sym->type)) {
3789 /* if critical function, turn on interrupts */
3791 /* TODO: add code here -- VR */
3794 // sym->regsUsed = _G.fregsUsed;
3796 /* now we need to restore the registers */
3797 /* if any registers used */
3799 /* first restore registers that might be used for stack access */
3800 if(_G.sregsAllocSet) {
3803 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3804 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3805 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3809 if (strcmp(sym->name, "main") && sym->regsUsed) {
3812 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3813 /* restore registers used */
3814 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3815 for ( i = sym->regsUsed->size; i >= 0; i--) {
3816 if (bitVectBitValue(sym->regsUsed,i)) {
3817 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3821 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3826 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3828 if (sym->stack == 1) {
3829 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3830 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3832 // we have to add more than one...
3833 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3834 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3835 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3837 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3838 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3839 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3843 if(strcmp(sym->name, "main")) {
3845 || !options.ommitFramePtr
3847 || IFFUNC_ARGS(sym->type)
3848 || FUNC_HASSTACKPARM(sym->etype)
3850 /* restore stack frame */
3851 if(STACK_MODEL_LARGE)
3852 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3853 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3859 if (IFFUNC_ISISR(sym->type)) {
3860 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3861 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3862 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3863 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3865 if(!FUNC_ISSHADOWREGS(sym->type)) {
3866 /* do not restore interrupt vector for WREG,STATUS,BSR
3867 * for high priority interrupt, see genFunction */
3868 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3869 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3870 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3872 // _G.interruptvector = 0; /* sanity check */
3875 /* if debug then send end of function */
3876 /* if (options.debug && currFunc) */
3878 debugFile->writeEndFunction (currFunc, ic, 1);
3881 if(_G.usefastretfie)
3882 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3884 pic16_emitpcodeNULLop(POC_RETFIE);
3886 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3888 _G.usefastretfie = 0;
3892 if (IFFUNC_ISCRITICAL(sym->type)) {
3893 pic16_emitcode("setb","ea");
3896 /* if debug then send end of function */
3898 debugFile->writeEndFunction (currFunc, ic, 1);
3901 /* insert code to restore stack frame, if user enabled it
3902 * and function is not main() */
3905 pic16_emitpcodeNULLop(POC_RETURN);
3907 /* Mark the end of a function */
3908 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3912 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3914 unsigned long lit=1;
3919 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3920 if(AOP_TYPE(op) == AOP_LIT) {
3921 if(!IS_FLOAT(operandType( op ))) {
3922 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3925 unsigned long lit_int;
3929 /* take care if literal is a float */
3930 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3936 pic16_movLit2f(dest, lit);
3938 if(dest->type == PO_WREG && (offset == 0)) {
3939 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3942 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3946 /*-----------------------------------------------------------------*/
3947 /* genRet - generate code for return statement */
3948 /*-----------------------------------------------------------------*/
3949 static void genRet (iCode *ic)
3955 /* if we have no return value then
3956 * just generate the "ret" */
3961 /* we have something to return then
3962 * move the return value into place */
3963 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3964 size = AOP_SIZE(IC_LEFT(ic));
3968 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3971 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3974 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3976 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3979 /* >32-bits, setup stack and FSR0 */
3981 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3982 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3984 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3986 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3991 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3992 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3994 if(STACK_MODEL_LARGE) {
3995 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3996 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3998 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4003 /* old code, left here for reference -- VR */
4007 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4009 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4010 pic16_emitpcomment("push %s",l);
4013 DEBUGpic16_emitcode(";", "%d", __LINE__);
4014 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4015 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4017 if (strcmp(fReturn[offset],l)) {
4018 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4019 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4020 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4022 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4026 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4036 if (strcmp(fReturn[pushed],"a"))
4037 pic16_emitcode("pop",fReturn[pushed]);
4039 pic16_emitcode("pop","acc");
4045 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4048 /* generate a jump to the return label
4049 * if the next is not the return statement */
4050 if (!(ic->next && ic->next->op == LABEL
4051 && IC_LABEL(ic->next) == returnLabel)) {
4053 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4054 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4058 /*-----------------------------------------------------------------*/
4059 /* genLabel - generates a label */
4060 /*-----------------------------------------------------------------*/
4061 static void genLabel (iCode *ic)
4065 /* special case never generate */
4066 if (IC_LABEL(ic) == entryLabel)
4069 pic16_emitpLabel(IC_LABEL(ic)->key);
4070 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4073 /*-----------------------------------------------------------------*/
4074 /* genGoto - generates a goto */
4075 /*-----------------------------------------------------------------*/
4077 static void genGoto (iCode *ic)
4080 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4081 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4085 /*-----------------------------------------------------------------*/
4086 /* genMultbits :- multiplication of bits */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultbits (operand *left,
4094 if(!pic16_sameRegs(AOP(result),AOP(right)))
4095 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4097 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4098 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4099 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4104 /*-----------------------------------------------------------------*/
4105 /* genMultOneByte : 8 bit multiplication & division */
4106 /*-----------------------------------------------------------------*/
4107 static void genMultOneByte (operand *left,
4113 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4114 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4116 /* (if two literals, the value is computed before) */
4117 /* if one literal, literal on the right */
4118 if (AOP_TYPE(left) == AOP_LIT){
4124 /* size is already checked in genMult == 1 */
4125 // size = AOP_SIZE(result);
4127 if (AOP_TYPE(right) == AOP_LIT){
4128 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4129 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4130 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4131 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4133 pic16_emitpcomment("multiply variable :%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));
4139 pic16_genMult8X8_8 (left, right,result);
4142 /*-----------------------------------------------------------------*/
4143 /* genMultOneWord : 16 bit multiplication */
4144 /*-----------------------------------------------------------------*/
4145 static void genMultOneWord (operand *left,
4150 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4151 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4153 /* (if two literals, the value is computed before)
4154 * if one literal, literal on the right */
4155 if (AOP_TYPE(left) == AOP_LIT){
4161 /* size is checked already == 2 */
4162 // size = AOP_SIZE(result);
4164 if (AOP_TYPE(right) == AOP_LIT) {
4165 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4166 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4167 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4168 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4170 pic16_emitpcomment("multiply variable :%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));
4176 pic16_genMult16X16_16(left, right,result);
4179 /*-----------------------------------------------------------------*/
4180 /* genMultOneLong : 32 bit multiplication */
4181 /*-----------------------------------------------------------------*/
4182 static void genMultOneLong (operand *left,
4187 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4190 /* (if two literals, the value is computed before)
4191 * if one literal, literal on the right */
4192 if (AOP_TYPE(left) == AOP_LIT){
4198 /* size is checked already == 4 */
4199 // size = AOP_SIZE(result);
4201 if (AOP_TYPE(right) == AOP_LIT) {
4202 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4203 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4204 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207 pic16_emitpcomment("multiply variable :%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));
4213 pic16_genMult32X32_32(left, right,result);
4218 /*-----------------------------------------------------------------*/
4219 /* genMult - generates code for multiplication */
4220 /*-----------------------------------------------------------------*/
4221 static void genMult (iCode *ic)
4223 operand *left = IC_LEFT(ic);
4224 operand *right = IC_RIGHT(ic);
4225 operand *result= IC_RESULT(ic);
4228 /* assign the amsops */
4229 pic16_aopOp (left,ic,FALSE);
4230 pic16_aopOp (right,ic,FALSE);
4231 pic16_aopOp (result,ic,TRUE);
4233 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4235 /* special cases first *
4237 if (AOP_TYPE(left) == AOP_CRY
4238 && AOP_TYPE(right)== AOP_CRY) {
4239 genMultbits(left,right,result);
4243 /* if both are of size == 1 */
4244 if(AOP_SIZE(left) == 1
4245 && AOP_SIZE(right) == 1) {
4246 genMultOneByte(left,right,result);
4250 /* if both are of size == 2 */
4251 if(AOP_SIZE(left) == 2
4252 && AOP_SIZE(right) == 2) {
4253 genMultOneWord(left, right, result);
4257 /* if both are of size == 4 */
4258 if(AOP_SIZE(left) == 4
4259 && AOP_SIZE(right) == 4) {
4260 genMultOneLong(left, right, result);
4264 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4267 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4268 /* should have been converted to function call */
4272 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4274 pic16_freeAsmop(result,NULL,ic,TRUE);
4277 /*-----------------------------------------------------------------*/
4278 /* genDivbits :- division of bits */
4279 /*-----------------------------------------------------------------*/
4280 static void genDivbits (operand *left,
4287 /* the result must be bit */
4288 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4289 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4293 pic16_emitcode("div","ab");
4294 pic16_emitcode("rrc","a");
4295 pic16_aopPut(AOP(result),"c",0);
4298 /*-----------------------------------------------------------------*/
4299 /* genDivOneByte : 8 bit division */
4300 /*-----------------------------------------------------------------*/
4301 static void genDivOneByte (operand *left,
4305 sym_link *opetype = operandType(result);
4310 /* result = divident / divisor
4311 * - divident may be a register or a literal,
4312 * - divisor may be a register or a literal,
4313 * so there are 3 cases (literal / literal is optimized
4314 * by the front-end) to handle.
4315 * In addition we must handle signed and unsigned, which
4316 * result in 6 final different cases -- VR */
4320 size = AOP_SIZE(result) - 1;
4322 /* signed or unsigned */
4323 if (SPEC_USIGN(opetype)) {
4324 pCodeOp *pct1, /* count */
4327 symbol *label1, *label2, *label3;;
4330 /* unsigned is easy */
4332 pct1 = pic16_popGetTempReg(1);
4333 pct2 = pic16_popGetTempReg(1);
4334 pct3 = pic16_popGetTempReg(1);
4336 label1 = newiTempLabel(NULL);
4337 label2 = newiTempLabel(NULL);
4338 label3 = newiTempLabel(NULL);
4340 /* the following algorithm is extracted from divuint.c */
4342 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4343 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4345 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4349 pic16_emitpLabel(label1->key);
4352 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4356 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4360 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4362 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4365 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4366 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4367 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4369 pic16_emitpLabel( label3->key );
4370 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4371 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4375 pic16_emitpLabel(label2->key);
4376 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4377 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4378 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4380 /* result is in wreg */
4381 if(AOP_TYPE(result) != AOP_ACC)
4382 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4384 pic16_popReleaseTempReg( pct3, 1);
4385 pic16_popReleaseTempReg( pct2, 1);
4386 pic16_popReleaseTempReg( pct1, 1);
4391 /* signed is a little bit more difficult */
4393 /* save the signs of the operands */
4394 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4396 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4397 pic16_emitcode("push","acc"); /* save it on the stack */
4399 /* now sign adjust for both left & right */
4400 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4402 lbl = newiTempLabel(NULL);
4403 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4404 pic16_emitcode("cpl","a");
4405 pic16_emitcode("inc","a");
4406 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4407 pic16_emitcode("mov","b,a");
4409 /* sign adjust left side */
4410 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4413 lbl = newiTempLabel(NULL);
4414 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4415 pic16_emitcode("cpl","a");
4416 pic16_emitcode("inc","a");
4417 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4419 /* now the division */
4420 pic16_emitcode("div","ab");
4421 /* we are interested in the lower order
4423 pic16_emitcode("mov","b,a");
4424 lbl = newiTempLabel(NULL);
4425 pic16_emitcode("pop","acc");
4426 /* if there was an over flow we don't
4427 adjust the sign of the result */
4428 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4429 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4431 pic16_emitcode("clr","a");
4432 pic16_emitcode("subb","a,b");
4433 pic16_emitcode("mov","b,a");
4434 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4436 /* now we are done */
4437 pic16_aopPut(AOP(result),"b",0);
4439 pic16_emitcode("mov","c,b.7");
4440 pic16_emitcode("subb","a,acc");
4443 pic16_aopPut(AOP(result),"a",offset++);
4447 /*-----------------------------------------------------------------*/
4448 /* genDiv - generates code for division */
4449 /*-----------------------------------------------------------------*/
4450 static void genDiv (iCode *ic)
4452 operand *left = IC_LEFT(ic);
4453 operand *right = IC_RIGHT(ic);
4454 operand *result= IC_RESULT(ic);
4457 /* Division is a very lengthy algorithm, so it is better
4458 * to call support routines than inlining algorithm.
4459 * Division functions written here just in case someone
4460 * wants to inline and not use the support libraries -- VR */
4464 /* assign the amsops */
4465 pic16_aopOp (left,ic,FALSE);
4466 pic16_aopOp (right,ic,FALSE);
4467 pic16_aopOp (result,ic,TRUE);
4469 /* special cases first */
4471 if (AOP_TYPE(left) == AOP_CRY &&
4472 AOP_TYPE(right)== AOP_CRY) {
4473 genDivbits(left,right,result);
4477 /* if both are of size == 1 */
4478 if (AOP_SIZE(left) == 1 &&
4479 AOP_SIZE(right) == 1 ) {
4480 genDivOneByte(left,right,result);
4484 /* should have been converted to function call */
4487 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489 pic16_freeAsmop(result,NULL,ic,TRUE);
4492 /*-----------------------------------------------------------------*/
4493 /* genModbits :- modulus of bits */
4494 /*-----------------------------------------------------------------*/
4495 static void genModbits (operand *left,
4503 werror(W_POSSBUG2, __FILE__, __LINE__);
4504 /* the result must be bit */
4505 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4506 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4510 pic16_emitcode("div","ab");
4511 pic16_emitcode("mov","a,b");
4512 pic16_emitcode("rrc","a");
4513 pic16_aopPut(AOP(result),"c",0);
4516 /*-----------------------------------------------------------------*/
4517 /* genModOneByte : 8 bit modulus */
4518 /*-----------------------------------------------------------------*/
4519 static void genModOneByte (operand *left,
4523 sym_link *opetype = operandType(result);
4528 werror(W_POSSBUG2, __FILE__, __LINE__);
4530 /* signed or unsigned */
4531 if (SPEC_USIGN(opetype)) {
4532 /* unsigned is easy */
4533 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4534 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4536 pic16_emitcode("div","ab");
4537 pic16_aopPut(AOP(result),"b",0);
4541 /* signed is a little bit more difficult */
4543 /* save the signs of the operands */
4544 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4547 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4548 pic16_emitcode("push","acc"); /* save it on the stack */
4550 /* now sign adjust for both left & right */
4551 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4554 lbl = newiTempLabel(NULL);
4555 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4556 pic16_emitcode("cpl","a");
4557 pic16_emitcode("inc","a");
4558 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4559 pic16_emitcode("mov","b,a");
4561 /* sign adjust left side */
4562 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4565 lbl = newiTempLabel(NULL);
4566 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4567 pic16_emitcode("cpl","a");
4568 pic16_emitcode("inc","a");
4569 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4571 /* now the multiplication */
4572 pic16_emitcode("div","ab");
4573 /* we are interested in the lower order
4575 lbl = newiTempLabel(NULL);
4576 pic16_emitcode("pop","acc");
4577 /* if there was an over flow we don't
4578 adjust the sign of the result */
4579 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4580 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4582 pic16_emitcode("clr","a");
4583 pic16_emitcode("subb","a,b");
4584 pic16_emitcode("mov","b,a");
4585 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4587 /* now we are done */
4588 pic16_aopPut(AOP(result),"b",0);
4592 /*-----------------------------------------------------------------*/
4593 /* genMod - generates code for division */
4594 /*-----------------------------------------------------------------*/
4595 static void genMod (iCode *ic)
4597 operand *left = IC_LEFT(ic);
4598 operand *right = IC_RIGHT(ic);
4599 operand *result= IC_RESULT(ic);
4603 /* assign the amsops */
4604 pic16_aopOp (left,ic,FALSE);
4605 pic16_aopOp (right,ic,FALSE);
4606 pic16_aopOp (result,ic,TRUE);
4608 /* special cases first */
4610 if (AOP_TYPE(left) == AOP_CRY &&
4611 AOP_TYPE(right)== AOP_CRY) {
4612 genModbits(left,right,result);
4616 /* if both are of size == 1 */
4617 if (AOP_SIZE(left) == 1 &&
4618 AOP_SIZE(right) == 1 ) {
4619 genModOneByte(left,right,result);
4623 /* should have been converted to function call */
4627 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629 pic16_freeAsmop(result,NULL,ic,TRUE);
4632 /*-----------------------------------------------------------------*/
4633 /* genIfxJump :- will create a jump depending on the ifx */
4634 /*-----------------------------------------------------------------*/
4636 note: May need to add parameter to indicate when a variable is in bit space.
4638 static void genIfxJump (iCode *ic, char *jval)
4642 /* if true label then we jump if condition
4644 if ( IC_TRUE(ic) ) {
4646 if(strcmp(jval,"a") == 0)
4648 else if (strcmp(jval,"c") == 0)
4651 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4652 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4655 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4656 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4660 /* false label is present */
4661 if(strcmp(jval,"a") == 0)
4663 else if (strcmp(jval,"c") == 0)
4666 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4667 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4670 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4671 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4676 /* mark the icode as generated */
4680 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4684 /* if true label then we jump if condition
4686 if ( IC_TRUE(ic) ) {
4687 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4688 pic16_emitpcode(POC_BTFSC, jop);
4690 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4691 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4694 /* false label is present */
4695 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4696 pic16_emitpcode(POC_BTFSS, jop);
4698 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4699 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4703 /* mark the icode as generated */
4710 /*-----------------------------------------------------------------*/
4712 /*-----------------------------------------------------------------*/
4713 static void genSkip(iCode *ifx,int status_bit)
4715 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4719 if ( IC_TRUE(ifx) ) {
4720 switch(status_bit) {
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4736 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4740 switch(status_bit) {
4754 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4755 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4762 /*-----------------------------------------------------------------*/
4764 /*-----------------------------------------------------------------*/
4765 static void genSkipc(resolvedIfx *rifx)
4767 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4777 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4778 rifx->generated = 1;
4781 #if !(USE_SIMPLE_GENCMP)
4782 /*-----------------------------------------------------------------*/
4784 /*-----------------------------------------------------------------*/
4785 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4787 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4792 if( (rifx->condition ^ invert_condition) & 1)
4797 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4798 rifx->generated = 1;
4803 /*-----------------------------------------------------------------*/
4805 /*-----------------------------------------------------------------*/
4806 static void genSkipz(iCode *ifx, int condition)
4817 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4819 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4822 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4824 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4829 #if !(USE_SIMPLE_GENCMP)
4830 /*-----------------------------------------------------------------*/
4832 /*-----------------------------------------------------------------*/
4833 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4839 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4841 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4845 rifx->generated = 1;
4850 /*-----------------------------------------------------------------*/
4851 /* genChkZeroes :- greater or less than comparison */
4852 /* For each byte in a literal that is zero, inclusive or the */
4853 /* the corresponding byte in the operand with W */
4854 /* returns true if any of the bytes are zero */
4855 /*-----------------------------------------------------------------*/
4856 static int genChkZeroes(operand *op, int lit, int size)
4863 i = (lit >> (size*8)) & 0xff;
4867 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4869 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4879 /*-----------------------------------------------------------------*/
4880 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4881 /* aop (if it's NOT a literal) or from lit (if */
4882 /* aop is a literal) */
4883 /*-----------------------------------------------------------------*/
4884 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4885 if (aop->type == AOP_LIT) {
4886 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4888 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4892 /*-----------------------------------------------------------------*/
4893 /* genCmp :- greater or less than comparison */
4894 /*-----------------------------------------------------------------*/
4896 #if USE_SIMPLE_GENCMP /* { */
4898 /* genCmp performs a left < right comparison, stores
4899 * the outcome in result (if != NULL) and generates
4900 * control flow code for the ifx (if != NULL).
4902 * This version leaves in sequences like
4903 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4904 * which should be optmized by the peephole
4905 * optimizer - RN 2005-01-01 */
4906 static void genCmp (operand *left,operand *right,
4907 operand *result, iCode *ifx, int sign)
4920 assert (left && right);
4921 assert (AOP_SIZE(left) == AOP_SIZE(right));
4923 size = AOP_SIZE(right) - 1;
4924 mask = (0x100UL << (size*8)) - 1;
4925 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4930 resolveIfx (&rIfx, ifx);
4932 /* handle for special cases */
4933 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4936 /**********************************************************************
4937 * handle bits - bit compares are promoted to int compares seemingly! *
4938 **********************************************************************/
4940 // THIS IS COMPLETELY UNTESTED!
4941 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4942 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4943 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4944 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4947 // 1 < {0,1} is false --> clear C by skipping the next instruction
4948 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4949 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4950 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4951 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4952 emitCLRC; // only skipped for left=0 && right=1
4954 goto correct_result_in_carry;
4958 /*************************************************
4959 * make sure that left is register (or the like) *
4960 *************************************************/
4961 if (!isAOP_REGlike(left)) {
4962 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4963 assert (isAOP_LIT(left));
4964 assert (isAOP_REGlike(right));
4965 // swap left and right
4966 // left < right <==> right > left <==> (right >= left + 1)
4967 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4969 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4970 // MAXVALUE < right? always false
4971 if (performedLt) emitCLRC; else emitSETC;
4972 goto correct_result_in_carry;
4975 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4976 // that's why we handled it above.
4983 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4984 } else if (isAOP_LIT(right)) {
4985 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4988 assert (isAOP_REGlike(left)); // left must be register or the like
4989 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4991 /*************************************************
4992 * special cases go here *
4993 *************************************************/
4995 if (isAOP_LIT(right)) {
4997 // unsigned comparison to a literal
4998 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5000 // unsigned left < 0? always false
5001 if (performedLt) emitCLRC; else emitSETC;
5002 goto correct_result_in_carry;
5005 // signed comparison to a literal
5006 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5007 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5008 // signed left < 0x80000000? always false
5009 if (performedLt) emitCLRC; else emitSETC;
5010 goto correct_result_in_carry;
5011 } else if (lit == 0) {
5012 // compare left < 0; set CARRY if SIGNBIT(left) is set
5013 if (performedLt) emitSETC; else emitCLRC;
5014 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5015 if (performedLt) emitCLRC; else emitSETC;
5016 goto correct_result_in_carry;
5019 } // right is literal
5021 /*************************************************
5022 * perform a general case comparison *
5023 * make sure we get CARRY==1 <==> left >= right *
5024 *************************************************/
5025 // compare most significant bytes
5026 //DEBUGpc ("comparing bytes at offset %d", size);
5028 // unsigned comparison
5029 mov2w_regOrLit (AOP(right), lit, size);
5030 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5032 // signed comparison
5033 // (add 2^n to both operands then perform an unsigned comparison)
5034 if (isAOP_LIT(right)) {
5035 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5036 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5038 if (litbyte == 0x80) {
5039 // left >= 0x80 -- always true, but more bytes to come
5040 pic16_mov2w (AOP(left), size);
5041 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5044 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5045 pic16_mov2w (AOP(left), size);
5046 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5047 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5050 /* using PRODL as a temporary register here */
5051 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5052 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5053 pic16_mov2w (AOP(left), size);
5054 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5055 pic16_emitpcode (POC_MOVWF, pctemp);
5056 pic16_mov2w (AOP(right), size);
5057 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5058 pic16_emitpcode (POC_SUBFW, pctemp);
5059 //pic16_popReleaseTempReg(pctemp, 1);
5063 // compare remaining bytes (treat as unsigned case from above)
5064 templbl = newiTempLabel ( NULL );
5067 //DEBUGpc ("comparing bytes at offset %d", offs);
5068 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5069 mov2w_regOrLit (AOP(right), lit, offs);
5070 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5072 pic16_emitpLabel (templbl->key);
5073 goto result_in_carry;
5077 /****************************************************
5078 * now CARRY contains the result of the comparison: *
5079 * SUBWF sets CARRY iff *
5080 * F-W >= 0 <==> F >= W <==> !(F < W) *
5081 * (F=left, W=right) *
5082 ****************************************************/
5085 if (result && AOP_TYPE(result) != AOP_CRY) {
5086 // value will be stored
5089 // value wil only be used in the following genSkipc()
5090 rIfx.condition ^= 1;
5094 correct_result_in_carry:
5096 // assign result to variable (if neccessary)
5097 if (result && AOP_TYPE(result) != AOP_CRY) {
5098 //DEBUGpc ("assign result");
5099 size = AOP_SIZE(result);
5101 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5103 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5106 // perform conditional jump
5108 //DEBUGpc ("generate control flow");
5117 static void genCmp (operand *left,operand *right,
5118 operand *result, iCode *ifx, int sign)
5120 int size; //, offset = 0 ;
5121 unsigned long lit = 0L,i = 0;
5122 resolvedIfx rFalseIfx;
5123 // resolvedIfx rTrueIfx;
5125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5128 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5129 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5135 resolveIfx(&rFalseIfx,ifx);
5136 truelbl = newiTempLabel(NULL);
5137 size = max(AOP_SIZE(left),AOP_SIZE(right));
5139 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5143 /* if literal is on the right then swap with left */
5144 if ((AOP_TYPE(right) == AOP_LIT)) {
5145 operand *tmp = right ;
5146 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5147 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5150 lit = (lit - 1) & mask;
5153 rFalseIfx.condition ^= 1;
5156 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5157 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5161 //if(IC_TRUE(ifx) == NULL)
5162 /* if left & right are bit variables */
5163 if (AOP_TYPE(left) == AOP_CRY &&
5164 AOP_TYPE(right) == AOP_CRY ) {
5165 assert (0 && "bit variables used in genCmp");
5166 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5167 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5169 /* subtract right from left if at the
5170 end the carry flag is set then we know that
5171 left is greater than right */
5173 symbol *lbl = newiTempLabel(NULL);
5176 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5177 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5181 if(AOP_TYPE(right) == AOP_LIT) {
5183 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5185 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5192 genSkipCond(&rFalseIfx,left,size-1,7);
5194 /* no need to compare to 0...*/
5195 /* NOTE: this is a de-generate compare that most certainly
5196 * creates some dead code. */
5197 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5199 if(ifx) ifx->generated = 1;
5206 //i = (lit >> (size*8)) & 0xff;
5207 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5209 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5211 i = ((0-lit) & 0xff);
5214 /* lit is 0x7f, all signed chars are less than
5215 * this except for 0x7f itself */
5216 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5217 genSkipz2(&rFalseIfx,0);
5219 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5220 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5221 genSkipc(&rFalseIfx);
5226 genSkipz2(&rFalseIfx,1);
5228 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5229 genSkipc(&rFalseIfx);
5233 if(ifx) ifx->generated = 1;
5237 /* chars are out of the way. now do ints and longs */
5240 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5247 genSkipCond(&rFalseIfx,left,size,7);
5248 if(ifx) ifx->generated = 1;
5253 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5255 //rFalseIfx.condition ^= 1;
5256 //genSkipCond(&rFalseIfx,left,size,7);
5257 //rFalseIfx.condition ^= 1;
5259 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5260 if(rFalseIfx.condition)
5261 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5263 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5265 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5266 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5267 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5270 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5272 if(rFalseIfx.condition) {
5274 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5280 genSkipc(&rFalseIfx);
5281 pic16_emitpLabel(truelbl->key);
5282 if(ifx) ifx->generated = 1;
5289 if( (lit & 0xff) == 0) {
5290 /* lower byte is zero */
5291 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5292 i = ((lit >> 8) & 0xff) ^0x80;
5293 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5294 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5295 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5296 genSkipc(&rFalseIfx);
5299 if(ifx) ifx->generated = 1;
5304 /* Special cases for signed longs */
5305 if( (lit & 0xffffff) == 0) {
5306 /* lower byte is zero */
5307 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5308 i = ((lit >> 8*3) & 0xff) ^0x80;
5309 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5310 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5311 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5312 genSkipc(&rFalseIfx);
5315 if(ifx) ifx->generated = 1;
5323 if(lit & (0x80 << (size*8))) {
5324 /* lit is negative */
5325 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5327 //genSkipCond(&rFalseIfx,left,size,7);
5329 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5331 if(rFalseIfx.condition)
5332 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5334 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5338 /* lit is positive */
5339 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5340 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5341 if(rFalseIfx.condition)
5342 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5344 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5349 This works, but is only good for ints.
5350 It also requires a "known zero" register.
5351 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5352 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5353 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5354 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5355 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5356 genSkipc(&rFalseIfx);
5358 pic16_emitpLabel(truelbl->key);
5359 if(ifx) ifx->generated = 1;
5363 /* There are no more special cases, so perform a general compare */
5365 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5366 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5372 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374 //rFalseIfx.condition ^= 1;
5375 genSkipc(&rFalseIfx);
5377 pic16_emitpLabel(truelbl->key);
5379 if(ifx) ifx->generated = 1;
5386 /* sign is out of the way. So now do an unsigned compare */
5387 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5390 /* General case - compare to an unsigned literal on the right.*/
5392 i = (lit >> (size*8)) & 0xff;
5393 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5394 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5396 i = (lit >> (size*8)) & 0xff;
5399 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5401 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5403 /* this byte of the lit is zero,
5404 *if it's not the last then OR in the variable */
5406 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5411 pic16_emitpLabel(lbl->key);
5412 // pic16_emitpLabel(truelbl->key);
5413 //if(emitFinalCheck)
5414 genSkipc(&rFalseIfx);
5416 pic16_emitpLabel(truelbl->key);
5418 if(ifx) ifx->generated = 1;
5425 if(AOP_TYPE(left) == AOP_LIT) {
5426 //symbol *lbl = newiTempLabel(NULL);
5428 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5431 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5434 if((lit == 0) && (sign == 0)){
5437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5439 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5441 genSkipz2(&rFalseIfx,0);
5442 if(ifx) ifx->generated = 1;
5449 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5450 /* degenerate compare can never be true */
5451 if(rFalseIfx.condition == 0)
5452 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5454 if(ifx) ifx->generated = 1;
5459 /* signed comparisons to a literal byte */
5461 int lp1 = (lit+1) & 0xff;
5463 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5466 rFalseIfx.condition ^= 1;
5467 genSkipCond(&rFalseIfx,right,0,7);
5470 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5471 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5472 genSkipz2(&rFalseIfx,1);
5475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5476 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5477 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5478 rFalseIfx.condition ^= 1;
5479 genSkipc(&rFalseIfx);
5483 /* unsigned comparisons to a literal byte */
5485 switch(lit & 0xff ) {
5487 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5488 genSkipz2(&rFalseIfx,0);
5491 rFalseIfx.condition ^= 1;
5492 genSkipCond(&rFalseIfx,right,0,7);
5496 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5497 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5499 rFalseIfx.condition ^= 1;
5500 if (AOP_TYPE(result) == AOP_CRY)
5501 genSkipc(&rFalseIfx);
5503 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5504 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5510 if(ifx) ifx->generated = 1;
5511 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5517 /* Size is greater than 1 */
5525 /* this means lit = 0xffffffff, or -1 */
5528 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5529 rFalseIfx.condition ^= 1;
5530 genSkipCond(&rFalseIfx,right,size,7);
5531 if(ifx) ifx->generated = 1;
5533 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5542 if(rFalseIfx.condition) {
5543 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5544 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5547 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5549 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5553 if(rFalseIfx.condition) {
5554 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5555 pic16_emitpLabel(truelbl->key);
5557 rFalseIfx.condition ^= 1;
5558 genSkipCond(&rFalseIfx,right,s,7);
5561 if(ifx) ifx->generated = 1;
5563 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5569 if((size == 1) && (0 == (lp1&0xff))) {
5570 /* lower byte of signed word is zero */
5571 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5572 i = ((lp1 >> 8) & 0xff) ^0x80;
5573 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5574 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5575 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5577 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5579 if(ifx) ifx->generated = 1;
5582 rFalseIfx.condition ^= 1;
5583 genSkipc(&rFalseIfx);
5584 if(ifx) ifx->generated = 1;
5590 if(lit & (0x80 << (size*8))) {
5591 /* Lit is less than zero */
5592 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5593 //rFalseIfx.condition ^= 1;
5594 //genSkipCond(&rFalseIfx,left,size,7);
5595 //rFalseIfx.condition ^= 1;
5596 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5597 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5599 if(rFalseIfx.condition)
5600 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5602 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5606 /* Lit is greater than or equal to zero */
5607 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5608 //rFalseIfx.condition ^= 1;
5609 //genSkipCond(&rFalseIfx,right,size,7);
5610 //rFalseIfx.condition ^= 1;
5612 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5613 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5615 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5616 if(rFalseIfx.condition)
5617 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5619 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5623 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5624 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5628 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5630 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5632 rFalseIfx.condition ^= 1;
5633 //rFalseIfx.condition = 1;
5634 genSkipc(&rFalseIfx);
5636 pic16_emitpLabel(truelbl->key);
5638 if(ifx) ifx->generated = 1;
5641 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5648 /* compare word or long to an unsigned literal on the right.*/
5653 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5656 break; /* handled above */
5659 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5661 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5662 genSkipz2(&rFalseIfx,0);
5666 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5668 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5671 if(rFalseIfx.condition)
5672 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5674 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5677 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5678 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5680 rFalseIfx.condition ^= 1;
5681 genSkipc(&rFalseIfx);
5684 pic16_emitpLabel(truelbl->key);
5686 if(ifx) ifx->generated = 1;
5688 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5696 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5697 i = (lit >> (size*8)) & 0xff;
5699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5700 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5703 i = (lit >> (size*8)) & 0xff;
5706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5708 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5710 /* this byte of the lit is zero,
5711 * if it's not the last then OR in the variable */
5713 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5718 pic16_emitpLabel(lbl->key);
5720 rFalseIfx.condition ^= 1;
5722 genSkipc(&rFalseIfx);
5726 pic16_emitpLabel(truelbl->key);
5727 if(ifx) ifx->generated = 1;
5729 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5735 /* Compare two variables */
5737 DEBUGpic16_emitcode(";sign","%d",sign);
5741 /* Sigh. thus sucks... */
5745 pctemp = pic16_popGetTempReg(1);
5746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5747 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5748 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5749 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5750 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5751 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5752 pic16_popReleaseTempReg(pctemp, 1);
5754 /* Signed char comparison */
5755 /* Special thanks to Nikolai Golovchenko for this snippet */
5756 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5757 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5758 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5759 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5760 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5761 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5764 genSkipc(&rFalseIfx);
5766 if(ifx) ifx->generated = 1;
5768 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5777 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5781 /* The rest of the bytes of a multi-byte compare */
5785 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5788 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5789 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5794 pic16_emitpLabel(lbl->key);
5796 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5797 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5798 (AOP_TYPE(result) == AOP_REG)) {
5799 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5800 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5802 genSkipc(&rFalseIfx);
5804 //genSkipc(&rFalseIfx);
5805 if(ifx) ifx->generated = 1;
5808 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5816 if ((AOP_TYPE(result) != AOP_CRY)
5817 && AOP_SIZE(result)) {
5818 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5820 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5822 pic16_outBitC(result);
5824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5825 /* if the result is used in the next
5826 ifx conditional branch then generate
5827 code a little differently */
5829 genIfxJump (ifx,"c");
5831 pic16_outBitC(result);
5832 /* leave the result in acc */
5837 #elif 0 /* VR version of genCmp() */ /* } else { */
5839 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5840 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5841 operand *result, int offset, int invert_op)
5845 /* check condition, > or < ?? */
5846 if(rIfx->condition != 0)invert_op ^= 1;
5848 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5850 if(!ifx)invert_op ^= 1;
5852 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5853 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5856 if(!invert_op)return POC_CPFSGT;
5857 else return POC_CPFSLT;
5860 static int compareAopfirstpass=1;
5862 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5863 operand *oper, int offset, operand *result,
5864 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5870 /* invert if there is a result to be loaded, in order to fit,
5871 * SETC/CLRC sequence */
5872 if(AOP_SIZE(result))invert_op ^= 1;
5874 // if(sign && !offset)invert_op ^= 1;
5876 // if(sign)invert_op ^= 1;
5878 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5880 if(AOP_SIZE(result) && compareAopfirstpass) {
5883 pic16_emitpcode(POC_SETF, pcop2);
5888 pic16_emitpcode(POC_CLRF, pcop2);
5894 compareAopfirstpass = 0;
5896 /* there is a bug when comparing operands with size > 1,
5897 * because higher bytes can be equal and test should be performed
5898 * to the next lower byte, current algorithm, considers operands
5899 * inequal in these cases! -- VR 20041107 */
5903 pic16_emitpcode(op, pcop);
5905 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5908 if((!sign || !offset) && AOP_SIZE(result)) {
5911 pic16_emitpcode(POC_CLRF, pcop2);
5916 pic16_emitpcode(POC_SETF, pcop2);
5921 /* don't emit final branch (offset == 0) */
5925 pic16_emitpcode(POC_RRCF, pcop2);
5927 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5930 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5931 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5932 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5934 truelbl = newiTempLabel( NULL );
5935 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5936 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5937 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5939 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5940 pic16_emitpLabel(truelbl->key);
5942 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5947 static void genCmp (operand *left, operand *right,
5948 operand *result, iCode *ifx, int sign)
5952 resolvedIfx rFalseIfx;
5953 symbol *falselbl, *tlbl;
5957 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5959 resolveIfx(&rFalseIfx, ifx);
5960 size = max(AOP_SIZE(left), AOP_SIZE(right));
5962 /* if left & right are bit variables */
5963 if(AOP_TYPE(left) == AOP_CRY
5964 && AOP_TYPE(right) == AOP_CRY ) {
5966 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5967 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5969 werror(W_POSSBUG2, __FILE__, __LINE__);
5973 /* if literal is on the right then swap with left */
5974 if((AOP_TYPE(right) == AOP_LIT)) {
5975 operand *tmp = right ;
5976 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5978 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5980 // lit = (lit - 1) & mask;
5983 rFalseIfx.condition ^= 1; /* reverse compare */
5985 if ((AOP_TYPE(left) == AOP_LIT)) {
5986 /* float compares are handled by support functions */
5987 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5990 /* actual comparing algorithm */
5991 // size = AOP_SIZE( right );
5993 falselbl = newiTempLabel( NULL );
5994 if(AOP_TYPE(left) == AOP_LIT) {
5995 /* compare to literal */
5996 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5999 pCodeOp *pct, *pct2;
6002 /* signed compare */
6003 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6005 /* using PRODL:PRODH as a temporary register here */
6006 pct = pic16_popCopyReg(&pic16_pc_prodl);
6007 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6008 tlbl = newiTempLabel( NULL );
6010 /* first compare signs:
6011 * a. if both are positive, compare just like unsigned
6012 * b. if both are negative, invert cmpop, compare just like unsigned
6013 * c. if different signs, determine the result directly */
6019 tlbl1 = newiTempLabel( NULL );
6020 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6024 /* literal is zero or positive:
6025 * a. if carry is zero, too, continue compare,
6026 * b. if carry is set, then continue depending on cmpop ^ condition:
6027 * 1. '<' return false (literal < variable),
6028 * 2. '>' return true (literal > variable) */
6029 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6030 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6033 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6034 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6038 /* literal is negative:
6039 * a. if carry is set, too, continue compare,
6040 * b. if carry is zero, then continue depending on cmpop ^ condition:
6041 * 1. '<' return true (literal < variable),
6042 * 2. '>' return false (literal > variable) */
6043 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6044 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6046 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6047 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6052 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6054 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6055 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6060 pic16_emitpLabel( tlbl1->key );
6063 compareAopfirstpass=1;
6064 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6065 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6066 // pic16_emitpcode(POC_MOVWF, pct);
6068 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6070 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6071 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6075 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6076 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6077 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6078 // pic16_emitpcode(POC_MOVWF, pct);
6080 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6081 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6082 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6083 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6084 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6087 if(ifx)ifx->generated = 1;
6089 if(AOP_SIZE(result)) {
6090 pic16_emitpLabel(tlbl->key);
6091 pic16_emitpLabel(falselbl->key);
6092 pic16_outBitOp( result, pct2 );
6094 pic16_emitpLabel(tlbl->key);
6098 /* unsigned compare */
6099 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6101 compareAopfirstpass=1;
6104 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6105 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6108 if(ifx)ifx->generated = 1;
6110 if(AOP_SIZE(result)) {
6111 pic16_emitpLabel(falselbl->key);
6112 pic16_outBitC( result );
6117 /* compare registers */
6118 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6122 pCodeOp *pct, *pct2;
6124 /* signed compare */
6125 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6127 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6128 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6129 tlbl = newiTempLabel( NULL );
6131 compareAopfirstpass=1;
6134 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6135 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6136 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6137 pic16_emitpcode(POC_MOVWF, pct);
6139 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6140 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6141 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6143 /* WREG already holds left + 0x80 */
6144 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6147 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6148 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6149 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6150 pic16_emitpcode(POC_MOVWF, pct);
6152 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6153 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6156 /* WREG already holds left + 0x80 */
6157 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6158 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6161 if(ifx)ifx->generated = 1;
6163 if(AOP_SIZE(result)) {
6164 pic16_emitpLabel(tlbl->key);
6165 pic16_emitpLabel(falselbl->key);
6166 pic16_outBitOp( result, pct2 );
6168 pic16_emitpLabel(tlbl->key);
6172 /* unsigned compare */
6173 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6175 compareAopfirstpass=1;
6178 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6179 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6183 if(ifx)ifx->generated = 1;
6184 if(AOP_SIZE(result)) {
6186 pic16_emitpLabel(falselbl->key);
6187 pic16_outBitC( result );
6198 /*-----------------------------------------------------------------*/
6199 /* genCmpGt :- greater than comparison */
6200 /*-----------------------------------------------------------------*/
6201 static void genCmpGt (iCode *ic, iCode *ifx)
6203 operand *left, *right, *result;
6204 sym_link *letype , *retype;
6210 right= IC_RIGHT(ic);
6211 result = IC_RESULT(ic);
6213 letype = getSpec(operandType(left));
6214 retype =getSpec(operandType(right));
6215 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6216 /* assign the amsops */
6217 pic16_aopOp (left,ic,FALSE);
6218 pic16_aopOp (right,ic,FALSE);
6219 pic16_aopOp (result,ic,TRUE);
6221 genCmp(right, left, result, ifx, sign);
6223 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6224 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6225 pic16_freeAsmop(result,NULL,ic,TRUE);
6228 /*-----------------------------------------------------------------*/
6229 /* genCmpLt - less than comparisons */
6230 /*-----------------------------------------------------------------*/
6231 static void genCmpLt (iCode *ic, iCode *ifx)
6233 operand *left, *right, *result;
6234 sym_link *letype , *retype;
6240 right= IC_RIGHT(ic);
6241 result = IC_RESULT(ic);
6243 letype = getSpec(operandType(left));
6244 retype =getSpec(operandType(right));
6245 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6247 /* assign the amsops */
6248 pic16_aopOp (left,ic,FALSE);
6249 pic16_aopOp (right,ic,FALSE);
6250 pic16_aopOp (result,ic,TRUE);
6252 genCmp(left, right, result, ifx, sign);
6254 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6255 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6256 pic16_freeAsmop(result,NULL,ic,TRUE);
6261 // FIXME reenable literal optimisation when the pic16 port is stable
6263 /*-----------------------------------------------------------------*/
6264 /* genc16bit2lit - compare a 16 bit value to a literal */
6265 /*-----------------------------------------------------------------*/
6266 static void genc16bit2lit(operand *op, int lit, int offset)
6270 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6271 if( (lit&0xff) == 0)
6276 switch( BYTEofLONG(lit,i)) {
6278 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6281 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6284 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6287 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6288 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6293 switch( BYTEofLONG(lit,i)) {
6295 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6299 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6303 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6306 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6308 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6317 /*-----------------------------------------------------------------*/
6318 /* gencjneshort - compare and jump if not equal */
6319 /*-----------------------------------------------------------------*/
6320 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6322 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6324 int res_offset = 0; /* the result may be a different size then left or right */
6325 int res_size = AOP_SIZE(result);
6327 symbol *lbl, *lbl_done;
6329 unsigned long lit = 0L;
6330 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6333 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6335 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6336 resolveIfx(&rIfx,ifx);
6337 lbl = newiTempLabel(NULL);
6338 lbl_done = newiTempLabel(NULL);
6341 /* if the left side is a literal or
6342 if the right is in a pointer register and left
6344 if ((AOP_TYPE(left) == AOP_LIT) ||
6345 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6350 if(AOP_TYPE(right) == AOP_LIT)
6351 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6353 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6354 preserve_result = 1;
6356 if(result && !preserve_result)
6359 for(i = 0; i < AOP_SIZE(result); i++)
6360 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6364 /* if the right side is a literal then anything goes */
6365 if (AOP_TYPE(right) == AOP_LIT &&
6366 AOP_TYPE(left) != AOP_DIR ) {
6369 genc16bit2lit(left, lit, 0);
6371 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6374 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6377 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6378 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6380 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6384 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6386 if(res_offset < res_size-1)
6394 /* if the right side is in a register or in direct space or
6395 if the left is a pointer register & right is not */
6396 else if (AOP_TYPE(right) == AOP_REG ||
6397 AOP_TYPE(right) == AOP_DIR ||
6398 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6399 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6400 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6401 int lbl_key = lbl->key;
6404 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6405 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6407 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6408 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6409 __FUNCTION__,__LINE__);
6413 /* switch(size) { */
6415 /* genc16bit2lit(left, lit, 0); */
6417 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6422 if((AOP_TYPE(left) == AOP_DIR) &&
6423 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6425 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6426 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6428 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6430 switch (lit & 0xff) {
6432 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6435 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6436 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6437 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6441 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6442 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6443 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6444 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6448 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6454 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6457 if(AOP_TYPE(result) == AOP_CRY) {
6458 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6465 /* fix me. probably need to check result size too */
6466 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6471 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6472 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6479 if(res_offset < res_size-1)
6484 } else if(AOP_TYPE(right) == AOP_REG &&
6485 AOP_TYPE(left) != AOP_DIR){
6488 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6489 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6490 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6495 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6497 if(res_offset < res_size-1)
6502 /* right is a pointer reg need both a & b */
6504 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6506 pic16_emitcode("mov","b,%s",l);
6507 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6508 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6513 if(result && preserve_result)
6516 for(i = 0; i < AOP_SIZE(result); i++)
6517 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6520 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6522 if(result && preserve_result)
6523 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6526 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6528 pic16_emitpLabel(lbl->key);
6530 if(result && preserve_result)
6533 for(i = 0; i < AOP_SIZE(result); i++)
6534 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6536 pic16_emitpLabel(lbl_done->key);
6539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6547 /*-----------------------------------------------------------------*/
6548 /* gencjne - compare and jump if not equal */
6549 /*-----------------------------------------------------------------*/
6550 static void gencjne(operand *left, operand *right, iCode *ifx)
6552 symbol *tlbl = newiTempLabel(NULL);
6554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6555 gencjneshort(left, right, lbl);
6557 pic16_emitcode("mov","a,%s",one);
6558 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6559 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6560 pic16_emitcode("clr","a");
6561 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6563 pic16_emitpLabel(lbl->key);
6564 pic16_emitpLabel(tlbl->key);
6570 /*-----------------------------------------------------------------*/
6571 /* is_LitOp - check if operand has to be treated as literal */
6572 /*-----------------------------------------------------------------*/
6573 static bool is_LitOp(operand *op)
6575 return ((AOP_TYPE(op) == AOP_LIT)
6576 || ( (AOP_TYPE(op) == AOP_PCODE)
6577 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6578 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6581 /*-----------------------------------------------------------------*/
6582 /* is_LitAOp - check if operand has to be treated as literal */
6583 /*-----------------------------------------------------------------*/
6584 static bool is_LitAOp(asmop *aop)
6586 return ((aop->type == AOP_LIT)
6587 || ( (aop->type == AOP_PCODE)
6588 && ( (aop->aopu.pcop->type == PO_LITERAL)
6589 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6594 /*-----------------------------------------------------------------*/
6595 /* genCmpEq - generates code for equal to */
6596 /*-----------------------------------------------------------------*/
6597 static void genCmpEq (iCode *ic, iCode *ifx)
6599 operand *left, *right, *result;
6600 symbol *falselbl = newiTempLabel(NULL);
6601 symbol *donelbl = newiTempLabel(NULL);
6603 int preserve_result = 0;
6604 int generate_result = 0;
6606 unsigned long lit = -1;
6610 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6611 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6612 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6614 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6616 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6618 werror(W_POSSBUG2, __FILE__, __LINE__);
6619 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6620 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6624 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6626 operand *tmp = right ;
6631 if (AOP_TYPE(right) == AOP_LIT) {
6632 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6635 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6636 preserve_result = 1;
6638 if(result && AOP_SIZE(result))
6639 generate_result = 1;
6641 if(generate_result && !preserve_result)
6643 for(i = 0; i < AOP_SIZE(result); i++)
6644 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6647 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6648 for(i=0; i < AOP_SIZE(left); i++)
6650 if(AOP_TYPE(left) != AOP_ACC)
6653 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6655 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6657 if(is_LitOp(right)) {
6658 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6659 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6662 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6664 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6669 if(generate_result && preserve_result)
6671 for(i = 0; i < AOP_SIZE(result); i++)
6672 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6676 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6678 if(generate_result && preserve_result)
6679 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6681 if(ifx && IC_TRUE(ifx))
6682 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6684 if(ifx && IC_FALSE(ifx))
6685 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6687 pic16_emitpLabel(falselbl->key);
6691 if(ifx && IC_FALSE(ifx))
6692 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6694 if(generate_result && preserve_result)
6696 for(i = 0; i < AOP_SIZE(result); i++)
6697 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6700 pic16_emitpLabel(donelbl->key);
6706 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6707 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6708 pic16_freeAsmop(result,NULL,ic,TRUE);
6714 // old version kept for reference
6716 /*-----------------------------------------------------------------*/
6717 /* genCmpEq - generates code for equal to */
6718 /*-----------------------------------------------------------------*/
6719 static void genCmpEq (iCode *ic, iCode *ifx)
6721 operand *left, *right, *result;
6722 unsigned long lit = 0L;
6724 symbol *falselbl = newiTempLabel(NULL);
6727 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6730 DEBUGpic16_emitcode ("; ifx is non-null","");
6732 DEBUGpic16_emitcode ("; ifx is null","");
6734 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6735 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6736 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6738 size = max(AOP_SIZE(left),AOP_SIZE(right));
6740 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6742 /* if literal, literal on the right or
6743 if the right is in a pointer register and left
6745 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6746 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6747 operand *tmp = right ;
6753 if(ifx && !AOP_SIZE(result)){
6755 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6756 /* if they are both bit variables */
6757 if (AOP_TYPE(left) == AOP_CRY &&
6758 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6759 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6760 if(AOP_TYPE(right) == AOP_LIT){
6761 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6763 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6764 pic16_emitcode("cpl","c");
6765 } else if(lit == 1L) {
6766 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6768 pic16_emitcode("clr","c");
6770 /* AOP_TYPE(right) == AOP_CRY */
6772 symbol *lbl = newiTempLabel(NULL);
6773 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6774 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6775 pic16_emitcode("cpl","c");
6776 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6778 /* if true label then we jump if condition
6780 tlbl = newiTempLabel(NULL);
6781 if ( IC_TRUE(ifx) ) {
6782 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6783 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6785 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6786 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6788 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6791 /* left and right are both bit variables, result is carry */
6794 resolveIfx(&rIfx,ifx);
6796 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6797 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6798 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6799 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6804 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6806 /* They're not both bit variables. Is the right a literal? */
6807 if(AOP_TYPE(right) == AOP_LIT) {
6808 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6813 switch(lit & 0xff) {
6815 if ( IC_TRUE(ifx) ) {
6816 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6818 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6820 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6821 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6825 if ( IC_TRUE(ifx) ) {
6826 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6828 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6830 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6831 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6835 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6837 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6842 /* end of size == 1 */
6846 genc16bit2lit(left,lit,offset);
6849 /* end of size == 2 */
6854 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6855 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6856 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6857 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6860 /* search for patterns that can be optimized */
6862 genc16bit2lit(left,lit,0);
6866 emitSKPZ; // if hi word unequal
6868 emitSKPNZ; // if hi word equal
6870 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6871 genc16bit2lit(left,lit,2);
6874 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6875 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6879 pic16_emitpLabel(falselbl->key);
6888 } else if(AOP_TYPE(right) == AOP_CRY ) {
6889 /* we know the left is not a bit, but that the right is */
6890 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6891 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6892 pic16_popGet(AOP(right),offset));
6893 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6895 /* if the two are equal, then W will be 0 and the Z bit is set
6896 * we could test Z now, or go ahead and check the high order bytes if
6897 * the variable we're comparing is larger than a byte. */
6900 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6902 if ( IC_TRUE(ifx) ) {
6904 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6905 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6909 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6913 /* They're both variables that are larger than bits */
6916 tlbl = newiTempLabel(NULL);
6919 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6920 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6922 if ( IC_TRUE(ifx) ) {
6926 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6928 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6929 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6933 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6936 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6937 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6942 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6944 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6945 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6949 if(s>1 && IC_TRUE(ifx)) {
6950 pic16_emitpLabel(tlbl->key);
6951 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6955 /* mark the icode as generated */
6960 /* if they are both bit variables */
6961 if (AOP_TYPE(left) == AOP_CRY &&
6962 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6963 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6964 if(AOP_TYPE(right) == AOP_LIT){
6965 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6967 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6968 pic16_emitcode("cpl","c");
6969 } else if(lit == 1L) {
6970 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6972 pic16_emitcode("clr","c");
6974 /* AOP_TYPE(right) == AOP_CRY */
6976 symbol *lbl = newiTempLabel(NULL);
6977 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6978 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6979 pic16_emitcode("cpl","c");
6980 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6983 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6984 pic16_outBitC(result);
6988 genIfxJump (ifx,"c");
6991 /* if the result is used in an arithmetic operation
6992 then put the result in place */
6993 pic16_outBitC(result);
6996 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6997 gencjne(left,right,result,ifx);
7000 gencjne(left,right,newiTempLabel(NULL));
7002 if(IC_TRUE(ifx)->key)
7003 gencjne(left,right,IC_TRUE(ifx)->key);
7005 gencjne(left,right,IC_FALSE(ifx)->key);
7009 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7010 pic16_aopPut(AOP(result),"a",0);
7015 genIfxJump (ifx,"a");
7019 /* if the result is used in an arithmetic operation
7020 then put the result in place */
7022 if (AOP_TYPE(result) != AOP_CRY)
7023 pic16_outAcc(result);
7025 /* leave the result in acc */
7029 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7030 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031 pic16_freeAsmop(result,NULL,ic,TRUE);
7035 /*-----------------------------------------------------------------*/
7036 /* ifxForOp - returns the icode containing the ifx for operand */
7037 /*-----------------------------------------------------------------*/
7038 static iCode *ifxForOp ( operand *op, iCode *ic )
7042 /* if true symbol then needs to be assigned */
7043 if (IS_TRUE_SYMOP(op))
7046 /* if this has register type condition and
7047 the next instruction is ifx with the same operand
7048 and live to of the operand is upto the ifx only then */
7050 && ic->next->op == IFX
7051 && IC_COND(ic->next)->key == op->key
7052 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7054 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7060 ic->next->op == IFX &&
7061 IC_COND(ic->next)->key == op->key) {
7062 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7067 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7069 ic->next->op == IFX)
7070 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7073 ic->next->op == IFX &&
7074 IC_COND(ic->next)->key == op->key) {
7075 DEBUGpic16_emitcode ("; "," key is okay");
7076 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7077 OP_SYMBOL(op)->liveTo,
7082 /* the code below is completely untested
7083 * it just allows ulong2fs.c compile -- VR */
7086 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7087 __FILE__, __FUNCTION__, __LINE__);
7089 /* if this has register type condition and
7090 the next instruction is ifx with the same operand
7091 and live to of the operand is upto the ifx only then */
7093 ic->next->op == IFX &&
7094 IC_COND(ic->next)->key == op->key &&
7095 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7099 ic->next->op == IFX &&
7100 IC_COND(ic->next)->key == op->key) {
7101 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7105 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7106 __FILE__, __FUNCTION__, __LINE__);
7108 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7113 /*-----------------------------------------------------------------*/
7114 /* genAndOp - for && operation */
7115 /*-----------------------------------------------------------------*/
7116 static void genAndOp (iCode *ic)
7118 operand *left,*right, *result;
7123 /* note here that && operations that are in an
7124 if statement are taken away by backPatchLabels
7125 only those used in arthmetic operations remain */
7126 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7127 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7128 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7130 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7132 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7133 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7134 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7136 /* if both are bit variables */
7137 /* if (AOP_TYPE(left) == AOP_CRY && */
7138 /* AOP_TYPE(right) == AOP_CRY ) { */
7139 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7140 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7141 /* pic16_outBitC(result); */
7143 /* tlbl = newiTempLabel(NULL); */
7144 /* pic16_toBoolean(left); */
7145 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7146 /* pic16_toBoolean(right); */
7147 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7148 /* pic16_outBitAcc(result); */
7151 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7152 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7153 pic16_freeAsmop(result,NULL,ic,TRUE);
7157 /*-----------------------------------------------------------------*/
7158 /* genOrOp - for || operation */
7159 /*-----------------------------------------------------------------*/
7162 modified this code, but it doesn't appear to ever get called
7165 static void genOrOp (iCode *ic)
7167 operand *left,*right, *result;
7172 /* note here that || operations that are in an
7173 if statement are taken away by backPatchLabels
7174 only those used in arthmetic operations remain */
7175 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7176 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7177 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7179 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7181 /* if both are bit variables */
7182 if (AOP_TYPE(left) == AOP_CRY &&
7183 AOP_TYPE(right) == AOP_CRY ) {
7184 pic16_emitcode("clrc","");
7185 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7186 AOP(left)->aopu.aop_dir,
7187 AOP(left)->aopu.aop_dir);
7188 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7189 AOP(right)->aopu.aop_dir,
7190 AOP(right)->aopu.aop_dir);
7191 pic16_emitcode("setc","");
7194 tlbl = newiTempLabel(NULL);
7195 pic16_toBoolean(left);
7197 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7198 pic16_toBoolean(right);
7199 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7201 pic16_outBitAcc(result);
7204 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7205 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7206 pic16_freeAsmop(result,NULL,ic,TRUE);
7209 /*-----------------------------------------------------------------*/
7210 /* isLiteralBit - test if lit == 2^n */
7211 /*-----------------------------------------------------------------*/
7212 static int isLiteralBit(unsigned long lit)
7214 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7215 0x100L,0x200L,0x400L,0x800L,
7216 0x1000L,0x2000L,0x4000L,0x8000L,
7217 0x10000L,0x20000L,0x40000L,0x80000L,
7218 0x100000L,0x200000L,0x400000L,0x800000L,
7219 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7220 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7224 for(idx = 0; idx < 32; idx++)
7230 /*-----------------------------------------------------------------*/
7231 /* continueIfTrue - */
7232 /*-----------------------------------------------------------------*/
7233 static void continueIfTrue (iCode *ic)
7237 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7241 /*-----------------------------------------------------------------*/
7243 /*-----------------------------------------------------------------*/
7244 static void jumpIfTrue (iCode *ic)
7248 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7252 /*-----------------------------------------------------------------*/
7253 /* jmpTrueOrFalse - */
7254 /*-----------------------------------------------------------------*/
7255 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7257 // ugly but optimized by peephole
7260 symbol *nlbl = newiTempLabel(NULL);
7261 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7262 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7263 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7264 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7266 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7267 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7272 /*-----------------------------------------------------------------*/
7273 /* genAnd - code for and */
7274 /*-----------------------------------------------------------------*/
7275 static void genAnd (iCode *ic, iCode *ifx)
7277 operand *left, *right, *result;
7279 unsigned long lit = 0L;
7285 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7286 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7287 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7289 resolveIfx(&rIfx,ifx);
7291 /* if left is a literal & right is not then exchange them */
7292 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7293 AOP_NEEDSACC(left)) {
7294 operand *tmp = right ;
7299 /* if result = right then exchange them */
7300 if(pic16_sameRegs(AOP(result),AOP(right))){
7301 operand *tmp = right ;
7306 /* if right is bit then exchange them */
7307 if (AOP_TYPE(right) == AOP_CRY &&
7308 AOP_TYPE(left) != AOP_CRY){
7309 operand *tmp = right ;
7313 if(AOP_TYPE(right) == AOP_LIT)
7314 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7316 size = AOP_SIZE(result);
7318 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7321 // result = bit & yy;
7322 if (AOP_TYPE(left) == AOP_CRY){
7323 // c = bit & literal;
7324 if(AOP_TYPE(right) == AOP_LIT){
7326 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7329 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7332 if(size && (AOP_TYPE(result) == AOP_CRY)){
7333 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7336 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7340 pic16_emitcode("clr","c");
7343 if (AOP_TYPE(right) == AOP_CRY){
7345 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7346 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7349 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7351 pic16_emitcode("rrc","a");
7352 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7358 pic16_outBitC(result);
7360 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7361 genIfxJump(ifx, "c");
7365 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7366 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7367 if((AOP_TYPE(right) == AOP_LIT) &&
7368 (AOP_TYPE(result) == AOP_CRY) &&
7369 (AOP_TYPE(left) != AOP_CRY)){
7370 int posbit = isLiteralBit(lit);
7374 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7377 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7383 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7384 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7386 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7387 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7390 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7391 size = AOP_SIZE(left);
7394 int bp = posbit, ofs=0;
7401 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7402 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7406 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7407 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7409 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7416 symbol *tlbl = newiTempLabel(NULL);
7417 int sizel = AOP_SIZE(left);
7423 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7425 /* patch provided by Aaron Colwell */
7426 if((posbit = isLiteralBit(bytelit)) != 0) {
7427 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7428 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7429 (posbit-1),0, PO_GPR_REGISTER));
7431 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7432 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7434 if (bytelit == 0xff) {
7435 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7436 * a peephole could optimize it out -- VR */
7437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7439 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7440 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7443 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7444 pic16_popGetLabel(tlbl->key));
7448 /* old code, left here for reference -- VR 09/2004 */
7449 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7451 if((posbit = isLiteralBit(bytelit)) != 0)
7452 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7454 if(bytelit != 0x0FFL)
7455 pic16_emitcode("anl","a,%s",
7456 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7457 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7463 // bit = left & literal
7466 pic16_emitpLabel(tlbl->key);
7468 // if(left & literal)
7471 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7474 pic16_emitpLabel(tlbl->key);
7479 pic16_outBitC(result);
7483 /* if left is same as result */
7484 if(pic16_sameRegs(AOP(result),AOP(left))){
7486 for(;size--; offset++,lit>>=8) {
7487 if(AOP_TYPE(right) == AOP_LIT){
7488 switch(lit & 0xff) {
7490 /* and'ing with 0 has clears the result */
7491 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7492 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7495 /* and'ing with 0xff is a nop when the result and left are the same */
7500 int p = pic16_my_powof2( (~lit) & 0xff );
7502 /* only one bit is set in the literal, so use a bcf instruction */
7503 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7504 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7507 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7508 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7509 if(know_W != (lit&0xff))
7510 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7512 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7517 if (AOP_TYPE(left) == AOP_ACC) {
7518 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7520 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7521 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7528 // left & result in different registers
7529 if(AOP_TYPE(result) == AOP_CRY){
7531 // if(size), result in bit
7532 // if(!size && ifx), conditional oper: if(left & right)
7533 symbol *tlbl = newiTempLabel(NULL);
7534 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7536 pic16_emitcode("setb","c");
7538 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7539 pic16_emitcode("anl","a,%s",
7540 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7541 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7546 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7547 pic16_outBitC(result);
7549 jmpTrueOrFalse(ifx, tlbl);
7551 for(;(size--);offset++) {
7553 // result = left & right
7554 if(AOP_TYPE(right) == AOP_LIT){
7555 int t = (lit >> (offset*8)) & 0x0FFL;
7558 pic16_emitcode("clrf","%s",
7559 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7560 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7563 pic16_emitcode("movf","%s,w",
7564 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7565 pic16_emitcode("movwf","%s",
7566 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7567 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7568 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7571 pic16_emitcode("movlw","0x%x",t);
7572 pic16_emitcode("andwf","%s,w",
7573 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7574 pic16_emitcode("movwf","%s",
7575 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7577 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7578 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7579 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7584 if (AOP_TYPE(left) == AOP_ACC) {
7585 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7586 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7588 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7589 pic16_emitcode("andwf","%s,w",
7590 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7591 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7592 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7594 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7595 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7601 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7602 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7603 pic16_freeAsmop(result,NULL,ic,TRUE);
7606 /*-----------------------------------------------------------------*/
7607 /* genOr - code for or */
7608 /*-----------------------------------------------------------------*/
7609 static void genOr (iCode *ic, iCode *ifx)
7611 operand *left, *right, *result;
7613 unsigned long lit = 0L;
7615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7617 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7618 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7619 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7621 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7623 /* if left is a literal & right is not then exchange them */
7624 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7625 AOP_NEEDSACC(left)) {
7626 operand *tmp = right ;
7631 /* if result = right then exchange them */
7632 if(pic16_sameRegs(AOP(result),AOP(right))){
7633 operand *tmp = right ;
7638 /* if right is bit then exchange them */
7639 if (AOP_TYPE(right) == AOP_CRY &&
7640 AOP_TYPE(left) != AOP_CRY){
7641 operand *tmp = right ;
7646 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7648 if(AOP_TYPE(right) == AOP_LIT)
7649 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7651 size = AOP_SIZE(result);
7655 if (AOP_TYPE(left) == AOP_CRY){
7656 if(AOP_TYPE(right) == AOP_LIT){
7657 // c = bit & literal;
7659 // lit != 0 => result = 1
7660 if(AOP_TYPE(result) == AOP_CRY){
7662 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7663 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7664 // AOP(result)->aopu.aop_dir,
7665 // AOP(result)->aopu.aop_dir);
7667 continueIfTrue(ifx);
7671 // lit == 0 => result = left
7672 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7674 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7677 if (AOP_TYPE(right) == AOP_CRY){
7678 if(pic16_sameRegs(AOP(result),AOP(left))){
7680 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7681 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7682 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7684 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7685 AOP(result)->aopu.aop_dir,
7686 AOP(result)->aopu.aop_dir);
7687 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7688 AOP(right)->aopu.aop_dir,
7689 AOP(right)->aopu.aop_dir);
7690 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7691 AOP(result)->aopu.aop_dir,
7692 AOP(result)->aopu.aop_dir);
7694 if( AOP_TYPE(result) == AOP_ACC) {
7695 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7696 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7697 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7698 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7702 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7703 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7704 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7705 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7707 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7708 AOP(result)->aopu.aop_dir,
7709 AOP(result)->aopu.aop_dir);
7710 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7711 AOP(right)->aopu.aop_dir,
7712 AOP(right)->aopu.aop_dir);
7713 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7714 AOP(left)->aopu.aop_dir,
7715 AOP(left)->aopu.aop_dir);
7716 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7717 AOP(result)->aopu.aop_dir,
7718 AOP(result)->aopu.aop_dir);
7723 symbol *tlbl = newiTempLabel(NULL);
7724 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7727 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7728 if( AOP_TYPE(right) == AOP_ACC) {
7729 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7731 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7732 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7737 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7738 pic16_emitcode(";XXX setb","c");
7739 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7740 AOP(left)->aopu.aop_dir,tlbl->key+100);
7741 pic16_toBoolean(right);
7742 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7743 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7744 jmpTrueOrFalse(ifx, tlbl);
7748 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7755 pic16_outBitC(result);
7757 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7758 genIfxJump(ifx, "c");
7762 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7763 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7764 if((AOP_TYPE(right) == AOP_LIT) &&
7765 (AOP_TYPE(result) == AOP_CRY) &&
7766 (AOP_TYPE(left) != AOP_CRY)){
7768 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7771 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7773 continueIfTrue(ifx);
7776 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7777 // lit = 0, result = boolean(left)
7779 pic16_emitcode(";XXX setb","c");
7780 pic16_toBoolean(right);
7782 symbol *tlbl = newiTempLabel(NULL);
7783 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7785 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7787 genIfxJump (ifx,"a");
7791 pic16_outBitC(result);
7795 /* if left is same as result */
7796 if(pic16_sameRegs(AOP(result),AOP(left))){
7798 for(;size--; offset++,lit>>=8) {
7799 if(AOP_TYPE(right) == AOP_LIT){
7800 if((lit & 0xff) == 0)
7801 /* or'ing with 0 has no effect */
7804 int p = pic16_my_powof2(lit & 0xff);
7806 /* only one bit is set in the literal, so use a bsf instruction */
7807 pic16_emitpcode(POC_BSF,
7808 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7810 if(know_W != (lit & 0xff))
7811 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7812 know_W = lit & 0xff;
7813 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7818 if (AOP_TYPE(left) == AOP_ACC) {
7819 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7820 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7823 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7825 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7826 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7832 // left & result in different registers
7833 if(AOP_TYPE(result) == AOP_CRY){
7835 // if(size), result in bit
7836 // if(!size && ifx), conditional oper: if(left | right)
7837 symbol *tlbl = newiTempLabel(NULL);
7838 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7839 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7843 pic16_emitcode(";XXX setb","c");
7845 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7846 pic16_emitcode(";XXX orl","a,%s",
7847 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7848 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7853 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7854 pic16_outBitC(result);
7856 jmpTrueOrFalse(ifx, tlbl);
7857 } else for(;(size--);offset++){
7859 // result = left & right
7860 if(AOP_TYPE(right) == AOP_LIT){
7861 int t = (lit >> (offset*8)) & 0x0FFL;
7864 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7865 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7867 // pic16_emitcode("movf","%s,w",
7868 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7869 // pic16_emitcode("movwf","%s",
7870 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7873 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7874 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7875 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7877 // pic16_emitcode("movlw","0x%x",t);
7878 // pic16_emitcode("iorwf","%s,w",
7879 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7880 // pic16_emitcode("movwf","%s",
7881 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7887 // faster than result <- left, anl result,right
7888 // and better if result is SFR
7889 if (AOP_TYPE(left) == AOP_ACC) {
7890 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7891 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7894 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7896 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897 // pic16_emitcode("iorwf","%s,w",
7898 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7901 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7906 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7907 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7908 pic16_freeAsmop(result,NULL,ic,TRUE);
7911 /*-----------------------------------------------------------------*/
7912 /* genXor - code for xclusive or */
7913 /*-----------------------------------------------------------------*/
7914 static void genXor (iCode *ic, iCode *ifx)
7916 operand *left, *right, *result;
7918 unsigned long lit = 0L;
7920 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7922 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7923 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7924 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7926 /* if left is a literal & right is not ||
7927 if left needs acc & right does not */
7928 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7929 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7930 operand *tmp = right ;
7935 /* if result = right then exchange them */
7936 if(pic16_sameRegs(AOP(result),AOP(right))){
7937 operand *tmp = right ;
7942 /* if right is bit then exchange them */
7943 if (AOP_TYPE(right) == AOP_CRY &&
7944 AOP_TYPE(left) != AOP_CRY){
7945 operand *tmp = right ;
7949 if(AOP_TYPE(right) == AOP_LIT)
7950 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7952 size = AOP_SIZE(result);
7956 if (AOP_TYPE(left) == AOP_CRY){
7957 if(AOP_TYPE(right) == AOP_LIT){
7958 // c = bit & literal;
7960 // lit>>1 != 0 => result = 1
7961 if(AOP_TYPE(result) == AOP_CRY){
7963 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7964 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7966 continueIfTrue(ifx);
7969 pic16_emitcode("setb","c");
7973 // lit == 0, result = left
7974 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7976 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7978 // lit == 1, result = not(left)
7979 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7980 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7981 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7982 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7985 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7986 pic16_emitcode("cpl","c");
7993 symbol *tlbl = newiTempLabel(NULL);
7994 if (AOP_TYPE(right) == AOP_CRY){
7996 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7999 int sizer = AOP_SIZE(right);
8001 // if val>>1 != 0, result = 1
8002 pic16_emitcode("setb","c");
8004 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8006 // test the msb of the lsb
8007 pic16_emitcode("anl","a,#0xfe");
8008 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8012 pic16_emitcode("rrc","a");
8014 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8015 pic16_emitcode("cpl","c");
8016 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8021 pic16_outBitC(result);
8023 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8024 genIfxJump(ifx, "c");
8028 if(pic16_sameRegs(AOP(result),AOP(left))){
8029 /* if left is same as result */
8030 for(;size--; offset++) {
8031 if(AOP_TYPE(right) == AOP_LIT){
8032 int t = (lit >> (offset*8)) & 0x0FFL;
8036 if (IS_AOP_PREG(left)) {
8037 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8038 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8039 pic16_aopPut(AOP(result),"a",offset);
8041 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8042 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8043 pic16_emitcode("xrl","%s,%s",
8044 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8045 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8048 if (AOP_TYPE(left) == AOP_ACC)
8049 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8051 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8052 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8054 if (IS_AOP_PREG(left)) {
8055 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8056 pic16_aopPut(AOP(result),"a",offset);
8058 pic16_emitcode("xrl","%s,a",
8059 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8065 // left & result in different registers
8066 if(AOP_TYPE(result) == AOP_CRY){
8068 // if(size), result in bit
8069 // if(!size && ifx), conditional oper: if(left ^ right)
8070 symbol *tlbl = newiTempLabel(NULL);
8071 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8073 pic16_emitcode("setb","c");
8075 if((AOP_TYPE(right) == AOP_LIT) &&
8076 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8077 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8079 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8080 pic16_emitcode("xrl","a,%s",
8081 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8083 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8088 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8089 pic16_outBitC(result);
8091 jmpTrueOrFalse(ifx, tlbl);
8092 } else for(;(size--);offset++){
8094 // result = left & right
8095 if(AOP_TYPE(right) == AOP_LIT){
8096 int t = (lit >> (offset*8)) & 0x0FFL;
8099 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8100 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8101 pic16_emitcode("movf","%s,w",
8102 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8103 pic16_emitcode("movwf","%s",
8104 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8107 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8108 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8109 pic16_emitcode("comf","%s,w",
8110 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8111 pic16_emitcode("movwf","%s",
8112 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8115 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8116 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8117 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8118 pic16_emitcode("movlw","0x%x",t);
8119 pic16_emitcode("xorwf","%s,w",
8120 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8121 pic16_emitcode("movwf","%s",
8122 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8128 // faster than result <- left, anl result,right
8129 // and better if result is SFR
8130 if (AOP_TYPE(left) == AOP_ACC) {
8131 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8132 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8134 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8135 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8136 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8137 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8139 if ( AOP_TYPE(result) != AOP_ACC){
8140 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8141 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8147 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8148 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8149 pic16_freeAsmop(result,NULL,ic,TRUE);
8152 /*-----------------------------------------------------------------*/
8153 /* genInline - write the inline code out */
8154 /*-----------------------------------------------------------------*/
8155 static void genInline (iCode *ic)
8157 char *buffer, *bp, *bp1;
8159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8161 _G.inLine += (!options.asmpeep);
8163 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8164 strcpy(buffer,IC_INLINE(ic));
8166 while((bp1=strstr(bp, "\\n"))) {
8174 /* This is an experimental code for #pragma inline
8175 and is temporarily disabled for 2.5.0 release */
8183 cbuf = Safe_strdup(buffer);
8184 cblen = strlen(buffer)+1;
8185 memset(cbuf, 0, cblen);
8190 if(*bp != '%')*bp1++ = *bp++;
8196 if(i>elementsInSet(asmInlineMap))break;
8199 s = indexSet(asmInlineMap, i);
8200 DEBUGpc("searching symbol s = `%s'", s);
8201 sym = findSym(SymbolTab, NULL, s);
8204 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8206 strcat(bp1, sym->rname);
8212 if(strlen(bp1) > cblen - 16) {
8213 int i = strlen(cbuf);
8215 cbuf = realloc(cbuf, cblen);
8216 memset(cbuf+i, 0, 50);
8222 buffer = Safe_strdup( cbuf );
8229 /* emit each line as a code */
8235 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8243 /* print label, use this special format with NULL directive
8244 * to denote that the argument should not be indented with tab */
8245 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8248 /* advance to end of line (prevent splitting of comments at ':' */
8249 while (*bp && *bp != '\n') {
8257 if ((bp1 != bp) && *bp1)
8258 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8263 _G.inLine -= (!options.asmpeep);
8266 /*-----------------------------------------------------------------*/
8267 /* genRRC - rotate right with carry */
8268 /*-----------------------------------------------------------------*/
8269 static void genRRC (iCode *ic)
8271 operand *left , *result ;
8272 int size, offset = 0, same;
8274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8276 /* rotate right with carry */
8278 result=IC_RESULT(ic);
8279 pic16_aopOp (left,ic,FALSE);
8280 pic16_aopOp (result,ic,TRUE);
8282 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8284 same = pic16_sameRegs(AOP(result),AOP(left));
8286 size = AOP_SIZE(result);
8288 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8290 /* get the lsb and put it into the carry */
8291 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8298 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8300 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8301 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8307 pic16_freeAsmop(left,NULL,ic,TRUE);
8308 pic16_freeAsmop(result,NULL,ic,TRUE);
8311 /*-----------------------------------------------------------------*/
8312 /* genRLC - generate code for rotate left with carry */
8313 /*-----------------------------------------------------------------*/
8314 static void genRLC (iCode *ic)
8316 operand *left , *result ;
8317 int size, offset = 0;
8320 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8321 /* rotate right with carry */
8323 result=IC_RESULT(ic);
8324 pic16_aopOp (left,ic,FALSE);
8325 pic16_aopOp (result,ic,TRUE);
8327 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8329 same = pic16_sameRegs(AOP(result),AOP(left));
8331 /* move it to the result */
8332 size = AOP_SIZE(result);
8334 /* get the msb and put it into the carry */
8335 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8342 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8344 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8345 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8352 pic16_freeAsmop(left,NULL,ic,TRUE);
8353 pic16_freeAsmop(result,NULL,ic,TRUE);
8357 /* gpasm can get the highest order bit with HIGH/UPPER
8358 * so the following probably is not needed -- VR */
8360 /*-----------------------------------------------------------------*/
8361 /* genGetHbit - generates code get highest order bit */
8362 /*-----------------------------------------------------------------*/
8363 static void genGetHbit (iCode *ic)
8365 operand *left, *result;
8367 result=IC_RESULT(ic);
8368 pic16_aopOp (left,ic,FALSE);
8369 pic16_aopOp (result,ic,FALSE);
8371 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8372 /* get the highest order byte into a */
8373 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8374 if(AOP_TYPE(result) == AOP_CRY){
8375 pic16_emitcode("rlc","a");
8376 pic16_outBitC(result);
8379 pic16_emitcode("rl","a");
8380 pic16_emitcode("anl","a,#0x01");
8381 pic16_outAcc(result);
8385 pic16_freeAsmop(left,NULL,ic,TRUE);
8386 pic16_freeAsmop(result,NULL,ic,TRUE);
8390 /*-----------------------------------------------------------------*/
8391 /* AccRol - rotate left accumulator by known count */
8392 /*-----------------------------------------------------------------*/
8393 static void AccRol (int shCount)
8395 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8396 shCount &= 0x0007; // shCount : 0..7
8401 pic16_emitcode("rl","a");
8404 pic16_emitcode("rl","a");
8405 pic16_emitcode("rl","a");
8408 pic16_emitcode("swap","a");
8409 pic16_emitcode("rr","a");
8412 pic16_emitcode("swap","a");
8415 pic16_emitcode("swap","a");
8416 pic16_emitcode("rl","a");
8419 pic16_emitcode("rr","a");
8420 pic16_emitcode("rr","a");
8423 pic16_emitcode("rr","a");
8429 /*-----------------------------------------------------------------*/
8430 /* AccLsh - left shift accumulator by known count */
8431 /*-----------------------------------------------------------------*/
8432 static void AccLsh (int shCount, int doMask)
8434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8440 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8443 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8447 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8448 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8451 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8454 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8455 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8458 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8459 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8462 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8466 /* no masking is required in genPackBits */
8467 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8471 /*-----------------------------------------------------------------*/
8472 /* AccRsh - right shift accumulator by known count */
8473 /*-----------------------------------------------------------------*/
8474 static void AccRsh (int shCount, int andmask)
8476 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8481 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8484 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8485 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8488 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8489 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8492 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8495 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8496 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8499 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8500 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8503 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8510 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8514 /*-----------------------------------------------------------------*/
8515 /* AccSRsh - signed right shift accumulator by known count */
8516 /*-----------------------------------------------------------------*/
8517 static void AccSRsh (int shCount)
8520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8523 pic16_emitcode("mov","c,acc.7");
8524 pic16_emitcode("rrc","a");
8525 } else if(shCount == 2){
8526 pic16_emitcode("mov","c,acc.7");
8527 pic16_emitcode("rrc","a");
8528 pic16_emitcode("mov","c,acc.7");
8529 pic16_emitcode("rrc","a");
8531 tlbl = newiTempLabel(NULL);
8532 /* rotate right accumulator */
8533 AccRol(8 - shCount);
8534 /* and kill the higher order bits */
8535 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8536 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8537 pic16_emitcode("orl","a,#0x%02x",
8538 (unsigned char)~SRMask[shCount]);
8539 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8545 /*-----------------------------------------------------------------*/
8546 /* shiftR1Left2Result - shift right one byte from left to result */
8547 /*-----------------------------------------------------------------*/
8548 static void shiftR1Left2ResultSigned (operand *left, int offl,
8549 operand *result, int offr,
8554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8556 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8560 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8562 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8564 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8565 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8571 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8573 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8575 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8576 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8578 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8579 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8585 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8587 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8588 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8591 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8592 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8593 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8595 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8596 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8598 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8602 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8603 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8604 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8605 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8606 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8610 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8612 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8613 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8615 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8616 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8617 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8618 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8619 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8624 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8625 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8626 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8627 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8628 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8631 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8632 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8633 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8634 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8635 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8641 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8642 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8643 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8644 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8647 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8648 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8656 /*-----------------------------------------------------------------*/
8657 /* shiftR1Left2Result - shift right one byte from left to result */
8658 /*-----------------------------------------------------------------*/
8659 static void shiftR1Left2Result (operand *left, int offl,
8660 operand *result, int offr,
8661 int shCount, int sign)
8665 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8667 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8669 /* Copy the msb into the carry if signed. */
8671 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8681 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8704 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8707 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8708 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8709 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8710 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8715 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8716 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8720 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8721 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8722 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8724 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8729 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8730 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8732 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8733 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8738 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8739 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8740 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8749 /*-----------------------------------------------------------------*/
8750 /* shiftL1Left2Result - shift left one byte from left to result */
8751 /*-----------------------------------------------------------------*/
8752 static void shiftL1Left2Result (operand *left, int offl,
8753 operand *result, int offr, int shCount)
8758 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8760 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8761 DEBUGpic16_emitcode ("; ***","same = %d",same);
8762 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8764 /* shift left accumulator */
8765 //AccLsh(shCount, 1); // don't comment out just yet...
8766 // pic16_aopPut(AOP(result),"a",offr);
8770 /* Shift left 1 bit position */
8771 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8773 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8775 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8776 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8780 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8781 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8782 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8786 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8787 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8788 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8789 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8793 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8794 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8795 pic16_emitpcode(POC_MOVWF,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));
8801 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8805 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8806 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8807 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8808 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8811 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8812 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8813 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8817 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8822 /*-----------------------------------------------------------------*/
8823 /* movLeft2Result - move byte from left to result */
8824 /*-----------------------------------------------------------------*/
8825 static void movLeft2Result (operand *left, int offl,
8826 operand *result, int offr)
8829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8830 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8831 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8833 if (*l == '@' && (IS_AOP_PREG(result))) {
8834 pic16_emitcode("mov","a,%s",l);
8835 pic16_aopPut(AOP(result),"a",offr);
8837 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8843 /*-----------------------------------------------------------------*/
8844 /* shiftL2Left2Result - shift left two bytes from left to result */
8845 /*-----------------------------------------------------------------*/
8846 static void shiftL2Left2Result (operand *left, int offl,
8847 operand *result, int offr, int shCount)
8849 int same = pic16_sameRegs(AOP(result), AOP(left));
8852 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8854 if (same && (offl != offr)) { // shift bytes
8857 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8858 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8860 } else { // just treat as different later on
8873 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8879 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8886 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8887 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8888 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8889 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8890 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8894 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8895 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8899 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8900 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8902 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8903 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8904 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8905 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8907 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8911 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8912 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8914 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8915 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8925 /* note, use a mov/add for the shift since the mov has a
8926 chance of getting optimized out */
8927 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8928 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8929 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8930 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8935 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8936 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8942 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8943 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8945 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8948 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8958 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8959 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8967 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8974 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8975 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8982 /*-----------------------------------------------------------------*/
8983 /* shiftR2Left2Result - shift right two bytes from left to result */
8984 /*-----------------------------------------------------------------*/
8985 static void shiftR2Left2Result (operand *left, int offl,
8986 operand *result, int offr,
8987 int shCount, int sign)
8989 int same = pic16_sameRegs(AOP(result), AOP(left));
8991 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8993 if (same && (offl != offr)) { // shift right bytes
8996 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8997 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8999 } else { // just treat as different later on
9011 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9017 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9020 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9021 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9022 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9030 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9038 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9039 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9043 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9045 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9048 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9053 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9054 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9055 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9060 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9064 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9065 pic16_emitpcode(POC_BTFSC,
9066 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9067 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9075 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9076 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9078 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9079 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9083 pic16_emitpcode(POC_BTFSC,
9084 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9085 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9087 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9090 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9092 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9093 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9094 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9095 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9096 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9099 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9101 pic16_emitpcode(POC_BTFSC,
9102 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9103 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9105 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9106 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9114 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9119 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9121 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9126 /*-----------------------------------------------------------------*/
9127 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9128 /*-----------------------------------------------------------------*/
9129 static void shiftLLeftOrResult (operand *left, int offl,
9130 operand *result, int offr, int shCount)
9132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9134 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9135 /* shift left accumulator */
9137 /* or with result */
9138 /* back to result */
9139 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9142 /*-----------------------------------------------------------------*/
9143 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9144 /*-----------------------------------------------------------------*/
9145 static void shiftRLeftOrResult (operand *left, int offl,
9146 operand *result, int offr, int shCount)
9148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9150 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9151 /* shift right accumulator */
9153 /* or with result */
9154 /* back to result */
9155 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9158 /*-----------------------------------------------------------------*/
9159 /* genlshOne - left shift a one byte quantity by known count */
9160 /*-----------------------------------------------------------------*/
9161 static void genlshOne (operand *result, operand *left, int shCount)
9163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9164 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9167 /*-----------------------------------------------------------------*/
9168 /* genlshTwo - left shift two bytes by known amount != 0 */
9169 /*-----------------------------------------------------------------*/
9170 static void genlshTwo (operand *result,operand *left, int shCount)
9174 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9175 size = pic16_getDataSize(result);
9177 /* if shCount >= 8 */
9183 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9185 movLeft2Result(left, LSB, result, MSB16);
9187 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9190 /* 1 <= shCount <= 7 */
9193 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9195 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9199 /*-----------------------------------------------------------------*/
9200 /* shiftLLong - shift left one long from left to result */
9201 /* offr = LSB or MSB16 */
9202 /*-----------------------------------------------------------------*/
9203 static void shiftLLong (operand *left, operand *result, int offr )
9205 int size = AOP_SIZE(result);
9206 int same = pic16_sameRegs(AOP(left),AOP(result));
9209 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9211 if (same && (offr == MSB16)) { //shift one byte
9212 for(i=size-1;i>=MSB16;i--) {
9213 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9217 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9220 if (size > LSB+offr ){
9222 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9224 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9225 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9229 if(size > MSB16+offr){
9231 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9233 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9234 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9238 if(size > MSB24+offr){
9240 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9242 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9243 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9247 if(size > MSB32+offr){
9249 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9251 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9252 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9256 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9260 /*-----------------------------------------------------------------*/
9261 /* genlshFour - shift four byte by a known amount != 0 */
9262 /*-----------------------------------------------------------------*/
9263 static void genlshFour (operand *result, operand *left, int shCount)
9267 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9268 size = AOP_SIZE(result);
9270 /* if shifting more that 3 bytes */
9271 if (shCount >= 24 ) {
9274 /* lowest order of left goes to the highest
9275 order of the destination */
9276 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9278 movLeft2Result(left, LSB, result, MSB32);
9280 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9281 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9282 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9287 /* more than two bytes */
9288 else if ( shCount >= 16 ) {
9289 /* lower order two bytes goes to higher order two bytes */
9291 /* if some more remaining */
9293 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9295 movLeft2Result(left, MSB16, result, MSB32);
9296 movLeft2Result(left, LSB, result, MSB24);
9298 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9299 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9303 /* if more than 1 byte */
9304 else if ( shCount >= 8 ) {
9305 /* lower order three bytes goes to higher order three bytes */
9309 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9311 movLeft2Result(left, LSB, result, MSB16);
9313 else{ /* size = 4 */
9315 movLeft2Result(left, MSB24, result, MSB32);
9316 movLeft2Result(left, MSB16, result, MSB24);
9317 movLeft2Result(left, LSB, result, MSB16);
9318 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9320 else if(shCount == 1)
9321 shiftLLong(left, result, MSB16);
9323 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9324 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9325 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9326 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9331 /* 1 <= shCount <= 7 */
9332 else if(shCount <= 3)
9334 shiftLLong(left, result, LSB);
9335 while(--shCount >= 1)
9336 shiftLLong(result, result, LSB);
9338 /* 3 <= shCount <= 7, optimize */
9340 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9341 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9342 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9346 /*-----------------------------------------------------------------*/
9347 /* genLeftShiftLiteral - left shifting by known count */
9348 /*-----------------------------------------------------------------*/
9349 void pic16_genLeftShiftLiteral (operand *left,
9354 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9358 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9359 pic16_freeAsmop(right,NULL,ic,TRUE);
9361 pic16_aopOp(left,ic,FALSE);
9362 pic16_aopOp(result,ic,TRUE);
9364 size = getSize(operandType(result));
9367 pic16_emitcode("; shift left ","result %d, left %d",size,
9371 /* I suppose that the left size >= result size */
9374 movLeft2Result(left, size, result, size);
9378 else if(shCount >= (size * 8))
9380 pic16_aopPut(AOP(result),zero,size);
9384 genlshOne (result,left,shCount);
9389 genlshTwo (result,left,shCount);
9393 genlshFour (result,left,shCount);
9397 pic16_freeAsmop(left,NULL,ic,TRUE);
9398 pic16_freeAsmop(result,NULL,ic,TRUE);
9401 /*-----------------------------------------------------------------*
9402 * genMultiAsm - repeat assembly instruction for size of register.
9403 * if endian == 1, then the high byte (i.e base address + size of
9404 * register) is used first else the low byte is used first;
9405 *-----------------------------------------------------------------*/
9406 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9411 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9424 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9430 #if !(USE_GENERIC_SIGNED_SHIFT)
9431 /*-----------------------------------------------------------------*/
9432 /* genLeftShift - generates code for left shifting */
9433 /*-----------------------------------------------------------------*/
9434 static void genLeftShift (iCode *ic)
9436 operand *left,*right, *result;
9439 symbol *tlbl , *tlbl1;
9442 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9444 right = IC_RIGHT(ic);
9446 result = IC_RESULT(ic);
9448 pic16_aopOp(right,ic,FALSE);
9450 /* if the shift count is known then do it
9451 as efficiently as possible */
9452 if (AOP_TYPE(right) == AOP_LIT) {
9453 pic16_genLeftShiftLiteral (left,right,result,ic);
9457 /* shift count is unknown then we have to form
9458 * a loop. Get the loop count in WREG : Note: we take
9459 * only the lower order byte since shifting
9460 * more than 32 bits make no sense anyway, ( the
9461 * largest size of an object can be only 32 bits ) */
9463 pic16_aopOp(left,ic,FALSE);
9464 pic16_aopOp(result,ic,FALSE);
9466 /* now move the left to the result if they are not the
9467 * same, and if size > 1,
9468 * and if right is not same to result (!!!) -- VR */
9469 if (!pic16_sameRegs(AOP(left),AOP(result))
9470 && (AOP_SIZE(result) > 1)) {
9472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9474 size = AOP_SIZE(result);
9479 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9480 if (*l == '@' && (IS_AOP_PREG(result))) {
9482 pic16_emitcode("mov","a,%s",l);
9483 pic16_aopPut(AOP(result),"a",offset);
9487 /* we don't know if left is a literal or a register, take care -- VR */
9488 pic16_mov2f(AOP(result), AOP(left), offset);
9494 size = AOP_SIZE(result);
9496 /* if it is only one byte then */
9498 if(optimized_for_speed) {
9499 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9500 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9501 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9502 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9503 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9504 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9505 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9506 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9507 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9508 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9509 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9510 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9515 tlbl = newiTempLabel(NULL);
9518 /* this is already done, why change it? */
9519 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9520 pic16_mov2f(AOP(result), AOP(left), 0);
9524 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9525 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9526 pic16_emitpLabel(tlbl->key);
9527 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9528 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9530 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9535 if (pic16_sameRegs(AOP(left),AOP(result))) {
9537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9539 tlbl = newiTempLabel(NULL);
9540 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9541 genMultiAsm(POC_RRCF, result, size,1);
9542 pic16_emitpLabel(tlbl->key);
9543 genMultiAsm(POC_RLCF, result, size,0);
9544 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9546 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9550 //tlbl = newiTempLabel(NULL);
9552 //tlbl1 = newiTempLabel(NULL);
9554 //reAdjustPreg(AOP(result));
9556 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9557 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9558 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9560 //pic16_emitcode("add","a,acc");
9561 //pic16_aopPut(AOP(result),"a",offset++);
9563 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9565 // pic16_emitcode("rlc","a");
9566 // pic16_aopPut(AOP(result),"a",offset++);
9568 //reAdjustPreg(AOP(result));
9570 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9571 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9574 tlbl = newiTempLabel(NULL);
9575 tlbl1= newiTempLabel(NULL);
9577 size = AOP_SIZE(result);
9580 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9582 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9584 /* offset should be 0, 1 or 3 */
9586 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9588 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9590 pic16_emitpcode(POC_MOVWF, pctemp);
9593 pic16_emitpLabel(tlbl->key);
9596 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9598 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9600 pic16_emitpcode(POC_DECFSZ, pctemp);
9601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602 pic16_emitpLabel(tlbl1->key);
9604 pic16_popReleaseTempReg(pctemp,1);
9608 pic16_freeAsmop (right,NULL,ic,TRUE);
9609 pic16_freeAsmop(left,NULL,ic,TRUE);
9610 pic16_freeAsmop(result,NULL,ic,TRUE);
9616 #error old code (left here for reference)
9617 /*-----------------------------------------------------------------*/
9618 /* genLeftShift - generates code for left shifting */
9619 /*-----------------------------------------------------------------*/
9620 static void genLeftShift (iCode *ic)
9622 operand *left,*right, *result;
9625 symbol *tlbl , *tlbl1;
9628 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9630 right = IC_RIGHT(ic);
9632 result = IC_RESULT(ic);
9634 pic16_aopOp(right,ic,FALSE);
9636 /* if the shift count is known then do it
9637 as efficiently as possible */
9638 if (AOP_TYPE(right) == AOP_LIT) {
9639 pic16_genLeftShiftLiteral (left,right,result,ic);
9643 /* shift count is unknown then we have to form
9644 a loop get the loop count in B : Note: we take
9645 only the lower order byte since shifting
9646 more that 32 bits make no sense anyway, ( the
9647 largest size of an object can be only 32 bits ) */
9650 pic16_aopOp(left,ic,FALSE);
9651 pic16_aopOp(result,ic,FALSE);
9653 /* now move the left to the result if they are not the
9655 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9656 AOP_SIZE(result) > 1) {
9658 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9660 size = AOP_SIZE(result);
9663 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9664 if (*l == '@' && (IS_AOP_PREG(result))) {
9666 pic16_emitcode("mov","a,%s",l);
9667 pic16_aopPut(AOP(result),"a",offset);
9670 /* we don't know if left is a literal or a register, take care -- VR */
9671 pic16_mov2f(AOP(result), AOP(left), offset);
9677 size = AOP_SIZE(result);
9679 /* if it is only one byte then */
9681 if(optimized_for_speed) {
9682 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9684 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9685 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9687 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9688 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9689 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9690 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9691 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9692 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9693 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9698 tlbl = newiTempLabel(NULL);
9699 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9700 pic16_mov2f(AOP(result), AOP(left), 0);
9702 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9703 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9706 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9707 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9708 pic16_emitpLabel(tlbl->key);
9709 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9710 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9712 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9717 if (pic16_sameRegs(AOP(left),AOP(result))) {
9719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9721 tlbl = newiTempLabel(NULL);
9722 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9723 genMultiAsm(POC_RRCF, result, size,1);
9724 pic16_emitpLabel(tlbl->key);
9725 genMultiAsm(POC_RLCF, result, size,0);
9726 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9728 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9732 //tlbl = newiTempLabel(NULL);
9734 //tlbl1 = newiTempLabel(NULL);
9736 //reAdjustPreg(AOP(result));
9738 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9739 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9740 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9742 //pic16_emitcode("add","a,acc");
9743 //pic16_aopPut(AOP(result),"a",offset++);
9745 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9747 // pic16_emitcode("rlc","a");
9748 // pic16_aopPut(AOP(result),"a",offset++);
9750 //reAdjustPreg(AOP(result));
9752 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9753 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9756 tlbl = newiTempLabel(NULL);
9757 tlbl1= newiTempLabel(NULL);
9759 size = AOP_SIZE(result);
9762 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9764 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9766 /* offset should be 0, 1 or 3 */
9768 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9770 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9772 pic16_emitpcode(POC_MOVWF, pctemp);
9775 pic16_emitpLabel(tlbl->key);
9778 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9782 pic16_emitpcode(POC_DECFSZ, pctemp);
9783 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784 pic16_emitpLabel(tlbl1->key);
9786 pic16_popReleaseTempReg(pctemp,1);
9790 pic16_freeAsmop (right,NULL,ic,TRUE);
9791 pic16_freeAsmop(left,NULL,ic,TRUE);
9792 pic16_freeAsmop(result,NULL,ic,TRUE);
9796 /*-----------------------------------------------------------------*/
9797 /* genrshOne - right shift a one byte quantity by known count */
9798 /*-----------------------------------------------------------------*/
9799 static void genrshOne (operand *result, operand *left,
9800 int shCount, int sign)
9802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9803 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9806 /*-----------------------------------------------------------------*/
9807 /* genrshTwo - right shift two bytes by known amount != 0 */
9808 /*-----------------------------------------------------------------*/
9809 static void genrshTwo (operand *result,operand *left,
9810 int shCount, int sign)
9812 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9813 /* if shCount >= 8 */
9817 shiftR1Left2Result(left, MSB16, result, LSB,
9820 movLeft2Result(left, MSB16, result, LSB);
9822 pic16_addSign (result, 1, sign);
9825 /* 1 <= shCount <= 7 */
9827 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9830 /*-----------------------------------------------------------------*/
9831 /* shiftRLong - shift right one long from left to result */
9832 /* offl = LSB or MSB16 */
9833 /*-----------------------------------------------------------------*/
9834 static void shiftRLong (operand *left, int offl,
9835 operand *result, int sign)
9837 int size = AOP_SIZE(result);
9838 int same = pic16_sameRegs(AOP(left),AOP(result));
9840 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9842 if (same && (offl == MSB16)) { //shift one byte right
9843 for(i=MSB16;i<size;i++) {
9844 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9845 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9850 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9856 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9858 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9859 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9863 /* add sign of "a" */
9864 pic16_addSign(result, MSB32, sign);
9868 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9870 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9871 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9875 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9877 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9878 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9882 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9885 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9886 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9891 /*-----------------------------------------------------------------*/
9892 /* genrshFour - shift four byte by a known amount != 0 */
9893 /*-----------------------------------------------------------------*/
9894 static void genrshFour (operand *result, operand *left,
9895 int shCount, int sign)
9897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9898 /* if shifting more that 3 bytes */
9899 if(shCount >= 24 ) {
9902 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9904 movLeft2Result(left, MSB32, result, LSB);
9906 pic16_addSign(result, MSB16, sign);
9908 else if(shCount >= 16){
9911 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9913 movLeft2Result(left, MSB24, result, LSB);
9914 movLeft2Result(left, MSB32, result, MSB16);
9916 pic16_addSign(result, MSB24, sign);
9918 else if(shCount >= 8){
9921 shiftRLong(left, MSB16, result, sign);
9922 else if(shCount == 0){
9923 movLeft2Result(left, MSB16, result, LSB);
9924 movLeft2Result(left, MSB24, result, MSB16);
9925 movLeft2Result(left, MSB32, result, MSB24);
9926 pic16_addSign(result, MSB32, sign);
9928 else{ //shcount >= 2
9929 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9930 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9931 /* the last shift is signed */
9932 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9933 pic16_addSign(result, MSB32, sign);
9936 else{ /* 1 <= shCount <= 7 */
9938 shiftRLong(left, LSB, result, sign);
9940 shiftRLong(result, LSB, result, sign);
9943 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9944 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9945 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9950 /*-----------------------------------------------------------------*/
9951 /* genRightShiftLiteral - right shifting by known count */
9952 /*-----------------------------------------------------------------*/
9953 static void genRightShiftLiteral (operand *left,
9959 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9962 pic16_freeAsmop(right,NULL,ic,TRUE);
9964 pic16_aopOp(left,ic,FALSE);
9965 pic16_aopOp(result,ic,TRUE);
9967 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9970 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9974 lsize = pic16_getDataSize(left);
9975 res_size = pic16_getDataSize(result);
9976 /* test the LEFT size !!! */
9978 /* I suppose that the left size >= result size */
9980 assert (res_size <= lsize);
9981 while (res_size--) {
9982 pic16_mov2f (AOP(result), AOP(left), res_size);
9986 else if(shCount >= (lsize * 8)){
9989 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9991 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9992 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9997 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9998 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9999 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10006 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10011 switch (res_size) {
10013 genrshOne (result,left,shCount,sign);
10017 genrshTwo (result,left,shCount,sign);
10021 genrshFour (result,left,shCount,sign);
10029 pic16_freeAsmop(left,NULL,ic,TRUE);
10030 pic16_freeAsmop(result,NULL,ic,TRUE);
10033 #if !(USE_GENERIC_SIGNED_SHIFT)
10034 /*-----------------------------------------------------------------*/
10035 /* genSignedRightShift - right shift of signed number */
10036 /*-----------------------------------------------------------------*/
10037 static void genSignedRightShift (iCode *ic)
10039 operand *right, *left, *result;
10042 symbol *tlbl, *tlbl1 ;
10045 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10047 /* we do it the hard way put the shift count in b
10048 and loop thru preserving the sign */
10049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10051 right = IC_RIGHT(ic);
10052 left = IC_LEFT(ic);
10053 result = IC_RESULT(ic);
10055 pic16_aopOp(right,ic,FALSE);
10056 pic16_aopOp(left,ic,FALSE);
10057 pic16_aopOp(result,ic,FALSE);
10060 if ( AOP_TYPE(right) == AOP_LIT) {
10061 genRightShiftLiteral (left,right,result,ic,1);
10064 /* shift count is unknown then we have to form
10065 a loop get the loop count in B : Note: we take
10066 only the lower order byte since shifting
10067 more that 32 bits make no sense anyway, ( the
10068 largest size of an object can be only 32 bits ) */
10070 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10071 //pic16_emitcode("inc","b");
10072 //pic16_freeAsmop (right,NULL,ic,TRUE);
10073 //pic16_aopOp(left,ic,FALSE);
10074 //pic16_aopOp(result,ic,FALSE);
10076 /* now move the left to the result if they are not the
10078 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10079 AOP_SIZE(result) > 1) {
10081 size = AOP_SIZE(result);
10085 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10086 if (*l == '@' && IS_AOP_PREG(result)) {
10088 pic16_emitcode("mov","a,%s",l);
10089 pic16_aopPut(AOP(result),"a",offset);
10091 pic16_aopPut(AOP(result),l,offset);
10093 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10094 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10100 /* mov the highest order bit to OVR */
10101 tlbl = newiTempLabel(NULL);
10102 tlbl1= newiTempLabel(NULL);
10104 size = AOP_SIZE(result);
10107 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10109 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10111 /* offset should be 0, 1 or 3 */
10112 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10114 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10116 pic16_emitpcode(POC_MOVWF, pctemp);
10119 pic16_emitpLabel(tlbl->key);
10121 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10122 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10125 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10128 pic16_emitpcode(POC_DECFSZ, pctemp);
10129 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10130 pic16_emitpLabel(tlbl1->key);
10132 pic16_popReleaseTempReg(pctemp,1);
10134 size = AOP_SIZE(result);
10136 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10137 pic16_emitcode("rlc","a");
10138 pic16_emitcode("mov","ov,c");
10139 /* if it is only one byte then */
10141 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10143 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10144 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10145 pic16_emitcode("mov","c,ov");
10146 pic16_emitcode("rrc","a");
10147 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10148 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10149 pic16_aopPut(AOP(result),"a",0);
10153 reAdjustPreg(AOP(result));
10154 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10155 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10156 pic16_emitcode("mov","c,ov");
10158 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10160 pic16_emitcode("rrc","a");
10161 pic16_aopPut(AOP(result),"a",offset--);
10163 reAdjustPreg(AOP(result));
10164 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10165 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10170 pic16_freeAsmop(left,NULL,ic,TRUE);
10171 pic16_freeAsmop(result,NULL,ic,TRUE);
10172 pic16_freeAsmop(right,NULL,ic,TRUE);
10176 #if !(USE_GENERIC_SIGNED_SHIFT)
10177 #warning This implementation of genRightShift() is incomplete!
10178 /*-----------------------------------------------------------------*/
10179 /* genRightShift - generate code for right shifting */
10180 /*-----------------------------------------------------------------*/
10181 static void genRightShift (iCode *ic)
10183 operand *right, *left, *result;
10187 symbol *tlbl, *tlbl1 ;
10189 /* if signed then we do it the hard way preserve the
10190 sign bit moving it inwards */
10191 letype = getSpec(operandType(IC_LEFT(ic)));
10192 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10194 if (!SPEC_USIGN(letype)) {
10195 genSignedRightShift (ic);
10199 /* signed & unsigned types are treated the same : i.e. the
10200 signed is NOT propagated inwards : quoting from the
10201 ANSI - standard : "for E1 >> E2, is equivalent to division
10202 by 2**E2 if unsigned or if it has a non-negative value,
10203 otherwise the result is implementation defined ", MY definition
10204 is that the sign does not get propagated */
10206 right = IC_RIGHT(ic);
10207 left = IC_LEFT(ic);
10208 result = IC_RESULT(ic);
10210 pic16_aopOp(right,ic,FALSE);
10212 /* if the shift count is known then do it
10213 as efficiently as possible */
10214 if (AOP_TYPE(right) == AOP_LIT) {
10215 genRightShiftLiteral (left,right,result,ic, 0);
10219 /* shift count is unknown then we have to form
10220 a loop get the loop count in B : Note: we take
10221 only the lower order byte since shifting
10222 more that 32 bits make no sense anyway, ( the
10223 largest size of an object can be only 32 bits ) */
10225 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10226 pic16_emitcode("inc","b");
10227 pic16_aopOp(left,ic,FALSE);
10228 pic16_aopOp(result,ic,FALSE);
10230 /* now move the left to the result if they are not the
10232 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10233 AOP_SIZE(result) > 1) {
10235 size = AOP_SIZE(result);
10238 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10239 if (*l == '@' && IS_AOP_PREG(result)) {
10241 pic16_emitcode("mov","a,%s",l);
10242 pic16_aopPut(AOP(result),"a",offset);
10244 pic16_aopPut(AOP(result),l,offset);
10249 tlbl = newiTempLabel(NULL);
10250 tlbl1= newiTempLabel(NULL);
10251 size = AOP_SIZE(result);
10254 /* if it is only one byte then */
10257 tlbl = newiTempLabel(NULL);
10258 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10259 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10260 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10263 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10264 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10265 pic16_emitpLabel(tlbl->key);
10266 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10267 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10269 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10274 reAdjustPreg(AOP(result));
10275 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10276 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10279 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10281 pic16_emitcode("rrc","a");
10282 pic16_aopPut(AOP(result),"a",offset--);
10284 reAdjustPreg(AOP(result));
10286 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10287 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10290 pic16_freeAsmop(left,NULL,ic,TRUE);
10291 pic16_freeAsmop (right,NULL,ic,TRUE);
10292 pic16_freeAsmop(result,NULL,ic,TRUE);
10296 #if (USE_GENERIC_SIGNED_SHIFT)
10297 /*-----------------------------------------------------------------*/
10298 /* genGenericShift - generates code for left or right shifting */
10299 /*-----------------------------------------------------------------*/
10300 static void genGenericShift (iCode *ic, int isShiftLeft) {
10301 operand *left,*right, *result;
10303 int sign, signedCount;
10304 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10305 PIC_OPCODE pos_shift, neg_shift;
10309 right = IC_RIGHT(ic);
10310 left = IC_LEFT(ic);
10311 result = IC_RESULT(ic);
10313 pic16_aopOp(right,ic,FALSE);
10314 pic16_aopOp(left,ic,FALSE);
10315 pic16_aopOp(result,ic,TRUE);
10317 sign = !SPEC_USIGN(operandType (left));
10318 signedCount = !SPEC_USIGN(operandType (right));
10320 /* if the shift count is known then do it
10321 as efficiently as possible */
10322 if (AOP_TYPE(right) == AOP_LIT) {
10323 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10324 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10325 // we should modify right->aopu.aop_lit here!
10326 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10327 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10329 pic16_genLeftShiftLiteral (left,right,result,ic);
10331 genRightShiftLiteral (left,right,result,ic, sign);
10334 } // if (right is literal)
10336 /* shift count is unknown then we have to form a loop.
10337 * Note: we take only the lower order byte since shifting
10338 * more than 32 bits make no sense anyway, ( the
10339 * largest size of an object can be only 32 bits )
10340 * Note: we perform arithmetic shifts if the left operand is
10341 * signed and we do an (effective) right shift, i. e. we
10342 * shift in the sign bit from the left. */
10344 label_complete = newiTempLabel ( NULL );
10345 label_loop_pos = newiTempLabel ( NULL );
10346 label_loop_neg = NULL;
10347 label_negative = NULL;
10348 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10349 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10352 // additional labels needed
10353 label_loop_neg = newiTempLabel ( NULL );
10354 label_negative = newiTempLabel ( NULL );
10357 // copy source to result -- this will effectively truncate the left operand to the size of result!
10358 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10359 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10360 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10361 pic16_mov2f (AOP(result),AOP(left), offset);
10364 // if result is longer than left, fill with zeros (or sign)
10365 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10366 if (sign && AOP_SIZE(left) > 0) {
10367 // shift signed operand -- fill with sign
10368 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10369 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10370 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10371 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10372 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10375 // shift unsigned operand -- fill result with zeros
10376 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10377 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10380 } // if (size mismatch)
10382 pic16_mov2w (AOP(right), 0);
10383 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10384 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10387 // perform a shift by one (shift count is positive)
10388 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10389 // 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])
10390 pic16_emitpLabel (label_loop_pos->key);
10392 if (sign && (pos_shift == POC_RRCF)) {
10393 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10396 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10397 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10398 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10400 // perform a shift by one (shift count is positive)
10401 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10402 // 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])
10403 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10404 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10406 pic16_emitpLabel (label_loop_pos->key);
10407 if (sign && (pos_shift == POC_RRCF)) {
10408 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10411 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10412 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10413 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10414 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10418 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10420 pic16_emitpLabel (label_negative->key);
10421 // perform a shift by -1 (shift count is negative)
10422 // 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)
10424 pic16_emitpLabel (label_loop_neg->key);
10425 if (sign && (neg_shift == POC_RRCF)) {
10426 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10429 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10430 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10431 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10432 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10433 } // if (signedCount)
10435 pic16_emitpLabel (label_complete->key);
10438 pic16_freeAsmop (right,NULL,ic,TRUE);
10439 pic16_freeAsmop(left,NULL,ic,TRUE);
10440 pic16_freeAsmop(result,NULL,ic,TRUE);
10443 static void genLeftShift (iCode *ic) {
10444 genGenericShift (ic, 1);
10447 static void genRightShift (iCode *ic) {
10448 genGenericShift (ic, 0);
10453 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10454 void pic16_loadFSR0(operand *op, int lit)
10456 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10457 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10459 assert (!OP_SYMBOL(op)->remat);
10460 // set up FSR0 with address of result
10461 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10462 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10466 /*----------------------------------------------------------------*/
10467 /* pic16_derefPtr - move one byte from the location ptr points to */
10468 /* to WREG (doWrite == 0) or one byte from WREG */
10469 /* to the location ptr points to (doWrite != 0) */
10470 /*----------------------------------------------------------------*/
10471 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10473 if (!IS_PTR(operandType(ptr)))
10475 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10476 else pic16_mov2w (AOP(ptr), 0);
10480 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10481 /* We might determine pointer type right here: */
10482 p_type = DCL_TYPE(operandType(ptr));
10487 if (!fsr0_setup || !*fsr0_setup)
10489 pic16_loadFSR0( ptr, 0 );
10490 if (fsr0_setup) *fsr0_setup = 1;
10493 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10495 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10499 if (AOP(ptr)->aopu.aop_reg[2]) {
10500 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10501 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10502 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10503 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10504 pic16_mov2w(AOP(ptr), 2);
10505 pic16_callGenericPointerRW(doWrite, 1);
10507 // data pointer (just 2 byte given)
10508 if (!fsr0_setup || !*fsr0_setup)
10510 pic16_loadFSR0( ptr, 0 );
10511 if (fsr0_setup) *fsr0_setup = 1;
10514 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10516 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10521 assert (0 && "invalid pointer type specified");
10526 /*-----------------------------------------------------------------*/
10527 /* genUnpackBits - generates code for unpacking bits */
10528 /*-----------------------------------------------------------------*/
10529 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10532 sym_link *etype, *letype;
10533 int blen=0, bstr=0;
10538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10539 etype = getSpec(operandType(result));
10540 letype = getSpec(operandType(left));
10542 // if(IS_BITFIELD(etype)) {
10543 blen = SPEC_BLEN(etype);
10544 bstr = SPEC_BSTR(etype);
10547 lbstr = SPEC_BSTR( letype );
10549 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10550 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10553 if((blen == 1) && (bstr < 8)
10554 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10555 /* it is a single bit, so use the appropriate bit instructions */
10556 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10558 same = pic16_sameRegs(AOP(left),AOP(result));
10559 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10560 pic16_emitpcode(POC_CLRF, op);
10562 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10563 /* workaround to reduce the extra lfsr instruction */
10564 pic16_emitpcode(POC_BTFSC,
10565 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10567 assert (PIC_IS_DATA_PTR (operandType(left)));
10568 pic16_loadFSR0 (left, 0);
10569 pic16_emitpcode(POC_BTFSC,
10570 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10573 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10574 /* unsigned bitfields result in either 0 or 1 */
10575 pic16_emitpcode(POC_INCF, op);
10577 /* signed bitfields result in either 0 or -1 */
10578 pic16_emitpcode(POC_DECF, op);
10581 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10584 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10590 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10591 // access symbol directly
10592 pic16_mov2w (AOP(left), 0);
10594 pic16_derefPtr (left, ptype, 0, NULL);
10597 /* if we have bitdisplacement then it fits */
10598 /* into this byte completely or if length is */
10599 /* less than a byte */
10600 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10602 /* shift right acc */
10605 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10606 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10608 /* VR -- normally I would use the following, but since we use the hack,
10609 * to avoid the masking from AccRsh, why not mask it right now? */
10612 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10615 /* extend signed bitfields to 8 bits */
10616 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10618 assert (blen + bstr > 0);
10619 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10620 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10623 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10625 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10629 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10630 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10637 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10639 int size, offset = 0, leoffset=0 ;
10641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10642 pic16_aopOp(result, ic, TRUE);
10646 size = AOP_SIZE(result);
10647 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10651 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10652 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10653 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10658 if(AOP(left)->aopu.pcop->type == PO_DIR)
10659 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10661 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10664 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10666 // pic16_DumpOp("(result)",result);
10667 if(is_LitAOp(AOP(result))) {
10668 pic16_mov2w(AOP(left), offset); // patch 8
10669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10671 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10672 pic16_popGet(AOP(left), offset), //patch 8
10673 pic16_popGet(AOP(result), offset)));
10681 pic16_freeAsmop(result,NULL,ic,TRUE);
10686 /*-----------------------------------------------------------------*/
10687 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10688 /*-----------------------------------------------------------------*/
10689 static void genNearPointerGet (operand *left,
10693 // asmop *aop = NULL;
10694 //regs *preg = NULL ;
10695 sym_link *rtype, *retype;
10696 sym_link *ltype, *letype;
10700 rtype = operandType(result);
10701 retype= getSpec(rtype);
10702 ltype = operandType(left);
10703 letype= getSpec(ltype);
10705 pic16_aopOp(left,ic,FALSE);
10707 // pic16_DumpOp("(left)",left);
10708 // pic16_DumpOp("(result)",result);
10710 /* if left is rematerialisable and
10711 * result is not bit variable type and
10712 * the left is pointer to data space i.e
10713 * lower 128 bytes of space */
10715 if (AOP_TYPE(left) == AOP_PCODE
10716 && !IS_BITFIELD(retype)
10717 && DCL_TYPE(ltype) == POINTER) {
10719 genDataPointerGet (left,result,ic);
10720 pic16_freeAsmop(left, NULL, ic, TRUE);
10724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10725 pic16_aopOp (result,ic,TRUE);
10727 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10730 if(IS_BITFIELD( retype )
10731 && (SPEC_BLEN(operandType(result))==1)
10735 int bitstrt, bytestrt;
10737 /* if this is bitfield of size 1, see if we are checking the value
10738 * of a single bit in an if-statement,
10739 * if yes, then don't generate usual code, but execute the
10740 * genIfx directly -- VR */
10744 /* CHECK: if next iCode is IFX
10745 * and current result operand is nextic's conditional operand
10746 * and current result operand live ranges ends at nextic's key number
10748 if((nextic->op == IFX)
10749 && (result == IC_COND(nextic))
10750 && (OP_LIVETO(result) == nextic->seq)
10751 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10753 /* everything is ok then */
10754 /* find a way to optimize the genIfx iCode */
10756 bytestrt = SPEC_BSTR(operandType(result))/8;
10757 bitstrt = SPEC_BSTR(operandType(result))%8;
10759 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10761 genIfxpCOpJump(nextic, jop);
10763 pic16_freeAsmop(left, NULL, ic, TRUE);
10764 pic16_freeAsmop(result, NULL, ic, TRUE);
10770 /* if bitfield then unpack the bits */
10771 if (IS_BITFIELD(letype))
10772 genUnpackBits (result, left, NULL, POINTER);
10774 /* we have can just get the values */
10775 int size = AOP_SIZE(result);
10778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10780 pic16_loadFSR0( left, 0 );
10784 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10785 pic16_popGet(AOP(result), offset++)));
10787 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10788 pic16_popGet(AOP(result), offset++)));
10794 /* now some housekeeping stuff */
10796 /* we had to allocate for this iCode */
10797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10798 pic16_freeAsmop(NULL,aop,ic,TRUE);
10800 /* we did not allocate which means left
10801 * already in a pointer register, then
10802 * if size > 0 && this could be used again
10803 * we have to point it back to where it
10805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10806 if (AOP_SIZE(result) > 1
10807 && !OP_SYMBOL(left)->remat
10808 && ( OP_SYMBOL(left)->liveTo > ic->seq
10810 // int size = AOP_SIZE(result) - 1;
10812 // pic16_emitcode("dec","%s",rname);
10818 pic16_freeAsmop(left,NULL,ic,TRUE);
10819 pic16_freeAsmop(result,NULL,ic,TRUE);
10822 /*-----------------------------------------------------------------*/
10823 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10824 /*-----------------------------------------------------------------*/
10825 static void genPagedPointerGet (operand *left,
10830 regs *preg = NULL ;
10832 sym_link *rtype, *retype;
10834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10836 rtype = operandType(result);
10837 retype= getSpec(rtype);
10839 pic16_aopOp(left,ic,FALSE);
10841 /* if the value is already in a pointer register
10842 then don't need anything more */
10843 if (!AOP_INPREG(AOP(left))) {
10844 /* otherwise get a free pointer register */
10846 preg = getFreePtr(ic,&aop,FALSE);
10847 pic16_emitcode("mov","%s,%s",
10849 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10850 rname = preg->name ;
10852 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10854 pic16_freeAsmop(left,NULL,ic,TRUE);
10855 pic16_aopOp (result,ic,TRUE);
10857 /* if bitfield then unpack the bits */
10858 if (IS_BITFIELD(retype))
10859 genUnpackBits (result,left,rname,PPOINTER);
10861 /* we have can just get the values */
10862 int size = AOP_SIZE(result);
10867 pic16_emitcode("movx","a,@%s",rname);
10868 pic16_aopPut(AOP(result),"a",offset);
10873 pic16_emitcode("inc","%s",rname);
10877 /* now some housekeeping stuff */
10879 /* we had to allocate for this iCode */
10880 pic16_freeAsmop(NULL,aop,ic,TRUE);
10882 /* we did not allocate which means left
10883 already in a pointer register, then
10884 if size > 0 && this could be used again
10885 we have to point it back to where it
10887 if (AOP_SIZE(result) > 1 &&
10888 !OP_SYMBOL(left)->remat &&
10889 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10891 int size = AOP_SIZE(result) - 1;
10893 pic16_emitcode("dec","%s",rname);
10898 pic16_freeAsmop(result,NULL,ic,TRUE);
10904 /* This code is not adjusted to PIC16 and fails utterly.
10905 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10907 /*-----------------------------------------------------------------*/
10908 /* genFarPointerGet - gget value from far space */
10909 /*-----------------------------------------------------------------*/
10910 static void genFarPointerGet (operand *left,
10911 operand *result, iCode *ic)
10914 sym_link *retype = getSpec(operandType(result));
10916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10918 pic16_aopOp(left,ic,FALSE);
10920 /* if the operand is already in dptr
10921 then we do nothing else we move the value to dptr */
10922 if (AOP_TYPE(left) != AOP_STR) {
10923 /* if this is remateriazable */
10924 if (AOP_TYPE(left) == AOP_IMMD)
10925 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10926 else { /* we need to get it byte by byte */
10927 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10928 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10929 if (options.model == MODEL_FLAT24)
10931 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10935 /* so dptr know contains the address */
10936 pic16_freeAsmop(left,NULL,ic,TRUE);
10937 pic16_aopOp(result,ic,TRUE);
10939 /* if bit then unpack */
10940 if (IS_BITFIELD(retype))
10941 genUnpackBits(result,left,"dptr",FPOINTER);
10943 size = AOP_SIZE(result);
10947 pic16_emitcode("movx","a,@dptr");
10948 pic16_aopPut(AOP(result),"a",offset++);
10950 pic16_emitcode("inc","dptr");
10954 pic16_freeAsmop(result,NULL,ic,TRUE);
10959 /*-----------------------------------------------------------------*/
10960 /* genCodePointerGet - get value from code space */
10961 /*-----------------------------------------------------------------*/
10962 static void genCodePointerGet (operand *left,
10963 operand *result, iCode *ic)
10966 sym_link *retype = getSpec(operandType(result));
10968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10970 pic16_aopOp(left,ic,FALSE);
10972 /* if the operand is already in dptr
10973 then we do nothing else we move the value to dptr */
10974 if (AOP_TYPE(left) != AOP_STR) {
10975 /* if this is remateriazable */
10976 if (AOP_TYPE(left) == AOP_IMMD)
10977 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10978 else { /* we need to get it byte by byte */
10979 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10980 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10981 if (options.model == MODEL_FLAT24)
10983 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10987 /* so dptr know contains the address */
10988 pic16_freeAsmop(left,NULL,ic,TRUE);
10989 pic16_aopOp(result,ic,FALSE);
10991 /* if bit then unpack */
10992 if (IS_BITFIELD(retype))
10993 genUnpackBits(result,left,"dptr",CPOINTER);
10995 size = AOP_SIZE(result);
10999 pic16_emitcode("clr","a");
11000 pic16_emitcode("movc","a,@a+dptr");
11001 pic16_aopPut(AOP(result),"a",offset++);
11003 pic16_emitcode("inc","dptr");
11007 pic16_freeAsmop(result,NULL,ic,TRUE);
11012 /*-----------------------------------------------------------------*/
11013 /* genGenPointerGet - gget value from generic pointer space */
11014 /*-----------------------------------------------------------------*/
11015 static void genGenPointerGet (operand *left,
11016 operand *result, iCode *ic)
11018 int size, offset, lit;
11019 sym_link *retype = getSpec(operandType(result));
11021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11022 pic16_aopOp(left,ic,FALSE);
11023 pic16_aopOp(result,ic,FALSE);
11024 size = AOP_SIZE(result);
11026 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11028 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11030 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11031 // load FSR0 from immediate
11032 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11034 // pic16_loadFSR0( left );
11039 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11041 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11048 else { /* we need to get it byte by byte */
11049 // set up FSR0 with address from left
11050 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11051 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11057 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11059 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11066 /* if bit then unpack */
11067 if (IS_BITFIELD(retype))
11068 genUnpackBits(result,left,"BAD",GPOINTER);
11071 pic16_freeAsmop(left,NULL,ic,TRUE);
11072 pic16_freeAsmop(result,NULL,ic,TRUE);
11078 /*-----------------------------------------------------------------*/
11079 /* genGenPointerGet - gget value from generic pointer space */
11080 /*-----------------------------------------------------------------*/
11081 static void genGenPointerGet (operand *left,
11082 operand *result, iCode *ic)
11084 int size, offset, lit;
11085 sym_link *letype = getSpec(operandType(left));
11087 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11088 pic16_aopOp(left,ic,FALSE);
11089 pic16_aopOp(result,ic,TRUE);
11090 size = AOP_SIZE(result);
11092 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11094 /* if bit then unpack */
11095 if (IS_BITFIELD(letype)) {
11096 genUnpackBits(result,left,"BAD",GPOINTER);
11100 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11102 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11103 // load FSR0 from immediate
11104 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11106 werror(W_POSSBUG2, __FILE__, __LINE__);
11111 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11120 } else { /* we need to get it byte by byte */
11122 /* set up WREG:PRODL:FSR0L with address from left */
11123 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11124 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11125 pic16_mov2w(AOP(left), 2);
11126 pic16_callGenericPointerRW(0, size);
11128 assignResultValue(result, 1);
11134 pic16_freeAsmop(left,NULL,ic,TRUE);
11135 pic16_freeAsmop(result,NULL,ic,TRUE);
11138 /*-----------------------------------------------------------------*/
11139 /* genConstPointerGet - get value from const generic pointer space */
11140 /*-----------------------------------------------------------------*/
11141 static void genConstPointerGet (operand *left,
11142 operand *result, iCode *ic)
11144 //sym_link *retype = getSpec(operandType(result));
11145 // symbol *albl = newiTempLabel(NULL); // patch 15
11146 // symbol *blbl = newiTempLabel(NULL); //
11147 // PIC_OPCODE poc; // patch 15
11151 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11152 pic16_aopOp(left,ic,FALSE);
11153 pic16_aopOp(result,ic,TRUE);
11154 size = AOP_SIZE(result);
11156 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11158 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11160 // set up table pointer
11161 if( (AOP_TYPE(left) == AOP_PCODE)
11162 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11163 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11165 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11166 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11167 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11168 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11169 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11170 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11172 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11173 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11174 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11178 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11179 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11183 pic16_freeAsmop(left,NULL,ic,TRUE);
11184 pic16_freeAsmop(result,NULL,ic,TRUE);
11188 /*-----------------------------------------------------------------*/
11189 /* genPointerGet - generate code for pointer get */
11190 /*-----------------------------------------------------------------*/
11191 static void genPointerGet (iCode *ic)
11193 operand *left, *result ;
11194 sym_link *type, *etype;
11199 left = IC_LEFT(ic);
11200 result = IC_RESULT(ic) ;
11202 /* depending on the type of pointer we need to
11203 move it to the correct pointer register */
11204 type = operandType(left);
11205 etype = getSpec(type);
11208 if (IS_PTR_CONST(type))
11210 if (IS_CODEPTR(type))
11212 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11214 /* if left is of type of pointer then it is simple */
11215 if (IS_PTR(type) && !IS_FUNC(type->next))
11216 p_type = DCL_TYPE(type);
11218 /* we have to go by the storage class */
11219 p_type = PTR_TYPE(SPEC_OCLS(etype));
11221 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11223 if (SPEC_OCLS(etype)->codesp ) {
11224 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11225 //p_type = CPOINTER ;
11227 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11228 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11229 /*p_type = FPOINTER ;*/
11231 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11232 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11233 /* p_type = PPOINTER; */
11235 if (SPEC_OCLS(etype) == idata ) {
11236 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11237 /* p_type = IPOINTER; */
11239 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11240 /* p_type = POINTER ; */
11244 /* now that we have the pointer type we assign
11245 the pointer values */
11250 genNearPointerGet (left,result,ic);
11254 genPagedPointerGet(left,result,ic);
11258 /* PICs do not support FAR pointers... */
11259 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11261 genFarPointerGet (left,result,ic);
11266 genConstPointerGet (left,result,ic);
11267 //pic16_emitcodePointerGet (left,result,ic);
11272 if (IS_PTR_CONST(type))
11273 genConstPointerGet (left,result,ic);
11276 genGenPointerGet (left,result,ic);
11280 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11281 "genPointerGet: illegal pointer type");
11286 /*-----------------------------------------------------------------*/
11287 /* genPackBits - generates code for packed bit storage */
11288 /*-----------------------------------------------------------------*/
11289 static void genPackBits (sym_link *etype , operand *result,
11291 char *rname, int p_type)
11297 int shifted_and_masked = 0;
11298 unsigned long lit = (unsigned long)-1;
11301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11302 blen = SPEC_BLEN(etype);
11303 bstr = SPEC_BSTR(etype);
11305 retype = getSpec(operandType(right));
11307 if(AOP_TYPE(right) == AOP_LIT) {
11308 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11310 if((blen == 1) && (bstr < 8)) {
11311 /* it is a single bit, so use the appropriate bit instructions */
11313 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11315 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11316 /* workaround to reduce the extra lfsr instruction */
11318 pic16_emitpcode(POC_BSF,
11319 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11321 pic16_emitpcode(POC_BCF,
11322 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11325 if (PIC_IS_DATA_PTR(operandType(result))) {
11326 pic16_loadFSR0(result, 0);
11327 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11328 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11330 /* get old value */
11331 pic16_derefPtr (result, p_type, 0, NULL);
11332 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11333 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11334 /* write back new value */
11335 pic16_derefPtr (result, p_type, 1, NULL);
11341 /* IORLW below is more efficient */
11342 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11343 lit = (lit & ((1UL << blen) - 1)) << bstr;
11344 shifted_and_masked = 1;
11347 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11348 && IS_BITFIELD(retype)
11349 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11353 rblen = SPEC_BLEN( retype );
11354 rbstr = SPEC_BSTR( retype );
11356 if(IS_BITFIELD(etype)) {
11357 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11358 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11360 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11363 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11365 if(IS_BITFIELD(etype)) {
11366 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11368 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11371 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11375 /* move right to W */
11376 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11379 /* if the bit length is less than or */
11380 /* it exactly fits a byte then */
11381 if((shCnt=SPEC_BSTR(etype))
11382 || SPEC_BLEN(etype) <= 8 ) {
11383 int fsr0_setup = 0;
11385 if (blen != 8 || bstr != 0) {
11386 // we need to combine the value with the old value
11387 if(!shifted_and_masked)
11389 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11391 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11392 SPEC_BSTR(etype), SPEC_BLEN(etype));
11394 /* shift left acc, do NOT mask the result again */
11397 /* using PRODH as a temporary register here */
11398 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11401 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11402 || IS_DIRECT(result)) {
11403 /* access symbol directly */
11404 pic16_mov2w (AOP(result), 0);
11406 /* get old value */
11407 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11410 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11411 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11412 (unsigned char)(0xff >> (8-bstr))) ));
11413 if (!shifted_and_masked) {
11414 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11416 /* We have the shifted and masked (literal) right value in `lit' */
11418 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11420 } // if (blen != 8 || bstr != 0)
11422 /* write new value back */
11423 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11424 || IS_DIRECT(result)) {
11425 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11427 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11436 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11437 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11442 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11443 rLen = SPEC_BLEN(etype)-8;
11445 /* now generate for lengths greater than one byte */
11449 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11455 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11461 pic16_emitcode("movx","@dptr,a");
11466 DEBUGpic16_emitcode(";lcall","__gptrput");
11474 pic16_mov2w(AOP(right), offset++);
11477 /* last last was not complete */
11479 /* save the byte & read byte */
11482 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11483 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11488 pic16_emitcode ("mov","b,a");
11489 pic16_emitcode("movx","a,@dptr");
11493 pic16_emitcode ("push","b");
11494 pic16_emitcode ("push","acc");
11495 pic16_emitcode ("lcall","__gptrget");
11496 pic16_emitcode ("pop","b");
11502 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11503 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11504 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11505 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11506 // pic16_emitcode ("orl","a,b");
11509 // if (p_type == GPOINTER)
11510 // pic16_emitcode("pop","b");
11515 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11516 // pic16_emitcode("mov","@%s,a",rname);
11520 pic16_emitcode("movx","@dptr,a");
11524 DEBUGpic16_emitcode(";lcall","__gptrput");
11531 // pic16_freeAsmop(right, NULL, ic, TRUE);
11534 /*-----------------------------------------------------------------*/
11535 /* genDataPointerSet - remat pointer to data space */
11536 /*-----------------------------------------------------------------*/
11537 static void genDataPointerSet(operand *right,
11541 int size, offset = 0, resoffset=0 ;
11543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11544 pic16_aopOp(right,ic,FALSE);
11546 size = AOP_SIZE(right);
11548 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11551 if ( AOP_TYPE(result) == AOP_PCODE) {
11552 fprintf(stderr,"genDataPointerSet %s, %d\n",
11553 AOP(result)->aopu.pcop->name,
11554 (AOP(result)->aopu.pcop->type == PO_DIR)?
11555 PCOR(AOP(result)->aopu.pcop)->instance:
11556 PCOI(AOP(result)->aopu.pcop)->offset);
11560 if(AOP(result)->aopu.pcop->type == PO_DIR)
11561 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11564 if (AOP_TYPE(right) == AOP_LIT) {
11567 if(!IS_FLOAT(operandType( right )))
11568 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11571 unsigned long lit_int;
11575 /* take care if literal is a float */
11576 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11577 lit = info.lit_int;
11579 lit = lit >> (8*offset);
11580 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11582 pic16_mov2w(AOP(right), offset);
11583 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11589 pic16_freeAsmop(right,NULL,ic,TRUE);
11594 /*-----------------------------------------------------------------*/
11595 /* genNearPointerSet - pic16_emitcode for near pointer put */
11596 /*-----------------------------------------------------------------*/
11597 static void genNearPointerSet (operand *right,
11603 sym_link *ptype = operandType(result);
11604 sym_link *resetype;
11606 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11607 retype= getSpec(operandType(right));
11608 resetype = getSpec(operandType(result));
11610 pic16_aopOp(result,ic,FALSE);
11612 /* if the result is rematerializable &
11613 * in data space & not a bit variable */
11615 /* and result is not a bit variable */
11616 if (AOP_TYPE(result) == AOP_PCODE
11617 // && AOP_TYPE(result) == AOP_IMMD
11618 && DCL_TYPE(ptype) == POINTER
11619 && !IS_BITFIELD(retype)
11620 && !IS_BITFIELD(resetype)) {
11622 genDataPointerSet (right,result,ic);
11623 pic16_freeAsmop(result,NULL,ic,TRUE);
11627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11628 pic16_aopOp(right,ic,FALSE);
11629 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11631 /* if bitfield then unpack the bits */
11632 if (IS_BITFIELD(resetype)) {
11633 genPackBits (resetype, result, right, NULL, POINTER);
11635 /* we have can just get the values */
11636 int size = AOP_SIZE(right);
11639 pic16_loadFSR0(result, 0);
11641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11643 if (AOP_TYPE(right) == AOP_LIT) {
11644 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11646 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11648 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11650 } else { // no literal
11652 pic16_emitpcode(POC_MOVFF,
11653 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11654 pic16_popCopyReg(&pic16_pc_postinc0)));
11656 pic16_emitpcode(POC_MOVFF,
11657 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11658 pic16_popCopyReg(&pic16_pc_indf0)));
11666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11667 /* now some housekeeping stuff */
11669 /* we had to allocate for this iCode */
11670 pic16_freeAsmop(NULL,aop,ic,TRUE);
11672 /* we did not allocate which means left
11673 * already in a pointer register, then
11674 * if size > 0 && this could be used again
11675 * we have to point it back to where it
11677 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11678 if (AOP_SIZE(right) > 1
11679 && !OP_SYMBOL(result)->remat
11680 && ( OP_SYMBOL(result)->liveTo > ic->seq
11683 int size = AOP_SIZE(right) - 1;
11686 pic16_emitcode("decf","fsr0,f");
11687 //pic16_emitcode("dec","%s",rname);
11691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11694 pic16_freeAsmop(right,NULL,ic,TRUE);
11695 pic16_freeAsmop(result,NULL,ic,TRUE);
11698 /*-----------------------------------------------------------------*/
11699 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11700 /*-----------------------------------------------------------------*/
11701 static void genPagedPointerSet (operand *right,
11706 regs *preg = NULL ;
11710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11712 retype= getSpec(operandType(right));
11714 pic16_aopOp(result,ic,FALSE);
11716 /* if the value is already in a pointer register
11717 then don't need anything more */
11718 if (!AOP_INPREG(AOP(result))) {
11719 /* otherwise get a free pointer register */
11721 preg = getFreePtr(ic,&aop,FALSE);
11722 pic16_emitcode("mov","%s,%s",
11724 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11725 rname = preg->name ;
11727 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11729 pic16_freeAsmop(result,NULL,ic,TRUE);
11730 pic16_aopOp (right,ic,FALSE);
11732 /* if bitfield then unpack the bits */
11733 if (IS_BITFIELD(retype))
11734 genPackBits (retype,result,right,rname,PPOINTER);
11736 /* we have can just get the values */
11737 int size = AOP_SIZE(right);
11741 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11744 pic16_emitcode("movx","@%s,a",rname);
11747 pic16_emitcode("inc","%s",rname);
11753 /* now some housekeeping stuff */
11755 /* we had to allocate for this iCode */
11756 pic16_freeAsmop(NULL,aop,ic,TRUE);
11758 /* we did not allocate which means left
11759 already in a pointer register, then
11760 if size > 0 && this could be used again
11761 we have to point it back to where it
11763 if (AOP_SIZE(right) > 1 &&
11764 !OP_SYMBOL(result)->remat &&
11765 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11767 int size = AOP_SIZE(right) - 1;
11769 pic16_emitcode("dec","%s",rname);
11774 pic16_freeAsmop(right,NULL,ic,TRUE);
11780 /* This code is not adjusted to PIC16 and fails utterly...
11781 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11783 /*-----------------------------------------------------------------*/
11784 /* genFarPointerSet - set value from far space */
11785 /*-----------------------------------------------------------------*/
11786 static void genFarPointerSet (operand *right,
11787 operand *result, iCode *ic)
11790 sym_link *retype = getSpec(operandType(right));
11792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11793 pic16_aopOp(result,ic,FALSE);
11795 /* if the operand is already in dptr
11796 then we do nothing else we move the value to dptr */
11797 if (AOP_TYPE(result) != AOP_STR) {
11798 /* if this is remateriazable */
11799 if (AOP_TYPE(result) == AOP_IMMD)
11800 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11801 else { /* we need to get it byte by byte */
11802 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11803 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11804 if (options.model == MODEL_FLAT24)
11806 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11810 /* so dptr know contains the address */
11811 pic16_freeAsmop(result,NULL,ic,TRUE);
11812 pic16_aopOp(right,ic,FALSE);
11814 /* if bit then unpack */
11815 if (IS_BITFIELD(retype))
11816 genPackBits(retype,result,right,"dptr",FPOINTER);
11818 size = AOP_SIZE(right);
11822 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11824 pic16_emitcode("movx","@dptr,a");
11826 pic16_emitcode("inc","dptr");
11830 pic16_freeAsmop(right,NULL,ic,TRUE);
11834 /*-----------------------------------------------------------------*/
11835 /* genGenPointerSet - set value from generic pointer space */
11836 /*-----------------------------------------------------------------*/
11838 static void genGenPointerSet (operand *right,
11839 operand *result, iCode *ic)
11841 int i, size, offset, lit;
11842 sym_link *retype = getSpec(operandType(right));
11844 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11846 pic16_aopOp(result,ic,FALSE);
11847 pic16_aopOp(right,ic,FALSE);
11848 size = AOP_SIZE(right);
11851 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11853 /* if the operand is already in dptr
11854 then we do nothing else we move the value to dptr */
11855 if (AOP_TYPE(result) != AOP_STR) {
11856 /* if this is remateriazable */
11857 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11858 // WARNING: anythig until "else" is untested!
11859 if (AOP_TYPE(result) == AOP_IMMD) {
11860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11861 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11862 // load FSR0 from immediate
11863 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11867 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11869 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11875 else { /* we need to get it byte by byte */
11876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11877 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11879 // set up FSR0 with address of result
11880 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11883 /* hack hack! see if this the FSR. If so don't load W */
11884 if(AOP_TYPE(right) != AOP_ACC) {
11886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11888 if(AOP_TYPE(right) == AOP_LIT)
11891 // note: pic16_popGet handles sign extension
11892 for(i=0;i<size;i++) {
11893 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11895 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11897 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11902 for(i=0;i<size;i++) {
11904 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11905 pic16_popCopyReg(&pic16_pc_postinc0)));
11907 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11908 pic16_popCopyReg(&pic16_pc_indf0)));
11914 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11915 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11917 } // if (AOP_TYPE(result) != AOP_IMMD)
11919 } // if (AOP_TYPE(result) != AOP_STR)
11920 /* so dptr know contains the address */
11923 /* if bit then unpack */
11924 if (IS_BITFIELD(retype))
11925 genPackBits(retype,result,right,"dptr",GPOINTER);
11927 size = AOP_SIZE(right);
11930 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11932 // set up FSR0 with address of result
11933 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11937 if (AOP_TYPE(right) == AOP_LIT) {
11938 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11940 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11942 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11944 } else { // no literal
11946 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11948 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11956 pic16_freeAsmop(right,NULL,ic,TRUE);
11957 pic16_freeAsmop(result,NULL,ic,TRUE);
11961 static void genGenPointerSet (operand *right,
11962 operand *result, iCode *ic)
11965 sym_link *retype = getSpec(operandType(result));
11967 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11969 pic16_aopOp(result,ic,FALSE);
11970 pic16_aopOp(right,ic,FALSE);
11971 size = AOP_SIZE(right);
11973 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11976 /* if bit then unpack */
11977 if (IS_BITFIELD(retype)) {
11978 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11979 genPackBits(retype,result,right,"dptr",GPOINTER);
11983 size = AOP_SIZE(right);
11985 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11988 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11990 /* value of right+0 is placed on stack, which will be retrieved
11991 * by the support function thus restoring the stack. The important
11992 * thing is that there is no need to manually restore stack pointer
11994 pushaop(AOP(right), 0);
11995 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11996 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11997 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11998 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12000 /* load address to write to in WREG:FSR0H:FSR0L */
12001 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12002 pic16_popCopyReg(&pic16_pc_fsr0l)));
12003 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12004 pic16_popCopyReg(&pic16_pc_prodl)));
12005 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12007 pic16_callGenericPointerRW(1, size);
12010 pic16_freeAsmop(right,NULL,ic,TRUE);
12011 pic16_freeAsmop(result,NULL,ic,TRUE);
12014 /*-----------------------------------------------------------------*/
12015 /* genPointerSet - stores the value into a pointer location */
12016 /*-----------------------------------------------------------------*/
12017 static void genPointerSet (iCode *ic)
12019 operand *right, *result ;
12020 sym_link *type, *etype;
12025 right = IC_RIGHT(ic);
12026 result = IC_RESULT(ic) ;
12028 /* depending on the type of pointer we need to
12029 move it to the correct pointer register */
12030 type = operandType(result);
12031 etype = getSpec(type);
12033 /* if left is of type of pointer then it is simple */
12034 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12035 p_type = DCL_TYPE(type);
12038 /* we have to go by the storage class */
12039 p_type = PTR_TYPE(SPEC_OCLS(etype));
12041 /* if (SPEC_OCLS(etype)->codesp ) { */
12042 /* p_type = CPOINTER ; */
12045 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12046 /* p_type = FPOINTER ; */
12048 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12049 /* p_type = PPOINTER ; */
12051 /* if (SPEC_OCLS(etype) == idata ) */
12052 /* p_type = IPOINTER ; */
12054 /* p_type = POINTER ; */
12057 /* now that we have the pointer type we assign
12058 the pointer values */
12063 genNearPointerSet (right,result,ic);
12067 genPagedPointerSet (right,result,ic);
12071 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12073 genFarPointerSet (right,result,ic);
12078 genGenPointerSet (right,result,ic);
12082 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12083 "genPointerSet: illegal pointer type");
12087 /*-----------------------------------------------------------------*/
12088 /* genIfx - generate code for Ifx statement */
12089 /*-----------------------------------------------------------------*/
12090 static void genIfx (iCode *ic, iCode *popIc)
12092 operand *cond = IC_COND(ic);
12097 pic16_aopOp(cond,ic,FALSE);
12099 /* get the value into acc */
12100 if (AOP_TYPE(cond) != AOP_CRY)
12101 pic16_toBoolean(cond);
12104 /* the result is now in the accumulator */
12105 pic16_freeAsmop(cond,NULL,ic,TRUE);
12107 /* if there was something to be popped then do it */
12111 /* if the condition is a bit variable */
12112 if (isbit && IS_ITEMP(cond) &&
12114 genIfxJump(ic,"c");
12115 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12117 if (isbit && !IS_ITEMP(cond))
12118 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12120 genIfxJump(ic,"a");
12125 /*-----------------------------------------------------------------*/
12126 /* genAddrOf - generates code for address of */
12127 /*-----------------------------------------------------------------*/
12128 static void genAddrOf (iCode *ic)
12130 operand *result, *left;
12132 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12133 pCodeOp *pcop0, *pcop1, *pcop2;
12137 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12139 sym = OP_SYMBOL( IC_LEFT(ic) );
12142 /* get address of symbol on stack */
12143 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12145 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12146 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12149 // operands on stack are accessible via "FSR2 + index" with index
12150 // starting at 2 for arguments and growing from 0 downwards for
12151 // local variables (index == 0 is not assigned so we add one here)
12153 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12156 assert (soffs < 0);
12160 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12161 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12162 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12163 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12164 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12165 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12166 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12172 // if(pic16_debug_verbose) {
12173 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12174 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12177 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12178 size = AOP_SIZE(IC_RESULT(ic));
12180 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12181 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12182 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12185 pic16_emitpcode(POC_MOVLW, pcop0);
12186 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12187 pic16_emitpcode(POC_MOVLW, pcop1);
12188 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12189 pic16_emitpcode(POC_MOVLW, pcop2);
12190 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12193 pic16_emitpcode(POC_MOVLW, pcop0);
12194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12195 pic16_emitpcode(POC_MOVLW, pcop1);
12196 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12198 pic16_emitpcode(POC_MOVLW, pcop0);
12199 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12202 pic16_freeAsmop(left, NULL, ic, FALSE);
12204 pic16_freeAsmop(result,NULL,ic,TRUE);
12209 /*-----------------------------------------------------------------*/
12210 /* genFarFarAssign - assignment when both are in far space */
12211 /*-----------------------------------------------------------------*/
12212 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12214 int size = AOP_SIZE(right);
12217 /* first push the right side on to the stack */
12219 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12221 pic16_emitcode ("push","acc");
12224 pic16_freeAsmop(right,NULL,ic,FALSE);
12225 /* now assign DPTR to result */
12226 pic16_aopOp(result,ic,FALSE);
12227 size = AOP_SIZE(result);
12229 pic16_emitcode ("pop","acc");
12230 pic16_aopPut(AOP(result),"a",--offset);
12232 pic16_freeAsmop(result,NULL,ic,FALSE);
12237 /*-----------------------------------------------------------------*/
12238 /* genAssign - generate code for assignment */
12239 /*-----------------------------------------------------------------*/
12240 static void genAssign (iCode *ic)
12242 operand *result, *right;
12243 sym_link *restype, *rtype;
12244 int size, offset,know_W;
12245 unsigned long lit = 0L;
12247 result = IC_RESULT(ic);
12248 right = IC_RIGHT(ic) ;
12252 /* if they are the same */
12253 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12256 /* reversed order operands are aopOp'ed so that result operand
12257 * is effective in case right is a stack symbol. This maneauver
12258 * allows to use the _G.resDirect flag later */
12259 pic16_aopOp(result,ic,TRUE);
12260 pic16_aopOp(right,ic,FALSE);
12262 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12264 /* if they are the same registers */
12265 if (pic16_sameRegs(AOP(right),AOP(result)))
12268 /* if the result is a bit */
12269 if (AOP_TYPE(result) == AOP_CRY) {
12270 /* if the right size is a literal then
12271 we know what the value is */
12272 if (AOP_TYPE(right) == AOP_LIT) {
12274 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12275 pic16_popGet(AOP(result),0));
12277 if (((int) operandLitValue(right)))
12278 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12279 AOP(result)->aopu.aop_dir,
12280 AOP(result)->aopu.aop_dir);
12282 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12283 AOP(result)->aopu.aop_dir,
12284 AOP(result)->aopu.aop_dir);
12289 /* the right is also a bit variable */
12290 if (AOP_TYPE(right) == AOP_CRY) {
12291 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12292 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12293 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12298 /* we need to or */
12299 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12300 pic16_toBoolean(right);
12302 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12303 //pic16_aopPut(AOP(result),"a",0);
12307 /* bit variables done */
12309 size = AOP_SIZE(result);
12312 /* bit variables done */
12314 size = AOP_SIZE(result);
12315 restype = operandType(result);
12316 rtype = operandType(right);
12319 if(AOP_TYPE(right) == AOP_LIT) {
12320 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12322 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12324 /* patch tag for literals that are cast to pointers */
12325 if (IS_CODEPTR(restype)) {
12326 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12327 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12329 if (IS_GENPTR(restype))
12331 if (IS_CODEPTR(rtype)) {
12332 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12333 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12334 } else if (PIC_IS_DATA_PTR(rtype)) {
12335 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12336 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12337 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12338 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12339 } else if (IS_PTR(rtype)) {
12340 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12341 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12347 unsigned long lit_int;
12352 if(IS_FIXED16X16(operandType(right))) {
12353 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12355 /* take care if literal is a float */
12356 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12357 lit = info.lit_int;
12362 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12363 // sizeof(unsigned long int), sizeof(float));
12366 if (AOP_TYPE(right) == AOP_REG) {
12367 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12369 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12374 /* when do we have to read the program memory?
12375 * - if right itself is a symbol in code space
12376 * (we don't care what it points to if it's a pointer)
12377 * - AND right is not a function (we would want its address)
12379 if(AOP_TYPE(right) != AOP_LIT
12380 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12381 && !IS_FUNC(OP_SYM_TYPE(right))
12382 && !IS_ITEMP(right)) {
12384 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12385 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12387 // set up table pointer
12388 if(is_LitOp(right)) {
12389 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12390 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12391 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12392 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12393 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12394 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12395 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12397 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12398 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12399 pic16_popCopyReg(&pic16_pc_tblptrl)));
12400 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12401 pic16_popCopyReg(&pic16_pc_tblptrh)));
12402 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12403 pic16_popCopyReg(&pic16_pc_tblptru)));
12406 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12407 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12409 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12410 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12411 pic16_popGet(AOP(result),offset)));
12415 /* FIXME: for pointers we need to extend differently (according
12416 * to pointer type DATA/CODE/EEPROM/... :*/
12417 size = getSize(OP_SYM_TYPE(right));
12418 if(AOP_SIZE(result) > size) {
12419 size = AOP_SIZE(result) - size;
12421 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12429 /* VR - What is this?! */
12430 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12433 if(aopIdx(AOP(result),0) == 4) {
12434 /* this is a workaround to save value of right into wreg too,
12435 * value of wreg is going to be used later */
12436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12438 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12442 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12448 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12449 if(AOP_TYPE(right) == AOP_LIT) {
12451 if(know_W != (lit&0xff))
12452 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12454 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12456 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12460 } else if (AOP_TYPE(right) == AOP_CRY) {
12461 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12463 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12464 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12465 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12467 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12468 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12469 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12471 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12473 if(!_G.resDirect) /* use this aopForSym feature */
12474 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12481 pic16_freeAsmop (right,NULL,ic,FALSE);
12482 pic16_freeAsmop (result,NULL,ic,TRUE);
12485 /*-----------------------------------------------------------------*/
12486 /* genJumpTab - generates code for jump table */
12487 /*-----------------------------------------------------------------*/
12488 static void genJumpTab (iCode *ic)
12493 pCodeOp *jt_offs_hi;
12498 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12499 /* get the condition into accumulator */
12500 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12502 /* multiply by three */
12503 pic16_emitcode("add","a,acc");
12504 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12506 jtab = newiTempLabel(NULL);
12507 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12508 pic16_emitcode("jmp","@a+dptr");
12509 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12512 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12513 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12515 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12516 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12517 pic16_emitpLabel(jtab->key);
12521 jt_offs = pic16_popGetTempReg(0);
12522 jt_offs_hi = pic16_popGetTempReg(1);
12523 jt_label = pic16_popGetLabel (jtab->key);
12524 //fprintf (stderr, "Creating jump table...\n");
12526 // calculate offset into jump table (idx * sizeof (GOTO))
12527 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12528 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12529 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12530 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12531 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12532 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12533 pic16_emitpcode(POC_MOVWF , jt_offs);
12535 // prepare PCLATx (set to first entry in jump table)
12536 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12537 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12538 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12539 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12540 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12542 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12543 pic16_emitpcode(POC_ADDWF , jt_offs);
12544 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12545 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12547 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12549 // release temporaries and prepare jump into table (new PCL --> WREG)
12550 pic16_emitpcode(POC_MOVFW , jt_offs);
12551 pic16_popReleaseTempReg (jt_offs_hi, 1);
12552 pic16_popReleaseTempReg (jt_offs, 0);
12554 // jump into the table
12555 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12557 pic16_emitpLabelFORCE(jtab->key);
12560 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12561 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12563 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12564 /* now generate the jump labels */
12565 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12566 jtab = setNextItem(IC_JTLABELS(ic))) {
12567 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12568 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12571 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12575 /*-----------------------------------------------------------------*/
12576 /* genMixedOperation - gen code for operators between mixed types */
12577 /*-----------------------------------------------------------------*/
12579 TSD - Written for the PIC port - but this unfortunately is buggy.
12580 This routine is good in that it is able to efficiently promote
12581 types to different (larger) sizes. Unfortunately, the temporary
12582 variables that are optimized out by this routine are sometimes
12583 used in other places. So until I know how to really parse the
12584 iCode tree, I'm going to not be using this routine :(.
12586 static int genMixedOperation (iCode *ic)
12589 operand *result = IC_RESULT(ic);
12590 sym_link *ctype = operandType(IC_LEFT(ic));
12591 operand *right = IC_RIGHT(ic);
12597 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12599 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12605 nextright = IC_RIGHT(nextic);
12606 nextleft = IC_LEFT(nextic);
12607 nextresult = IC_RESULT(nextic);
12609 pic16_aopOp(right,ic,FALSE);
12610 pic16_aopOp(result,ic,FALSE);
12611 pic16_aopOp(nextright, nextic, FALSE);
12612 pic16_aopOp(nextleft, nextic, FALSE);
12613 pic16_aopOp(nextresult, nextic, FALSE);
12615 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12617 operand *t = right;
12621 pic16_emitcode(";remove right +","");
12623 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12625 operand *t = right;
12629 pic16_emitcode(";remove left +","");
12633 big = AOP_SIZE(nextleft);
12634 small = AOP_SIZE(nextright);
12636 switch(nextic->op) {
12639 pic16_emitcode(";optimize a +","");
12640 /* if unsigned or not an integral type */
12641 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12642 pic16_emitcode(";add a bit to something","");
12645 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12647 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12648 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12649 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12651 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12659 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12660 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12661 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12664 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12666 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12667 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12668 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12669 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12670 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12673 pic16_emitcode("rlf","known_zero,w");
12680 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12681 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12682 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12684 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12694 pic16_freeAsmop(right,NULL,ic,TRUE);
12695 pic16_freeAsmop(result,NULL,ic,TRUE);
12696 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12697 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12699 nextic->generated = 1;
12706 /*-----------------------------------------------------------------*/
12707 /* genCast - gen code for casting */
12708 /*-----------------------------------------------------------------*/
12709 static void genCast (iCode *ic)
12711 operand *result = IC_RESULT(ic);
12712 sym_link *ctype = operandType(IC_LEFT(ic));
12713 sym_link *rtype = operandType(IC_RIGHT(ic));
12714 sym_link *restype = operandType(IC_RESULT(ic));
12715 operand *right = IC_RIGHT(ic);
12721 /* if they are equivalent then do nothing */
12722 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12725 pic16_aopOp(result,ic,FALSE);
12726 pic16_aopOp(right,ic,FALSE) ;
12728 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12731 /* if the result is a bit */
12732 if (AOP_TYPE(result) == AOP_CRY) {
12734 /* if the right size is a literal then
12735 * we know what the value is */
12736 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12738 if (AOP_TYPE(right) == AOP_LIT) {
12739 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12740 pic16_popGet(AOP(result),0));
12742 if (((int) operandLitValue(right)))
12743 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12744 AOP(result)->aopu.aop_dir,
12745 AOP(result)->aopu.aop_dir);
12747 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12748 AOP(result)->aopu.aop_dir,
12749 AOP(result)->aopu.aop_dir);
12753 /* the right is also a bit variable */
12754 if (AOP_TYPE(right) == AOP_CRY) {
12756 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12758 pic16_emitcode("clrc","");
12759 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12760 AOP(right)->aopu.aop_dir,
12761 AOP(right)->aopu.aop_dir);
12762 pic16_aopPut(AOP(result),"c",0);
12766 /* we need to or */
12767 if (AOP_TYPE(right) == AOP_REG) {
12768 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12769 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12770 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12772 pic16_toBoolean(right);
12773 pic16_aopPut(AOP(result),"a",0);
12777 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12780 size = AOP_SIZE(result);
12782 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12784 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12785 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12786 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12789 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12794 if(IS_BITFIELD(getSpec(restype))
12795 && IS_BITFIELD(getSpec(rtype))) {
12796 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12799 /* port from pic14 to cope with generic pointers */
12800 if (PIC_IS_TAGGED(restype))
12802 operand *result = IC_RESULT(ic);
12803 //operand *left = IC_LEFT(ic);
12804 operand *right = IC_RIGHT(ic);
12807 /* copy common part */
12808 int max, size = AOP_SIZE(result);
12809 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12810 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12815 pic16_mov2w (AOP(right), size);
12816 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12819 /* upcast into generic pointer type? */
12820 if (IS_GENPTR(restype)
12821 && !PIC_IS_TAGGED(rtype)
12822 && (AOP_SIZE(result) > max))
12824 /* determine appropriate tag for right */
12825 if (PIC_IS_DATA_PTR(rtype))
12826 tag = GPTR_TAG_DATA;
12827 else if (IS_CODEPTR(rtype))
12828 tag = GPTR_TAG_CODE;
12829 else if (PIC_IS_DATA_PTR(ctype)) {
12830 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12831 tag = GPTR_TAG_DATA;
12832 } else if (IS_CODEPTR(ctype)) {
12833 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12834 tag = GPTR_TAG_CODE;
12835 } else if (IS_PTR(rtype)) {
12836 PERFORM_ONCE(weirdcast,
12837 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12839 tag = GPTR_TAG_DATA;
12841 PERFORM_ONCE(weirdcast,
12842 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12844 tag = GPTR_TAG_DATA;
12847 assert (AOP_SIZE(result) == 3);
12848 /* zero-extend address... */
12849 for (size = max; size < AOP_SIZE(result)-1; size++)
12850 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12851 /* ...and add tag */
12852 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12853 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12854 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12855 for (size = max; size < AOP_SIZE(result)-1; size++)
12856 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12857 /* add __code tag */
12858 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12859 } else if (AOP_SIZE(result) > max) {
12860 /* extend non-pointers */
12861 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12862 pic16_addSign(result, max, 0);
12867 /* if they are the same size : or less */
12868 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12870 /* if they are in the same place */
12871 if (pic16_sameRegs(AOP(right),AOP(result)))
12874 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12876 if (IS_PTR_CONST(rtype))
12878 if (IS_CODEPTR(rtype))
12880 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12883 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12885 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12887 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12890 if(AOP_TYPE(right) == AOP_IMMD) {
12891 pCodeOp *pcop0, *pcop1, *pcop2;
12892 symbol *sym = OP_SYMBOL( right );
12894 size = AOP_SIZE(result);
12896 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12898 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12900 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12903 pic16_emitpcode(POC_MOVLW, pcop0);
12904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12905 pic16_emitpcode(POC_MOVLW, pcop1);
12906 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12907 pic16_emitpcode(POC_MOVLW, pcop2);
12908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12911 pic16_emitpcode(POC_MOVLW, pcop0);
12912 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12913 pic16_emitpcode(POC_MOVLW, pcop1);
12914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12916 pic16_emitpcode(POC_MOVLW, pcop0);
12917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12921 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12922 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12924 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12925 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12926 if(AOP_SIZE(result) <2)
12927 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12929 /* if they in different places then copy */
12930 size = AOP_SIZE(result);
12933 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12934 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12941 /* if the result is of type pointer */
12942 if (IS_PTR(ctype)) {
12944 sym_link *type = operandType(right);
12945 sym_link *etype = getSpec(type);
12947 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12949 /* pointer to generic pointer */
12950 if (IS_GENPTR(ctype)) {
12954 p_type = DCL_TYPE(type);
12956 /* we have to go by the storage class */
12957 p_type = PTR_TYPE(SPEC_OCLS(etype));
12959 /* if (SPEC_OCLS(etype)->codesp ) */
12960 /* p_type = CPOINTER ; */
12962 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12963 /* p_type = FPOINTER ; */
12965 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12966 /* p_type = PPOINTER; */
12968 /* if (SPEC_OCLS(etype) == idata ) */
12969 /* p_type = IPOINTER ; */
12971 /* p_type = POINTER ; */
12974 /* the first two bytes are known */
12975 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12976 size = GPTRSIZE - 1;
12979 if(offset < AOP_SIZE(right)) {
12980 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12981 pic16_mov2f(AOP(result), AOP(right), offset);
12983 if ((AOP_TYPE(right) == AOP_PCODE) &&
12984 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12985 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12986 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12989 pic16_aopPut(AOP(result),
12990 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12995 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12998 /* the last byte depending on type */
13003 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13007 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13011 pic16_emitcode(";BUG!? ","%d",__LINE__);
13016 if (GPTRSIZE > AOP_SIZE(right)) {
13017 // assume __data pointer... THIS MIGHT BE WRONG!
13018 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13020 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13025 /* this should never happen */
13026 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13027 "got unknown pointer type");
13030 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13036 /* just copy the pointers */
13037 size = AOP_SIZE(result);
13040 pic16_aopPut(AOP(result),
13041 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13050 /* so we now know that the size of destination is greater
13051 than the size of the source.
13052 Now, if the next iCode is an operator then we might be
13053 able to optimize the operation without performing a cast.
13055 if(genMixedOperation(ic))
13058 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13060 /* we move to result for the size of source */
13061 size = AOP_SIZE(right);
13066 pic16_mov2f(AOP(result), AOP(right), offset);
13070 /* now depending on the sign of the destination */
13071 size = AOP_SIZE(result) - AOP_SIZE(right);
13072 /* if unsigned or not an integral type */
13073 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13075 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13077 /* we need to extend the sign :( */
13080 /* Save one instruction of casting char to int */
13081 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13082 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13083 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13085 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13088 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13090 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13092 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13095 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13100 pic16_freeAsmop(right,NULL,ic,TRUE);
13101 pic16_freeAsmop(result,NULL,ic,TRUE);
13105 /*-----------------------------------------------------------------*/
13106 /* genDjnz - generate decrement & jump if not zero instrucion */
13107 /*-----------------------------------------------------------------*/
13108 static int genDjnz (iCode *ic, iCode *ifx)
13110 symbol *lbl, *lbl1;
13111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13116 /* if the if condition has a false label
13117 then we cannot save */
13121 /* if the minus is not of the form
13123 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13124 !IS_OP_LITERAL(IC_RIGHT(ic)))
13127 if (operandLitValue(IC_RIGHT(ic)) != 1)
13130 /* if the size of this greater than one then no
13132 if (getSize(operandType(IC_RESULT(ic))) > 1)
13135 /* otherwise we can save BIG */
13136 lbl = newiTempLabel(NULL);
13137 lbl1= newiTempLabel(NULL);
13139 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13141 if (IS_AOP_PREG(IC_RESULT(ic))) {
13142 pic16_emitcode("dec","%s",
13143 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13144 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13145 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13149 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13150 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13152 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13153 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13157 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13158 ifx->generated = 1;
13162 /*-----------------------------------------------------------------*/
13163 /* genReceive - generate code for a receive iCode */
13164 /*-----------------------------------------------------------------*/
13165 static void genReceive (iCode *ic)
13171 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13172 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13174 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13176 if (isOperandInFarSpace(IC_RESULT(ic))
13177 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13178 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13180 int size = getSize(operandType(IC_RESULT(ic)));
13181 int offset = pic16_fReturnSizePic - size;
13185 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13186 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13190 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13192 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13193 size = AOP_SIZE(IC_RESULT(ic));
13196 pic16_emitcode ("pop","acc");
13197 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13200 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13202 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13205 /* set pseudo stack pointer to where it should be - dw*/
13206 GpsuedoStkPtr = ic->parmBytes;
13208 /* setting GpsuedoStkPtr has side effects here: */
13209 assignResultValue(IC_RESULT(ic), 0);
13212 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13215 /*-----------------------------------------------------------------*/
13216 /* genDummyRead - generate code for dummy read of volatiles */
13217 /*-----------------------------------------------------------------*/
13219 genDummyRead (iCode * ic)
13225 if (op && IS_SYMOP(op)) {
13226 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13227 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13230 pic16_aopOp (op, ic, FALSE);
13231 for (i=0; i < AOP_SIZE(op); i++) {
13232 // may need to protect this from the peepholer -- this is not nice but works...
13233 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13234 pic16_mov2w (AOP(op),i);
13235 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13237 pic16_freeAsmop (op, NULL, ic, TRUE);
13239 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13243 /*-----------------------------------------------------------------*/
13244 /* genpic16Code - generate code for pic16 based controllers */
13245 /*-----------------------------------------------------------------*/
13247 * At this point, ralloc.c has gone through the iCode and attempted
13248 * to optimize in a way suitable for a PIC. Now we've got to generate
13249 * PIC instructions that correspond to the iCode.
13251 * Once the instructions are generated, we'll pass through both the
13252 * peep hole optimizer and the pCode optimizer.
13253 *-----------------------------------------------------------------*/
13255 void genpic16Code (iCode *lic)
13260 lineHead = lineCurr = NULL;
13262 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13263 pic16_addpBlock(pb);
13266 /* if debug information required */
13267 if (options.debug && currFunc) {
13269 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13274 for (ic = lic ; ic ; ic = ic->next ) {
13276 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13277 if ( cln != ic->lineno ) {
13278 if ( options.debug ) {
13279 debugFile->writeCLine (ic);
13282 if(!options.noCcodeInAsm) {
13283 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13284 printCLine(ic->filename, ic->lineno)));
13290 if(options.iCodeInAsm) {
13293 /* insert here code to print iCode as comment */
13294 l = Safe_strdup(printILine(ic));
13295 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13298 /* if the result is marked as
13299 * spilt and rematerializable or code for
13300 * this has already been generated then
13302 if (resultRemat(ic) || ic->generated )
13305 /* depending on the operation */
13324 /* IPOP happens only when trying to restore a
13325 * spilt live range, if there is an ifx statement
13326 * following this pop then the if statement might
13327 * be using some of the registers being popped which
13328 * would destroy the contents of the register so
13329 * we need to check for this condition and handle it */
13331 && ic->next->op == IFX
13332 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13333 genIfx (ic->next,ic);
13351 genEndFunction (ic);
13367 pic16_genPlus (ic) ;
13371 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13372 pic16_genMinus (ic);
13388 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13392 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13398 /* note these two are xlated by algebraic equivalence
13399 * during parsing SDCC.y */
13400 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13401 "got '>=' or '<=' shouldn't have come here");
13405 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13417 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13421 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13425 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13449 genRightShift (ic);
13452 case GET_VALUE_AT_ADDRESS:
13457 if (POINTER_SET(ic))
13484 addSet(&_G.sendSet,ic);
13487 case DUMMY_READ_VOLATILE:
13497 /* now we are ready to call the
13498 peep hole optimizer */
13499 if (!options.nopeep)
13500 peepHole (&lineHead);
13502 /* now do the actual printing */
13503 printLine (lineHead, codeOutFile);
13506 DFPRINTF((stderr,"printing pBlock\n\n"));
13507 pic16_printpBlock(stdout,pb);