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)
3401 sym_link *ftype, *fntype;
3403 symbol *retlbl = newiTempLabel(NULL);
3404 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3408 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3409 fntype = operandType( IC_LEFT(ic) )->next;
3411 /* if send set is not empty the assign */
3414 int psuedoStkPtr=-1;
3416 /* reverse sendSet if function is not reentrant */
3417 if(!IFFUNC_ISREENT(fntype))
3418 _G.sendSet = reverseSet(_G.sendSet);
3422 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3425 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3426 size = AOP_SIZE(IC_LEFT(sic));
3429 /* all parameters are passed via stack, since WREG is clobbered
3430 * by the calling sequence */
3432 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3433 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3434 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3436 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3440 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3443 _G.stackRegSet = _G.sendSet;
3447 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3449 // push return address
3450 // push $ on return stack, then replace with retlbl
3452 /* Thanks to Thorsten Klose for pointing out that the following
3453 * snippet should be interrupt safe */
3454 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3455 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3457 pic16_emitpcodeNULLop(POC_PUSH);
3459 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3460 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3461 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3462 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3463 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3464 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3467 /* restore interrupt control register */
3468 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3469 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3471 /* make the call by writing the pointer into pc */
3472 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3473 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3475 // note: MOVFF to PCL not allowed
3476 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3477 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3480 /* return address is here: (X) */
3481 pic16_emitpLabelFORCE(retlbl->key);
3483 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3486 /* if we need assign a result value */
3487 if ((IS_ITEMP(IC_RESULT(ic))
3488 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3489 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3490 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3493 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3496 assignResultValue(IC_RESULT(ic), 1);
3498 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3501 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3504 // stackParms -= use_wreg;
3507 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3508 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3509 if(STACK_MODEL_LARGE) {
3511 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3516 /*-----------------------------------------------------------------*/
3517 /* resultRemat - result is rematerializable */
3518 /*-----------------------------------------------------------------*/
3519 static int resultRemat (iCode *ic)
3521 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3522 if (SKIP_IC(ic) || ic->op == IFX)
3525 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3526 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3527 if (sym->remat && !POINTER_SET(ic))
3534 #if defined(__BORLANDC__) || defined(_MSC_VER)
3535 #define STRCASECMP stricmp
3537 #define STRCASECMP strcasecmp
3541 /*-----------------------------------------------------------------*/
3542 /* inExcludeList - return 1 if the string is in exclude Reg list */
3543 /*-----------------------------------------------------------------*/
3544 static bool inExcludeList(char *s)
3546 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3550 if (options.excludeRegs[i] &&
3551 STRCASECMP(options.excludeRegs[i],"none") == 0)
3554 for ( i = 0 ; options.excludeRegs[i]; i++) {
3555 if (options.excludeRegs[i] &&
3556 STRCASECMP(s,options.excludeRegs[i]) == 0)
3563 /*-----------------------------------------------------------------*/
3564 /* genFunction - generated code for function entry */
3565 /*-----------------------------------------------------------------*/
3566 static void genFunction (iCode *ic)
3572 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3574 pic16_labelOffset += (max_key+4);
3579 ftype = operandType(IC_LEFT(ic));
3580 sym = OP_SYMBOL(IC_LEFT(ic));
3582 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3583 /* create an absolute section at the interrupt vector:
3584 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3589 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3591 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3592 sprintf(asymname, "ivec_%s", sym->name);
3594 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3596 /* when an interrupt is declared as naked, do not emit the special
3597 * wrapper segment at vector address. The user should take care for
3598 * this instead. -- VR */
3600 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3601 asym = newSymbol(asymname, 0);
3602 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3603 pic16_addpBlock( apb );
3605 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3606 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3607 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3608 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3609 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3611 /* mark the end of this tiny function */
3612 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3614 sprintf(asymname, "%s", sym->rname);
3620 abSym = Safe_calloc(1, sizeof(absSym));
3621 strcpy(abSym->name, asymname);
3623 switch( FUNC_INTNO(sym->type) ) {
3624 case 0: abSym->address = 0x000000; break;
3625 case 1: abSym->address = 0x000008; break;
3626 case 2: abSym->address = 0x000018; break;
3629 // fprintf(stderr, "no interrupt number is given\n");
3630 abSym->address = -1; break;
3633 /* relocate interrupt vectors if needed */
3634 if(abSym->address != -1)
3635 abSym->address += pic16_options.ivt_loc;
3637 addSet(&absSymSet, abSym);
3641 /* create the function header */
3642 pic16_emitcode(";","-----------------------------------------");
3643 pic16_emitcode(";"," function %s",sym->name);
3644 pic16_emitcode(";","-----------------------------------------");
3646 pic16_emitcode("","%s:",sym->rname);
3647 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3652 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3653 if(!strcmp(ab->name, sym->rname)) {
3654 pic16_pBlockConvert2Absolute(pb);
3660 if(IFFUNC_ISNAKED(ftype)) {
3661 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3665 /* if critical function then turn interrupts off */
3666 if (IFFUNC_ISCRITICAL(ftype)) {
3667 //pic16_emitcode("clr","ea");
3670 currFunc = sym; /* update the currFunc symbol */
3671 _G.fregsUsed = sym->regsUsed;
3672 _G.sregsAlloc = newBitVect(128);
3675 /* if this is an interrupt service routine then
3676 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3677 if (IFFUNC_ISISR(sym->type)) {
3678 _G.usefastretfie = 1; /* use shadow registers by default */
3680 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3681 if(!FUNC_ISSHADOWREGS(sym->type)) {
3682 /* do not save WREG,STATUS,BSR for high priority interrupts
3683 * because they are stored in the hardware shadow registers already */
3684 _G.usefastretfie = 0;
3685 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3686 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3687 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3690 /* these should really be optimized somehow, because not all
3691 * interrupt handlers modify them */
3692 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3693 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3694 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3695 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3697 // pic16_pBlockConvert2ISR(pb);
3700 /* emit code to setup stack frame if user enabled,
3701 * and function is not main() */
3703 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3704 if(strcmp(sym->name, "main")) {
3706 || !options.ommitFramePtr
3708 || IFFUNC_ARGS(sym->type)
3709 || FUNC_HASSTACKPARM(sym->etype)
3711 /* setup the stack frame */
3712 if(STACK_MODEL_LARGE)
3713 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3714 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3716 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3717 if(STACK_MODEL_LARGE)
3718 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3722 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3725 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3727 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3728 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3730 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3733 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3734 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3741 /* if callee-save to be used for this function
3742 * then save the registers being used in this function */
3743 // if (IFFUNC_CALLEESAVES(sym->type))
3744 if(strcmp(sym->name, "main")) {
3747 /* if any registers used */
3748 if (sym->regsUsed) {
3749 /* save the registers used */
3750 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3751 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3752 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3753 if (bitVectBitValue(sym->regsUsed,i)) {
3754 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3757 if(!pic16_regWithIdx(i)->wasUsed) {
3758 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3759 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3760 pic16_regWithIdx(i)->wasUsed = 1;
3764 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3768 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3769 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3772 /*-----------------------------------------------------------------*/
3773 /* genEndFunction - generates epilogue for functions */
3774 /*-----------------------------------------------------------------*/
3775 static void genEndFunction (iCode *ic)
3777 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3781 if(IFFUNC_ISNAKED(sym->type)) {
3782 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3788 /* add code for ISCRITICAL */
3789 if(IFFUNC_ISCRITICAL(sym->type)) {
3790 /* if critical function, turn on interrupts */
3792 /* TODO: add code here -- VR */
3795 // sym->regsUsed = _G.fregsUsed;
3797 /* now we need to restore the registers */
3798 /* if any registers used */
3800 /* first restore registers that might be used for stack access */
3801 if(_G.sregsAllocSet) {
3804 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3805 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3806 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3810 if (strcmp(sym->name, "main") && sym->regsUsed) {
3813 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3814 /* restore registers used */
3815 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3816 for ( i = sym->regsUsed->size; i >= 0; i--) {
3817 if (bitVectBitValue(sym->regsUsed,i)) {
3818 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3822 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3827 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3829 if (sym->stack == 1) {
3830 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3831 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3833 // we have to add more than one...
3834 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3835 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3836 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3838 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3839 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3840 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3844 if(strcmp(sym->name, "main")) {
3846 || !options.ommitFramePtr
3848 || IFFUNC_ARGS(sym->type)
3849 || FUNC_HASSTACKPARM(sym->etype)
3851 /* restore stack frame */
3852 if(STACK_MODEL_LARGE)
3853 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3854 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3860 if (IFFUNC_ISISR(sym->type)) {
3861 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3862 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3863 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3864 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3866 if(!FUNC_ISSHADOWREGS(sym->type)) {
3867 /* do not restore interrupt vector for WREG,STATUS,BSR
3868 * for high priority interrupt, see genFunction */
3869 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3870 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3871 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3873 // _G.interruptvector = 0; /* sanity check */
3876 /* if debug then send end of function */
3877 /* if (options.debug && currFunc) */
3879 debugFile->writeEndFunction (currFunc, ic, 1);
3882 if(_G.usefastretfie)
3883 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3885 pic16_emitpcodeNULLop(POC_RETFIE);
3887 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3889 _G.usefastretfie = 0;
3893 if (IFFUNC_ISCRITICAL(sym->type)) {
3894 pic16_emitcode("setb","ea");
3897 /* if debug then send end of function */
3899 debugFile->writeEndFunction (currFunc, ic, 1);
3902 /* insert code to restore stack frame, if user enabled it
3903 * and function is not main() */
3906 pic16_emitpcodeNULLop(POC_RETURN);
3908 /* Mark the end of a function */
3909 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3913 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3915 unsigned long lit=1;
3920 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3921 if(AOP_TYPE(op) == AOP_LIT) {
3922 if(!IS_FLOAT(operandType( op ))) {
3923 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3926 unsigned long lit_int;
3930 /* take care if literal is a float */
3931 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3937 pic16_movLit2f(dest, lit);
3939 if(dest->type == PO_WREG && (offset == 0)) {
3940 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3943 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3947 /*-----------------------------------------------------------------*/
3948 /* genRet - generate code for return statement */
3949 /*-----------------------------------------------------------------*/
3950 static void genRet (iCode *ic)
3956 /* if we have no return value then
3957 * just generate the "ret" */
3962 /* we have something to return then
3963 * move the return value into place */
3964 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3965 size = AOP_SIZE(IC_LEFT(ic));
3969 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3972 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3975 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3977 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3980 /* >32-bits, setup stack and FSR0 */
3982 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3983 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3985 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3987 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3992 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3993 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3995 if(STACK_MODEL_LARGE) {
3996 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3997 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3999 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4004 /* old code, left here for reference -- VR */
4008 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4010 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4011 pic16_emitpcomment("push %s",l);
4014 DEBUGpic16_emitcode(";", "%d", __LINE__);
4015 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4016 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4018 if (strcmp(fReturn[offset],l)) {
4019 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4020 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4021 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4023 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4027 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4037 if (strcmp(fReturn[pushed],"a"))
4038 pic16_emitcode("pop",fReturn[pushed]);
4040 pic16_emitcode("pop","acc");
4046 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4049 /* generate a jump to the return label
4050 * if the next is not the return statement */
4051 if (!(ic->next && ic->next->op == LABEL
4052 && IC_LABEL(ic->next) == returnLabel)) {
4054 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4055 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4059 /*-----------------------------------------------------------------*/
4060 /* genLabel - generates a label */
4061 /*-----------------------------------------------------------------*/
4062 static void genLabel (iCode *ic)
4066 /* special case never generate */
4067 if (IC_LABEL(ic) == entryLabel)
4070 pic16_emitpLabel(IC_LABEL(ic)->key);
4071 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4074 /*-----------------------------------------------------------------*/
4075 /* genGoto - generates a goto */
4076 /*-----------------------------------------------------------------*/
4078 static void genGoto (iCode *ic)
4081 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4082 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4086 /*-----------------------------------------------------------------*/
4087 /* genMultbits :- multiplication of bits */
4088 /*-----------------------------------------------------------------*/
4089 static void genMultbits (operand *left,
4095 if(!pic16_sameRegs(AOP(result),AOP(right)))
4096 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4098 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4099 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4100 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4105 /*-----------------------------------------------------------------*/
4106 /* genMultOneByte : 8 bit multiplication & division */
4107 /*-----------------------------------------------------------------*/
4108 static void genMultOneByte (operand *left,
4114 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4115 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4117 /* (if two literals, the value is computed before) */
4118 /* if one literal, literal on the right */
4119 if (AOP_TYPE(left) == AOP_LIT){
4125 /* size is already checked in genMult == 1 */
4126 // size = AOP_SIZE(result);
4128 if (AOP_TYPE(right) == AOP_LIT){
4129 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4130 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4131 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4132 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4134 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4135 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4136 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4137 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4140 pic16_genMult8X8_8 (left, right,result);
4143 /*-----------------------------------------------------------------*/
4144 /* genMultOneWord : 16 bit multiplication */
4145 /*-----------------------------------------------------------------*/
4146 static void genMultOneWord (operand *left,
4151 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4152 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4154 /* (if two literals, the value is computed before)
4155 * if one literal, literal on the right */
4156 if (AOP_TYPE(left) == AOP_LIT){
4162 /* size is checked already == 2 */
4163 // size = AOP_SIZE(result);
4165 if (AOP_TYPE(right) == AOP_LIT) {
4166 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4167 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4168 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4169 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4171 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4172 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4173 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4174 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4177 pic16_genMult16X16_16(left, right,result);
4180 /*-----------------------------------------------------------------*/
4181 /* genMultOneLong : 32 bit multiplication */
4182 /*-----------------------------------------------------------------*/
4183 static void genMultOneLong (operand *left,
4188 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4189 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4191 /* (if two literals, the value is computed before)
4192 * if one literal, literal on the right */
4193 if (AOP_TYPE(left) == AOP_LIT){
4199 /* size is checked already == 4 */
4200 // size = AOP_SIZE(result);
4202 if (AOP_TYPE(right) == AOP_LIT) {
4203 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4204 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4206 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4208 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4209 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4211 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214 pic16_genMult32X32_32(left, right,result);
4219 /*-----------------------------------------------------------------*/
4220 /* genMult - generates code for multiplication */
4221 /*-----------------------------------------------------------------*/
4222 static void genMult (iCode *ic)
4224 operand *left = IC_LEFT(ic);
4225 operand *right = IC_RIGHT(ic);
4226 operand *result= IC_RESULT(ic);
4229 /* assign the amsops */
4230 pic16_aopOp (left,ic,FALSE);
4231 pic16_aopOp (right,ic,FALSE);
4232 pic16_aopOp (result,ic,TRUE);
4234 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4236 /* special cases first *
4238 if (AOP_TYPE(left) == AOP_CRY
4239 && AOP_TYPE(right)== AOP_CRY) {
4240 genMultbits(left,right,result);
4244 /* if both are of size == 1 */
4245 if(AOP_SIZE(left) == 1
4246 && AOP_SIZE(right) == 1) {
4247 genMultOneByte(left,right,result);
4251 /* if both are of size == 2 */
4252 if(AOP_SIZE(left) == 2
4253 && AOP_SIZE(right) == 2) {
4254 genMultOneWord(left, right, result);
4258 /* if both are of size == 4 */
4259 if(AOP_SIZE(left) == 4
4260 && AOP_SIZE(right) == 4) {
4261 genMultOneLong(left, right, result);
4265 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4268 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4269 /* should have been converted to function call */
4273 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4274 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4275 pic16_freeAsmop(result,NULL,ic,TRUE);
4278 /*-----------------------------------------------------------------*/
4279 /* genDivbits :- division of bits */
4280 /*-----------------------------------------------------------------*/
4281 static void genDivbits (operand *left,
4288 /* the result must be bit */
4289 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4290 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4294 pic16_emitcode("div","ab");
4295 pic16_emitcode("rrc","a");
4296 pic16_aopPut(AOP(result),"c",0);
4299 /*-----------------------------------------------------------------*/
4300 /* genDivOneByte : 8 bit division */
4301 /*-----------------------------------------------------------------*/
4302 static void genDivOneByte (operand *left,
4306 sym_link *opetype = operandType(result);
4311 /* result = divident / divisor
4312 * - divident may be a register or a literal,
4313 * - divisor may be a register or a literal,
4314 * so there are 3 cases (literal / literal is optimized
4315 * by the front-end) to handle.
4316 * In addition we must handle signed and unsigned, which
4317 * result in 6 final different cases -- VR */
4321 size = AOP_SIZE(result) - 1;
4323 /* signed or unsigned */
4324 if (SPEC_USIGN(opetype)) {
4325 pCodeOp *pct1, /* count */
4328 symbol *label1, *label2, *label3;;
4331 /* unsigned is easy */
4333 pct1 = pic16_popGetTempReg(1);
4334 pct2 = pic16_popGetTempReg(1);
4335 pct3 = pic16_popGetTempReg(1);
4337 label1 = newiTempLabel(NULL);
4338 label2 = newiTempLabel(NULL);
4339 label3 = newiTempLabel(NULL);
4341 /* the following algorithm is extracted from divuint.c */
4343 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4344 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4346 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4348 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4350 pic16_emitpLabel(label1->key);
4353 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4357 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4361 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4363 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4364 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4366 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4367 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4368 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4370 pic16_emitpLabel( label3->key );
4371 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4372 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4376 pic16_emitpLabel(label2->key);
4377 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4378 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4379 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4381 /* result is in wreg */
4382 if(AOP_TYPE(result) != AOP_ACC)
4383 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4385 pic16_popReleaseTempReg( pct3, 1);
4386 pic16_popReleaseTempReg( pct2, 1);
4387 pic16_popReleaseTempReg( pct1, 1);
4392 /* signed is a little bit more difficult */
4394 /* save the signs of the operands */
4395 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4397 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4398 pic16_emitcode("push","acc"); /* save it on the stack */
4400 /* now sign adjust for both left & right */
4401 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4403 lbl = newiTempLabel(NULL);
4404 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4405 pic16_emitcode("cpl","a");
4406 pic16_emitcode("inc","a");
4407 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4408 pic16_emitcode("mov","b,a");
4410 /* sign adjust left side */
4411 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4414 lbl = newiTempLabel(NULL);
4415 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4416 pic16_emitcode("cpl","a");
4417 pic16_emitcode("inc","a");
4418 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4420 /* now the division */
4421 pic16_emitcode("div","ab");
4422 /* we are interested in the lower order
4424 pic16_emitcode("mov","b,a");
4425 lbl = newiTempLabel(NULL);
4426 pic16_emitcode("pop","acc");
4427 /* if there was an over flow we don't
4428 adjust the sign of the result */
4429 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4430 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4432 pic16_emitcode("clr","a");
4433 pic16_emitcode("subb","a,b");
4434 pic16_emitcode("mov","b,a");
4435 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4437 /* now we are done */
4438 pic16_aopPut(AOP(result),"b",0);
4440 pic16_emitcode("mov","c,b.7");
4441 pic16_emitcode("subb","a,acc");
4444 pic16_aopPut(AOP(result),"a",offset++);
4448 /*-----------------------------------------------------------------*/
4449 /* genDiv - generates code for division */
4450 /*-----------------------------------------------------------------*/
4451 static void genDiv (iCode *ic)
4453 operand *left = IC_LEFT(ic);
4454 operand *right = IC_RIGHT(ic);
4455 operand *result= IC_RESULT(ic);
4458 /* Division is a very lengthy algorithm, so it is better
4459 * to call support routines than inlining algorithm.
4460 * Division functions written here just in case someone
4461 * wants to inline and not use the support libraries -- VR */
4465 /* assign the amsops */
4466 pic16_aopOp (left,ic,FALSE);
4467 pic16_aopOp (right,ic,FALSE);
4468 pic16_aopOp (result,ic,TRUE);
4470 /* special cases first */
4472 if (AOP_TYPE(left) == AOP_CRY &&
4473 AOP_TYPE(right)== AOP_CRY) {
4474 genDivbits(left,right,result);
4478 /* if both are of size == 1 */
4479 if (AOP_SIZE(left) == 1 &&
4480 AOP_SIZE(right) == 1 ) {
4481 genDivOneByte(left,right,result);
4485 /* should have been converted to function call */
4488 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4490 pic16_freeAsmop(result,NULL,ic,TRUE);
4493 /*-----------------------------------------------------------------*/
4494 /* genModbits :- modulus of bits */
4495 /*-----------------------------------------------------------------*/
4496 static void genModbits (operand *left,
4504 werror(W_POSSBUG2, __FILE__, __LINE__);
4505 /* the result must be bit */
4506 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4507 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4511 pic16_emitcode("div","ab");
4512 pic16_emitcode("mov","a,b");
4513 pic16_emitcode("rrc","a");
4514 pic16_aopPut(AOP(result),"c",0);
4517 /*-----------------------------------------------------------------*/
4518 /* genModOneByte : 8 bit modulus */
4519 /*-----------------------------------------------------------------*/
4520 static void genModOneByte (operand *left,
4524 sym_link *opetype = operandType(result);
4529 werror(W_POSSBUG2, __FILE__, __LINE__);
4531 /* signed or unsigned */
4532 if (SPEC_USIGN(opetype)) {
4533 /* unsigned is easy */
4534 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4535 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4537 pic16_emitcode("div","ab");
4538 pic16_aopPut(AOP(result),"b",0);
4542 /* signed is a little bit more difficult */
4544 /* save the signs of the operands */
4545 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4548 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4549 pic16_emitcode("push","acc"); /* save it on the stack */
4551 /* now sign adjust for both left & right */
4552 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4555 lbl = newiTempLabel(NULL);
4556 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4557 pic16_emitcode("cpl","a");
4558 pic16_emitcode("inc","a");
4559 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4560 pic16_emitcode("mov","b,a");
4562 /* sign adjust left side */
4563 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4566 lbl = newiTempLabel(NULL);
4567 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4568 pic16_emitcode("cpl","a");
4569 pic16_emitcode("inc","a");
4570 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4572 /* now the multiplication */
4573 pic16_emitcode("div","ab");
4574 /* we are interested in the lower order
4576 lbl = newiTempLabel(NULL);
4577 pic16_emitcode("pop","acc");
4578 /* if there was an over flow we don't
4579 adjust the sign of the result */
4580 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4581 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4583 pic16_emitcode("clr","a");
4584 pic16_emitcode("subb","a,b");
4585 pic16_emitcode("mov","b,a");
4586 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4588 /* now we are done */
4589 pic16_aopPut(AOP(result),"b",0);
4593 /*-----------------------------------------------------------------*/
4594 /* genMod - generates code for division */
4595 /*-----------------------------------------------------------------*/
4596 static void genMod (iCode *ic)
4598 operand *left = IC_LEFT(ic);
4599 operand *right = IC_RIGHT(ic);
4600 operand *result= IC_RESULT(ic);
4604 /* assign the amsops */
4605 pic16_aopOp (left,ic,FALSE);
4606 pic16_aopOp (right,ic,FALSE);
4607 pic16_aopOp (result,ic,TRUE);
4609 /* special cases first */
4611 if (AOP_TYPE(left) == AOP_CRY &&
4612 AOP_TYPE(right)== AOP_CRY) {
4613 genModbits(left,right,result);
4617 /* if both are of size == 1 */
4618 if (AOP_SIZE(left) == 1 &&
4619 AOP_SIZE(right) == 1 ) {
4620 genModOneByte(left,right,result);
4624 /* should have been converted to function call */
4628 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4630 pic16_freeAsmop(result,NULL,ic,TRUE);
4633 /*-----------------------------------------------------------------*/
4634 /* genIfxJump :- will create a jump depending on the ifx */
4635 /*-----------------------------------------------------------------*/
4637 note: May need to add parameter to indicate when a variable is in bit space.
4639 static void genIfxJump (iCode *ic, char *jval)
4643 /* if true label then we jump if condition
4645 if ( IC_TRUE(ic) ) {
4647 if(strcmp(jval,"a") == 0)
4649 else if (strcmp(jval,"c") == 0)
4652 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4653 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4656 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4657 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4661 /* false label is present */
4662 if(strcmp(jval,"a") == 0)
4664 else if (strcmp(jval,"c") == 0)
4667 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4668 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4672 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4677 /* mark the icode as generated */
4681 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4685 /* if true label then we jump if condition
4687 if ( IC_TRUE(ic) ) {
4688 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4689 pic16_emitpcode(POC_BTFSC, jop);
4691 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4692 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4695 /* false label is present */
4696 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4697 pic16_emitpcode(POC_BTFSS, jop);
4699 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4700 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4704 /* mark the icode as generated */
4711 /*-----------------------------------------------------------------*/
4713 /*-----------------------------------------------------------------*/
4714 static void genSkip(iCode *ifx,int status_bit)
4716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4720 if ( IC_TRUE(ifx) ) {
4721 switch(status_bit) {
4736 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4737 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4741 switch(status_bit) {
4755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4756 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4763 /*-----------------------------------------------------------------*/
4765 /*-----------------------------------------------------------------*/
4766 static void genSkipc(resolvedIfx *rifx)
4768 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4778 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4779 rifx->generated = 1;
4782 #if !(USE_SIMPLE_GENCMP)
4783 /*-----------------------------------------------------------------*/
4785 /*-----------------------------------------------------------------*/
4786 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4788 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4793 if( (rifx->condition ^ invert_condition) & 1)
4798 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4799 rifx->generated = 1;
4804 /*-----------------------------------------------------------------*/
4806 /*-----------------------------------------------------------------*/
4807 static void genSkipz(iCode *ifx, int condition)
4818 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4820 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4823 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4825 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4830 #if !(USE_SIMPLE_GENCMP)
4831 /*-----------------------------------------------------------------*/
4833 /*-----------------------------------------------------------------*/
4834 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4840 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4842 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4845 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4846 rifx->generated = 1;
4851 /*-----------------------------------------------------------------*/
4852 /* genChkZeroes :- greater or less than comparison */
4853 /* For each byte in a literal that is zero, inclusive or the */
4854 /* the corresponding byte in the operand with W */
4855 /* returns true if any of the bytes are zero */
4856 /*-----------------------------------------------------------------*/
4857 static int genChkZeroes(operand *op, int lit, int size)
4864 i = (lit >> (size*8)) & 0xff;
4868 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4870 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4880 /*-----------------------------------------------------------------*/
4881 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4882 /* aop (if it's NOT a literal) or from lit (if */
4883 /* aop is a literal) */
4884 /*-----------------------------------------------------------------*/
4885 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4886 if (aop->type == AOP_LIT) {
4887 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4889 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4893 /*-----------------------------------------------------------------*/
4894 /* genCmp :- greater or less than comparison */
4895 /*-----------------------------------------------------------------*/
4897 #if USE_SIMPLE_GENCMP /* { */
4899 /* genCmp performs a left < right comparison, stores
4900 * the outcome in result (if != NULL) and generates
4901 * control flow code for the ifx (if != NULL).
4903 * This version leaves in sequences like
4904 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4905 * which should be optmized by the peephole
4906 * optimizer - RN 2005-01-01 */
4907 static void genCmp (operand *left,operand *right,
4908 operand *result, iCode *ifx, int sign)
4921 assert (left && right);
4922 assert (AOP_SIZE(left) == AOP_SIZE(right));
4924 size = AOP_SIZE(right) - 1;
4925 mask = (0x100UL << (size*8)) - 1;
4926 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4931 resolveIfx (&rIfx, ifx);
4933 /* handle for special cases */
4934 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4937 /**********************************************************************
4938 * handle bits - bit compares are promoted to int compares seemingly! *
4939 **********************************************************************/
4941 // THIS IS COMPLETELY UNTESTED!
4942 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4943 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4944 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4945 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4948 // 1 < {0,1} is false --> clear C by skipping the next instruction
4949 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4950 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4951 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4952 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4953 emitCLRC; // only skipped for left=0 && right=1
4955 goto correct_result_in_carry;
4959 /*************************************************
4960 * make sure that left is register (or the like) *
4961 *************************************************/
4962 if (!isAOP_REGlike(left)) {
4963 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4964 assert (isAOP_LIT(left));
4965 assert (isAOP_REGlike(right));
4966 // swap left and right
4967 // left < right <==> right > left <==> (right >= left + 1)
4968 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4970 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4971 // MAXVALUE < right? always false
4972 if (performedLt) emitCLRC; else emitSETC;
4973 goto correct_result_in_carry;
4976 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4977 // that's why we handled it above.
4984 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4985 } else if (isAOP_LIT(right)) {
4986 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4989 assert (isAOP_REGlike(left)); // left must be register or the like
4990 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4992 /*************************************************
4993 * special cases go here *
4994 *************************************************/
4996 if (isAOP_LIT(right)) {
4998 // unsigned comparison to a literal
4999 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5001 // unsigned left < 0? always false
5002 if (performedLt) emitCLRC; else emitSETC;
5003 goto correct_result_in_carry;
5006 // signed comparison to a literal
5007 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5008 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5009 // signed left < 0x80000000? always false
5010 if (performedLt) emitCLRC; else emitSETC;
5011 goto correct_result_in_carry;
5012 } else if (lit == 0) {
5013 // compare left < 0; set CARRY if SIGNBIT(left) is set
5014 if (performedLt) emitSETC; else emitCLRC;
5015 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5016 if (performedLt) emitCLRC; else emitSETC;
5017 goto correct_result_in_carry;
5020 } // right is literal
5022 /*************************************************
5023 * perform a general case comparison *
5024 * make sure we get CARRY==1 <==> left >= right *
5025 *************************************************/
5026 // compare most significant bytes
5027 //DEBUGpc ("comparing bytes at offset %d", size);
5029 // unsigned comparison
5030 mov2w_regOrLit (AOP(right), lit, size);
5031 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5033 // signed comparison
5034 // (add 2^n to both operands then perform an unsigned comparison)
5035 if (isAOP_LIT(right)) {
5036 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5037 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5039 if (litbyte == 0x80) {
5040 // left >= 0x80 -- always true, but more bytes to come
5041 pic16_mov2w (AOP(left), size);
5042 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5045 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5046 pic16_mov2w (AOP(left), size);
5047 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5048 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5051 /* using PRODL as a temporary register here */
5052 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5053 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5054 pic16_mov2w (AOP(left), size);
5055 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5056 pic16_emitpcode (POC_MOVWF, pctemp);
5057 pic16_mov2w (AOP(right), size);
5058 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5059 pic16_emitpcode (POC_SUBFW, pctemp);
5060 //pic16_popReleaseTempReg(pctemp, 1);
5064 // compare remaining bytes (treat as unsigned case from above)
5065 templbl = newiTempLabel ( NULL );
5068 //DEBUGpc ("comparing bytes at offset %d", offs);
5069 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5070 mov2w_regOrLit (AOP(right), lit, offs);
5071 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5073 pic16_emitpLabel (templbl->key);
5074 goto result_in_carry;
5078 /****************************************************
5079 * now CARRY contains the result of the comparison: *
5080 * SUBWF sets CARRY iff *
5081 * F-W >= 0 <==> F >= W <==> !(F < W) *
5082 * (F=left, W=right) *
5083 ****************************************************/
5086 if (result && AOP_TYPE(result) != AOP_CRY) {
5087 // value will be stored
5090 // value wil only be used in the following genSkipc()
5091 rIfx.condition ^= 1;
5095 correct_result_in_carry:
5097 // assign result to variable (if neccessary)
5098 if (result && AOP_TYPE(result) != AOP_CRY) {
5099 //DEBUGpc ("assign result");
5100 size = AOP_SIZE(result);
5102 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5104 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5107 // perform conditional jump
5109 //DEBUGpc ("generate control flow");
5118 static void genCmp (operand *left,operand *right,
5119 operand *result, iCode *ifx, int sign)
5121 int size; //, offset = 0 ;
5122 unsigned long lit = 0L,i = 0;
5123 resolvedIfx rFalseIfx;
5124 // resolvedIfx rTrueIfx;
5126 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5129 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5130 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5136 resolveIfx(&rFalseIfx,ifx);
5137 truelbl = newiTempLabel(NULL);
5138 size = max(AOP_SIZE(left),AOP_SIZE(right));
5140 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5144 /* if literal is on the right then swap with left */
5145 if ((AOP_TYPE(right) == AOP_LIT)) {
5146 operand *tmp = right ;
5147 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5148 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5151 lit = (lit - 1) & mask;
5154 rFalseIfx.condition ^= 1;
5157 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5158 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5162 //if(IC_TRUE(ifx) == NULL)
5163 /* if left & right are bit variables */
5164 if (AOP_TYPE(left) == AOP_CRY &&
5165 AOP_TYPE(right) == AOP_CRY ) {
5166 assert (0 && "bit variables used in genCmp");
5167 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5168 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5170 /* subtract right from left if at the
5171 end the carry flag is set then we know that
5172 left is greater than right */
5174 symbol *lbl = newiTempLabel(NULL);
5177 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5178 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5182 if(AOP_TYPE(right) == AOP_LIT) {
5184 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5186 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5193 genSkipCond(&rFalseIfx,left,size-1,7);
5195 /* no need to compare to 0...*/
5196 /* NOTE: this is a de-generate compare that most certainly
5197 * creates some dead code. */
5198 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5200 if(ifx) ifx->generated = 1;
5207 //i = (lit >> (size*8)) & 0xff;
5208 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5212 i = ((0-lit) & 0xff);
5215 /* lit is 0x7f, all signed chars are less than
5216 * this except for 0x7f itself */
5217 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5218 genSkipz2(&rFalseIfx,0);
5220 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5221 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5222 genSkipc(&rFalseIfx);
5227 genSkipz2(&rFalseIfx,1);
5229 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5230 genSkipc(&rFalseIfx);
5234 if(ifx) ifx->generated = 1;
5238 /* chars are out of the way. now do ints and longs */
5241 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5248 genSkipCond(&rFalseIfx,left,size,7);
5249 if(ifx) ifx->generated = 1;
5254 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5256 //rFalseIfx.condition ^= 1;
5257 //genSkipCond(&rFalseIfx,left,size,7);
5258 //rFalseIfx.condition ^= 1;
5260 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5261 if(rFalseIfx.condition)
5262 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5264 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5266 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5267 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5268 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5271 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5273 if(rFalseIfx.condition) {
5275 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5281 genSkipc(&rFalseIfx);
5282 pic16_emitpLabel(truelbl->key);
5283 if(ifx) ifx->generated = 1;
5290 if( (lit & 0xff) == 0) {
5291 /* lower byte is zero */
5292 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5293 i = ((lit >> 8) & 0xff) ^0x80;
5294 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5295 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5297 genSkipc(&rFalseIfx);
5300 if(ifx) ifx->generated = 1;
5305 /* Special cases for signed longs */
5306 if( (lit & 0xffffff) == 0) {
5307 /* lower byte is zero */
5308 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5309 i = ((lit >> 8*3) & 0xff) ^0x80;
5310 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5311 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5312 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5313 genSkipc(&rFalseIfx);
5316 if(ifx) ifx->generated = 1;
5324 if(lit & (0x80 << (size*8))) {
5325 /* lit is negative */
5326 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5328 //genSkipCond(&rFalseIfx,left,size,7);
5330 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5332 if(rFalseIfx.condition)
5333 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5335 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5339 /* lit is positive */
5340 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5341 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5342 if(rFalseIfx.condition)
5343 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5345 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5350 This works, but is only good for ints.
5351 It also requires a "known zero" register.
5352 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5353 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5354 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5355 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5356 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5357 genSkipc(&rFalseIfx);
5359 pic16_emitpLabel(truelbl->key);
5360 if(ifx) ifx->generated = 1;
5364 /* There are no more special cases, so perform a general compare */
5366 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5367 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5371 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5373 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5375 //rFalseIfx.condition ^= 1;
5376 genSkipc(&rFalseIfx);
5378 pic16_emitpLabel(truelbl->key);
5380 if(ifx) ifx->generated = 1;
5387 /* sign is out of the way. So now do an unsigned compare */
5388 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5391 /* General case - compare to an unsigned literal on the right.*/
5393 i = (lit >> (size*8)) & 0xff;
5394 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5395 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5397 i = (lit >> (size*8)) & 0xff;
5400 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5402 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5404 /* this byte of the lit is zero,
5405 *if it's not the last then OR in the variable */
5407 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5412 pic16_emitpLabel(lbl->key);
5413 // pic16_emitpLabel(truelbl->key);
5414 //if(emitFinalCheck)
5415 genSkipc(&rFalseIfx);
5417 pic16_emitpLabel(truelbl->key);
5419 if(ifx) ifx->generated = 1;
5426 if(AOP_TYPE(left) == AOP_LIT) {
5427 //symbol *lbl = newiTempLabel(NULL);
5429 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5432 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5435 if((lit == 0) && (sign == 0)){
5438 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5440 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5442 genSkipz2(&rFalseIfx,0);
5443 if(ifx) ifx->generated = 1;
5450 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5451 /* degenerate compare can never be true */
5452 if(rFalseIfx.condition == 0)
5453 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5455 if(ifx) ifx->generated = 1;
5460 /* signed comparisons to a literal byte */
5462 int lp1 = (lit+1) & 0xff;
5464 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5467 rFalseIfx.condition ^= 1;
5468 genSkipCond(&rFalseIfx,right,0,7);
5471 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5472 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5473 genSkipz2(&rFalseIfx,1);
5476 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5477 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5478 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5479 rFalseIfx.condition ^= 1;
5480 genSkipc(&rFalseIfx);
5484 /* unsigned comparisons to a literal byte */
5486 switch(lit & 0xff ) {
5488 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5489 genSkipz2(&rFalseIfx,0);
5492 rFalseIfx.condition ^= 1;
5493 genSkipCond(&rFalseIfx,right,0,7);
5497 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5498 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5500 rFalseIfx.condition ^= 1;
5501 if (AOP_TYPE(result) == AOP_CRY)
5502 genSkipc(&rFalseIfx);
5504 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5505 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5511 if(ifx) ifx->generated = 1;
5512 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5518 /* Size is greater than 1 */
5526 /* this means lit = 0xffffffff, or -1 */
5529 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5530 rFalseIfx.condition ^= 1;
5531 genSkipCond(&rFalseIfx,right,size,7);
5532 if(ifx) ifx->generated = 1;
5534 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5543 if(rFalseIfx.condition) {
5544 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5545 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5548 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5550 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5554 if(rFalseIfx.condition) {
5555 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5556 pic16_emitpLabel(truelbl->key);
5558 rFalseIfx.condition ^= 1;
5559 genSkipCond(&rFalseIfx,right,s,7);
5562 if(ifx) ifx->generated = 1;
5564 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5570 if((size == 1) && (0 == (lp1&0xff))) {
5571 /* lower byte of signed word is zero */
5572 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5573 i = ((lp1 >> 8) & 0xff) ^0x80;
5574 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5575 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5576 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5578 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5580 if(ifx) ifx->generated = 1;
5583 rFalseIfx.condition ^= 1;
5584 genSkipc(&rFalseIfx);
5585 if(ifx) ifx->generated = 1;
5591 if(lit & (0x80 << (size*8))) {
5592 /* Lit is less than zero */
5593 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5594 //rFalseIfx.condition ^= 1;
5595 //genSkipCond(&rFalseIfx,left,size,7);
5596 //rFalseIfx.condition ^= 1;
5597 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5598 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5600 if(rFalseIfx.condition)
5601 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5603 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5607 /* Lit is greater than or equal to zero */
5608 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5609 //rFalseIfx.condition ^= 1;
5610 //genSkipCond(&rFalseIfx,right,size,7);
5611 //rFalseIfx.condition ^= 1;
5613 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5614 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5616 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5617 if(rFalseIfx.condition)
5618 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5620 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5624 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5625 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5629 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5631 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5633 rFalseIfx.condition ^= 1;
5634 //rFalseIfx.condition = 1;
5635 genSkipc(&rFalseIfx);
5637 pic16_emitpLabel(truelbl->key);
5639 if(ifx) ifx->generated = 1;
5642 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649 /* compare word or long to an unsigned literal on the right.*/
5654 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5657 break; /* handled above */
5660 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5662 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5663 genSkipz2(&rFalseIfx,0);
5667 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5669 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5672 if(rFalseIfx.condition)
5673 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5675 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5678 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5679 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5681 rFalseIfx.condition ^= 1;
5682 genSkipc(&rFalseIfx);
5685 pic16_emitpLabel(truelbl->key);
5687 if(ifx) ifx->generated = 1;
5689 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5697 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5698 i = (lit >> (size*8)) & 0xff;
5700 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5701 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5704 i = (lit >> (size*8)) & 0xff;
5707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5709 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5711 /* this byte of the lit is zero,
5712 * if it's not the last then OR in the variable */
5714 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5719 pic16_emitpLabel(lbl->key);
5721 rFalseIfx.condition ^= 1;
5723 genSkipc(&rFalseIfx);
5727 pic16_emitpLabel(truelbl->key);
5728 if(ifx) ifx->generated = 1;
5730 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5736 /* Compare two variables */
5738 DEBUGpic16_emitcode(";sign","%d",sign);
5742 /* Sigh. thus sucks... */
5746 pctemp = pic16_popGetTempReg(1);
5747 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5748 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5749 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5750 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5751 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5752 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5753 pic16_popReleaseTempReg(pctemp, 1);
5755 /* Signed char comparison */
5756 /* Special thanks to Nikolai Golovchenko for this snippet */
5757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5759 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5760 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5761 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5762 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5765 genSkipc(&rFalseIfx);
5767 if(ifx) ifx->generated = 1;
5769 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5777 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5778 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5782 /* The rest of the bytes of a multi-byte compare */
5786 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5789 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5790 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5795 pic16_emitpLabel(lbl->key);
5797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5798 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5799 (AOP_TYPE(result) == AOP_REG)) {
5800 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5801 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5803 genSkipc(&rFalseIfx);
5805 //genSkipc(&rFalseIfx);
5806 if(ifx) ifx->generated = 1;
5809 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5817 if ((AOP_TYPE(result) != AOP_CRY)
5818 && AOP_SIZE(result)) {
5819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5821 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5823 pic16_outBitC(result);
5825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5826 /* if the result is used in the next
5827 ifx conditional branch then generate
5828 code a little differently */
5830 genIfxJump (ifx,"c");
5832 pic16_outBitC(result);
5833 /* leave the result in acc */
5838 #elif 0 /* VR version of genCmp() */ /* } else { */
5840 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5841 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5842 operand *result, int offset, int invert_op)
5846 /* check condition, > or < ?? */
5847 if(rIfx->condition != 0)invert_op ^= 1;
5849 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5851 if(!ifx)invert_op ^= 1;
5853 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5854 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5857 if(!invert_op)return POC_CPFSGT;
5858 else return POC_CPFSLT;
5861 static int compareAopfirstpass=1;
5863 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5864 operand *oper, int offset, operand *result,
5865 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5871 /* invert if there is a result to be loaded, in order to fit,
5872 * SETC/CLRC sequence */
5873 if(AOP_SIZE(result))invert_op ^= 1;
5875 // if(sign && !offset)invert_op ^= 1;
5877 // if(sign)invert_op ^= 1;
5879 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5881 if(AOP_SIZE(result) && compareAopfirstpass) {
5884 pic16_emitpcode(POC_SETF, pcop2);
5889 pic16_emitpcode(POC_CLRF, pcop2);
5895 compareAopfirstpass = 0;
5897 /* there is a bug when comparing operands with size > 1,
5898 * because higher bytes can be equal and test should be performed
5899 * to the next lower byte, current algorithm, considers operands
5900 * inequal in these cases! -- VR 20041107 */
5904 pic16_emitpcode(op, pcop);
5906 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5909 if((!sign || !offset) && AOP_SIZE(result)) {
5912 pic16_emitpcode(POC_CLRF, pcop2);
5917 pic16_emitpcode(POC_SETF, pcop2);
5922 /* don't emit final branch (offset == 0) */
5926 pic16_emitpcode(POC_RRCF, pcop2);
5928 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5931 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5932 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5933 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5935 truelbl = newiTempLabel( NULL );
5936 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5937 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5938 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5940 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5941 pic16_emitpLabel(truelbl->key);
5943 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5948 static void genCmp (operand *left, operand *right,
5949 operand *result, iCode *ifx, int sign)
5953 resolvedIfx rFalseIfx;
5954 symbol *falselbl, *tlbl;
5958 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5960 resolveIfx(&rFalseIfx, ifx);
5961 size = max(AOP_SIZE(left), AOP_SIZE(right));
5963 /* if left & right are bit variables */
5964 if(AOP_TYPE(left) == AOP_CRY
5965 && AOP_TYPE(right) == AOP_CRY ) {
5967 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5968 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5970 werror(W_POSSBUG2, __FILE__, __LINE__);
5974 /* if literal is on the right then swap with left */
5975 if((AOP_TYPE(right) == AOP_LIT)) {
5976 operand *tmp = right ;
5977 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5979 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5981 // lit = (lit - 1) & mask;
5984 rFalseIfx.condition ^= 1; /* reverse compare */
5986 if ((AOP_TYPE(left) == AOP_LIT)) {
5987 /* float compares are handled by support functions */
5988 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5991 /* actual comparing algorithm */
5992 // size = AOP_SIZE( right );
5994 falselbl = newiTempLabel( NULL );
5995 if(AOP_TYPE(left) == AOP_LIT) {
5996 /* compare to literal */
5997 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6000 pCodeOp *pct, *pct2;
6003 /* signed compare */
6004 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6006 /* using PRODL:PRODH as a temporary register here */
6007 pct = pic16_popCopyReg(&pic16_pc_prodl);
6008 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6009 tlbl = newiTempLabel( NULL );
6011 /* first compare signs:
6012 * a. if both are positive, compare just like unsigned
6013 * b. if both are negative, invert cmpop, compare just like unsigned
6014 * c. if different signs, determine the result directly */
6020 tlbl1 = newiTempLabel( NULL );
6021 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6025 /* literal is zero or positive:
6026 * a. if carry is zero, too, continue compare,
6027 * b. if carry is set, then continue depending on cmpop ^ condition:
6028 * 1. '<' return false (literal < variable),
6029 * 2. '>' return true (literal > variable) */
6030 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6031 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6034 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6035 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6039 /* literal is negative:
6040 * a. if carry is set, too, continue compare,
6041 * b. if carry is zero, then continue depending on cmpop ^ condition:
6042 * 1. '<' return true (literal < variable),
6043 * 2. '>' return false (literal > variable) */
6044 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6045 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6047 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6053 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6055 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6056 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6061 pic16_emitpLabel( tlbl1->key );
6064 compareAopfirstpass=1;
6065 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6066 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6067 // pic16_emitpcode(POC_MOVWF, pct);
6069 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6071 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6072 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6076 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6077 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6078 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6079 // pic16_emitpcode(POC_MOVWF, pct);
6081 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6082 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6083 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6084 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6085 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6088 if(ifx)ifx->generated = 1;
6090 if(AOP_SIZE(result)) {
6091 pic16_emitpLabel(tlbl->key);
6092 pic16_emitpLabel(falselbl->key);
6093 pic16_outBitOp( result, pct2 );
6095 pic16_emitpLabel(tlbl->key);
6099 /* unsigned compare */
6100 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6102 compareAopfirstpass=1;
6105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6106 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6109 if(ifx)ifx->generated = 1;
6111 if(AOP_SIZE(result)) {
6112 pic16_emitpLabel(falselbl->key);
6113 pic16_outBitC( result );
6118 /* compare registers */
6119 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6123 pCodeOp *pct, *pct2;
6125 /* signed compare */
6126 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6128 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6129 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6130 tlbl = newiTempLabel( NULL );
6132 compareAopfirstpass=1;
6135 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6136 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6137 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6138 pic16_emitpcode(POC_MOVWF, pct);
6140 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6141 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6142 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6144 /* WREG already holds left + 0x80 */
6145 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6148 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6149 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6150 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6151 pic16_emitpcode(POC_MOVWF, pct);
6153 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6154 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6155 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6157 /* WREG already holds left + 0x80 */
6158 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6162 if(ifx)ifx->generated = 1;
6164 if(AOP_SIZE(result)) {
6165 pic16_emitpLabel(tlbl->key);
6166 pic16_emitpLabel(falselbl->key);
6167 pic16_outBitOp( result, pct2 );
6169 pic16_emitpLabel(tlbl->key);
6173 /* unsigned compare */
6174 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6176 compareAopfirstpass=1;
6179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6180 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6184 if(ifx)ifx->generated = 1;
6185 if(AOP_SIZE(result)) {
6187 pic16_emitpLabel(falselbl->key);
6188 pic16_outBitC( result );
6199 /*-----------------------------------------------------------------*/
6200 /* genCmpGt :- greater than comparison */
6201 /*-----------------------------------------------------------------*/
6202 static void genCmpGt (iCode *ic, iCode *ifx)
6204 operand *left, *right, *result;
6205 sym_link *letype , *retype;
6211 right= IC_RIGHT(ic);
6212 result = IC_RESULT(ic);
6214 letype = getSpec(operandType(left));
6215 retype =getSpec(operandType(right));
6216 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6217 /* assign the amsops */
6218 pic16_aopOp (left,ic,FALSE);
6219 pic16_aopOp (right,ic,FALSE);
6220 pic16_aopOp (result,ic,TRUE);
6222 genCmp(right, left, result, ifx, sign);
6224 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6225 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6226 pic16_freeAsmop(result,NULL,ic,TRUE);
6229 /*-----------------------------------------------------------------*/
6230 /* genCmpLt - less than comparisons */
6231 /*-----------------------------------------------------------------*/
6232 static void genCmpLt (iCode *ic, iCode *ifx)
6234 operand *left, *right, *result;
6235 sym_link *letype , *retype;
6241 right= IC_RIGHT(ic);
6242 result = IC_RESULT(ic);
6244 letype = getSpec(operandType(left));
6245 retype =getSpec(operandType(right));
6246 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6248 /* assign the amsops */
6249 pic16_aopOp (left,ic,FALSE);
6250 pic16_aopOp (right,ic,FALSE);
6251 pic16_aopOp (result,ic,TRUE);
6253 genCmp(left, right, result, ifx, sign);
6255 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6256 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6257 pic16_freeAsmop(result,NULL,ic,TRUE);
6262 // FIXME reenable literal optimisation when the pic16 port is stable
6264 /*-----------------------------------------------------------------*/
6265 /* genc16bit2lit - compare a 16 bit value to a literal */
6266 /*-----------------------------------------------------------------*/
6267 static void genc16bit2lit(operand *op, int lit, int offset)
6271 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6272 if( (lit&0xff) == 0)
6277 switch( BYTEofLONG(lit,i)) {
6279 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6282 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6285 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6288 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6289 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6294 switch( BYTEofLONG(lit,i)) {
6296 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6300 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6304 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6307 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6309 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6318 /*-----------------------------------------------------------------*/
6319 /* gencjneshort - compare and jump if not equal */
6320 /*-----------------------------------------------------------------*/
6321 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6323 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6325 int res_offset = 0; /* the result may be a different size then left or right */
6326 int res_size = AOP_SIZE(result);
6328 symbol *lbl, *lbl_done;
6330 unsigned long lit = 0L;
6331 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6333 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6334 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6336 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6337 resolveIfx(&rIfx,ifx);
6338 lbl = newiTempLabel(NULL);
6339 lbl_done = newiTempLabel(NULL);
6342 /* if the left side is a literal or
6343 if the right is in a pointer register and left
6345 if ((AOP_TYPE(left) == AOP_LIT) ||
6346 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6351 if(AOP_TYPE(right) == AOP_LIT)
6352 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6354 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6355 preserve_result = 1;
6357 if(result && !preserve_result)
6360 for(i = 0; i < AOP_SIZE(result); i++)
6361 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6365 /* if the right side is a literal then anything goes */
6366 if (AOP_TYPE(right) == AOP_LIT &&
6367 AOP_TYPE(left) != AOP_DIR ) {
6370 genc16bit2lit(left, lit, 0);
6372 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6375 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6378 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6379 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6381 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6385 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6387 if(res_offset < res_size-1)
6395 /* if the right side is in a register or in direct space or
6396 if the left is a pointer register & right is not */
6397 else if (AOP_TYPE(right) == AOP_REG ||
6398 AOP_TYPE(right) == AOP_DIR ||
6399 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6400 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6401 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6402 int lbl_key = lbl->key;
6405 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6406 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6408 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6409 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6410 __FUNCTION__,__LINE__);
6414 /* switch(size) { */
6416 /* genc16bit2lit(left, lit, 0); */
6418 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6423 if((AOP_TYPE(left) == AOP_DIR) &&
6424 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6426 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6427 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6429 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6431 switch (lit & 0xff) {
6433 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6436 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6437 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6438 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6442 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6443 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6444 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6445 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6449 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6450 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6455 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6458 if(AOP_TYPE(result) == AOP_CRY) {
6459 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6466 /* fix me. probably need to check result size too */
6467 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6472 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6473 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6480 if(res_offset < res_size-1)
6485 } else if(AOP_TYPE(right) == AOP_REG &&
6486 AOP_TYPE(left) != AOP_DIR){
6489 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6490 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6491 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6496 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6498 if(res_offset < res_size-1)
6503 /* right is a pointer reg need both a & b */
6505 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6507 pic16_emitcode("mov","b,%s",l);
6508 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6509 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6514 if(result && preserve_result)
6517 for(i = 0; i < AOP_SIZE(result); i++)
6518 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6521 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6523 if(result && preserve_result)
6524 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6527 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6529 pic16_emitpLabel(lbl->key);
6531 if(result && preserve_result)
6534 for(i = 0; i < AOP_SIZE(result); i++)
6535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6537 pic16_emitpLabel(lbl_done->key);
6540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6548 /*-----------------------------------------------------------------*/
6549 /* gencjne - compare and jump if not equal */
6550 /*-----------------------------------------------------------------*/
6551 static void gencjne(operand *left, operand *right, iCode *ifx)
6553 symbol *tlbl = newiTempLabel(NULL);
6555 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6556 gencjneshort(left, right, lbl);
6558 pic16_emitcode("mov","a,%s",one);
6559 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6560 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6561 pic16_emitcode("clr","a");
6562 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6564 pic16_emitpLabel(lbl->key);
6565 pic16_emitpLabel(tlbl->key);
6571 /*-----------------------------------------------------------------*/
6572 /* is_LitOp - check if operand has to be treated as literal */
6573 /*-----------------------------------------------------------------*/
6574 static bool is_LitOp(operand *op)
6576 return ((AOP_TYPE(op) == AOP_LIT)
6577 || ( (AOP_TYPE(op) == AOP_PCODE)
6578 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6579 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6582 /*-----------------------------------------------------------------*/
6583 /* is_LitAOp - check if operand has to be treated as literal */
6584 /*-----------------------------------------------------------------*/
6585 static bool is_LitAOp(asmop *aop)
6587 return ((aop->type == AOP_LIT)
6588 || ( (aop->type == AOP_PCODE)
6589 && ( (aop->aopu.pcop->type == PO_LITERAL)
6590 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6595 /*-----------------------------------------------------------------*/
6596 /* genCmpEq - generates code for equal to */
6597 /*-----------------------------------------------------------------*/
6598 static void genCmpEq (iCode *ic, iCode *ifx)
6600 operand *left, *right, *result;
6601 symbol *falselbl = newiTempLabel(NULL);
6602 symbol *donelbl = newiTempLabel(NULL);
6604 int preserve_result = 0;
6605 int generate_result = 0;
6607 unsigned long lit = -1;
6611 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6612 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6613 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6615 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6617 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6619 werror(W_POSSBUG2, __FILE__, __LINE__);
6620 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6621 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6625 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6627 operand *tmp = right ;
6632 if (AOP_TYPE(right) == AOP_LIT) {
6633 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6636 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6637 preserve_result = 1;
6639 if(result && AOP_SIZE(result))
6640 generate_result = 1;
6642 if(generate_result && !preserve_result)
6644 for(i = 0; i < AOP_SIZE(result); i++)
6645 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6648 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6649 for(i=0; i < AOP_SIZE(left); i++)
6651 if(AOP_TYPE(left) != AOP_ACC)
6654 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6656 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6658 if(is_LitOp(right)) {
6659 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6660 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6663 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6665 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6670 if(generate_result && preserve_result)
6672 for(i = 0; i < AOP_SIZE(result); i++)
6673 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6677 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6679 if(generate_result && preserve_result)
6680 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6682 if(ifx && IC_TRUE(ifx))
6683 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6685 if(ifx && IC_FALSE(ifx))
6686 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6688 pic16_emitpLabel(falselbl->key);
6692 if(ifx && IC_FALSE(ifx))
6693 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6695 if(generate_result && preserve_result)
6697 for(i = 0; i < AOP_SIZE(result); i++)
6698 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6701 pic16_emitpLabel(donelbl->key);
6707 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6708 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6709 pic16_freeAsmop(result,NULL,ic,TRUE);
6715 // old version kept for reference
6717 /*-----------------------------------------------------------------*/
6718 /* genCmpEq - generates code for equal to */
6719 /*-----------------------------------------------------------------*/
6720 static void genCmpEq (iCode *ic, iCode *ifx)
6722 operand *left, *right, *result;
6723 unsigned long lit = 0L;
6725 symbol *falselbl = newiTempLabel(NULL);
6728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6731 DEBUGpic16_emitcode ("; ifx is non-null","");
6733 DEBUGpic16_emitcode ("; ifx is null","");
6735 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6736 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6737 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6739 size = max(AOP_SIZE(left),AOP_SIZE(right));
6741 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6743 /* if literal, literal on the right or
6744 if the right is in a pointer register and left
6746 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6747 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6748 operand *tmp = right ;
6754 if(ifx && !AOP_SIZE(result)){
6756 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6757 /* if they are both bit variables */
6758 if (AOP_TYPE(left) == AOP_CRY &&
6759 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6760 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6761 if(AOP_TYPE(right) == AOP_LIT){
6762 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6764 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6765 pic16_emitcode("cpl","c");
6766 } else if(lit == 1L) {
6767 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6769 pic16_emitcode("clr","c");
6771 /* AOP_TYPE(right) == AOP_CRY */
6773 symbol *lbl = newiTempLabel(NULL);
6774 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6775 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6776 pic16_emitcode("cpl","c");
6777 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6779 /* if true label then we jump if condition
6781 tlbl = newiTempLabel(NULL);
6782 if ( IC_TRUE(ifx) ) {
6783 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6784 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6786 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6787 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6789 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6792 /* left and right are both bit variables, result is carry */
6795 resolveIfx(&rIfx,ifx);
6797 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6798 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6799 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6800 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6805 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6807 /* They're not both bit variables. Is the right a literal? */
6808 if(AOP_TYPE(right) == AOP_LIT) {
6809 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6814 switch(lit & 0xff) {
6816 if ( IC_TRUE(ifx) ) {
6817 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6819 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6821 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6822 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6826 if ( IC_TRUE(ifx) ) {
6827 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6829 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6831 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6832 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6836 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6838 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6843 /* end of size == 1 */
6847 genc16bit2lit(left,lit,offset);
6850 /* end of size == 2 */
6855 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6856 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6857 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6858 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6861 /* search for patterns that can be optimized */
6863 genc16bit2lit(left,lit,0);
6867 emitSKPZ; // if hi word unequal
6869 emitSKPNZ; // if hi word equal
6871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6872 genc16bit2lit(left,lit,2);
6875 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6876 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6880 pic16_emitpLabel(falselbl->key);
6889 } else if(AOP_TYPE(right) == AOP_CRY ) {
6890 /* we know the left is not a bit, but that the right is */
6891 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6892 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6893 pic16_popGet(AOP(right),offset));
6894 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6896 /* if the two are equal, then W will be 0 and the Z bit is set
6897 * we could test Z now, or go ahead and check the high order bytes if
6898 * the variable we're comparing is larger than a byte. */
6901 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6903 if ( IC_TRUE(ifx) ) {
6905 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6906 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6910 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6914 /* They're both variables that are larger than bits */
6917 tlbl = newiTempLabel(NULL);
6920 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6921 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6923 if ( IC_TRUE(ifx) ) {
6927 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6929 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6930 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6934 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6937 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6938 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6943 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6945 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6946 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6950 if(s>1 && IC_TRUE(ifx)) {
6951 pic16_emitpLabel(tlbl->key);
6952 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6956 /* mark the icode as generated */
6961 /* if they are both bit variables */
6962 if (AOP_TYPE(left) == AOP_CRY &&
6963 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6964 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6965 if(AOP_TYPE(right) == AOP_LIT){
6966 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6968 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6969 pic16_emitcode("cpl","c");
6970 } else if(lit == 1L) {
6971 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6973 pic16_emitcode("clr","c");
6975 /* AOP_TYPE(right) == AOP_CRY */
6977 symbol *lbl = newiTempLabel(NULL);
6978 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6979 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6980 pic16_emitcode("cpl","c");
6981 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6984 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6985 pic16_outBitC(result);
6989 genIfxJump (ifx,"c");
6992 /* if the result is used in an arithmetic operation
6993 then put the result in place */
6994 pic16_outBitC(result);
6997 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6998 gencjne(left,right,result,ifx);
7001 gencjne(left,right,newiTempLabel(NULL));
7003 if(IC_TRUE(ifx)->key)
7004 gencjne(left,right,IC_TRUE(ifx)->key);
7006 gencjne(left,right,IC_FALSE(ifx)->key);
7010 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7011 pic16_aopPut(AOP(result),"a",0);
7016 genIfxJump (ifx,"a");
7020 /* if the result is used in an arithmetic operation
7021 then put the result in place */
7023 if (AOP_TYPE(result) != AOP_CRY)
7024 pic16_outAcc(result);
7026 /* leave the result in acc */
7030 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032 pic16_freeAsmop(result,NULL,ic,TRUE);
7036 /*-----------------------------------------------------------------*/
7037 /* ifxForOp - returns the icode containing the ifx for operand */
7038 /*-----------------------------------------------------------------*/
7039 static iCode *ifxForOp ( operand *op, iCode *ic )
7043 /* if true symbol then needs to be assigned */
7044 if (IS_TRUE_SYMOP(op))
7047 /* if this has register type condition and
7048 the next instruction is ifx with the same operand
7049 and live to of the operand is upto the ifx only then */
7051 && ic->next->op == IFX
7052 && IC_COND(ic->next)->key == op->key
7053 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7055 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7061 ic->next->op == IFX &&
7062 IC_COND(ic->next)->key == op->key) {
7063 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7068 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7070 ic->next->op == IFX)
7071 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7074 ic->next->op == IFX &&
7075 IC_COND(ic->next)->key == op->key) {
7076 DEBUGpic16_emitcode ("; "," key is okay");
7077 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7078 OP_SYMBOL(op)->liveTo,
7083 /* the code below is completely untested
7084 * it just allows ulong2fs.c compile -- VR */
7087 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7088 __FILE__, __FUNCTION__, __LINE__);
7090 /* if this has register type condition and
7091 the next instruction is ifx with the same operand
7092 and live to of the operand is upto the ifx only then */
7094 ic->next->op == IFX &&
7095 IC_COND(ic->next)->key == op->key &&
7096 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7100 ic->next->op == IFX &&
7101 IC_COND(ic->next)->key == op->key) {
7102 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7106 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7107 __FILE__, __FUNCTION__, __LINE__);
7109 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7114 /*-----------------------------------------------------------------*/
7115 /* genAndOp - for && operation */
7116 /*-----------------------------------------------------------------*/
7117 static void genAndOp (iCode *ic)
7119 operand *left,*right, *result;
7124 /* note here that && operations that are in an
7125 if statement are taken away by backPatchLabels
7126 only those used in arthmetic operations remain */
7127 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7128 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7129 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7131 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7133 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7134 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7135 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7137 /* if both are bit variables */
7138 /* if (AOP_TYPE(left) == AOP_CRY && */
7139 /* AOP_TYPE(right) == AOP_CRY ) { */
7140 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7141 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7142 /* pic16_outBitC(result); */
7144 /* tlbl = newiTempLabel(NULL); */
7145 /* pic16_toBoolean(left); */
7146 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7147 /* pic16_toBoolean(right); */
7148 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7149 /* pic16_outBitAcc(result); */
7152 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7153 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7154 pic16_freeAsmop(result,NULL,ic,TRUE);
7158 /*-----------------------------------------------------------------*/
7159 /* genOrOp - for || operation */
7160 /*-----------------------------------------------------------------*/
7163 modified this code, but it doesn't appear to ever get called
7166 static void genOrOp (iCode *ic)
7168 operand *left,*right, *result;
7173 /* note here that || operations that are in an
7174 if statement are taken away by backPatchLabels
7175 only those used in arthmetic operations remain */
7176 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7177 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7178 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7180 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7182 /* if both are bit variables */
7183 if (AOP_TYPE(left) == AOP_CRY &&
7184 AOP_TYPE(right) == AOP_CRY ) {
7185 pic16_emitcode("clrc","");
7186 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7187 AOP(left)->aopu.aop_dir,
7188 AOP(left)->aopu.aop_dir);
7189 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7190 AOP(right)->aopu.aop_dir,
7191 AOP(right)->aopu.aop_dir);
7192 pic16_emitcode("setc","");
7195 tlbl = newiTempLabel(NULL);
7196 pic16_toBoolean(left);
7198 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7199 pic16_toBoolean(right);
7200 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7202 pic16_outBitAcc(result);
7205 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7206 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7207 pic16_freeAsmop(result,NULL,ic,TRUE);
7210 /*-----------------------------------------------------------------*/
7211 /* isLiteralBit - test if lit == 2^n */
7212 /*-----------------------------------------------------------------*/
7213 static int isLiteralBit(unsigned long lit)
7215 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7216 0x100L,0x200L,0x400L,0x800L,
7217 0x1000L,0x2000L,0x4000L,0x8000L,
7218 0x10000L,0x20000L,0x40000L,0x80000L,
7219 0x100000L,0x200000L,0x400000L,0x800000L,
7220 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7221 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7225 for(idx = 0; idx < 32; idx++)
7231 /*-----------------------------------------------------------------*/
7232 /* continueIfTrue - */
7233 /*-----------------------------------------------------------------*/
7234 static void continueIfTrue (iCode *ic)
7238 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7242 /*-----------------------------------------------------------------*/
7244 /*-----------------------------------------------------------------*/
7245 static void jumpIfTrue (iCode *ic)
7249 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7253 /*-----------------------------------------------------------------*/
7254 /* jmpTrueOrFalse - */
7255 /*-----------------------------------------------------------------*/
7256 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7258 // ugly but optimized by peephole
7261 symbol *nlbl = newiTempLabel(NULL);
7262 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7263 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7264 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7265 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7267 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7268 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7273 /*-----------------------------------------------------------------*/
7274 /* genAnd - code for and */
7275 /*-----------------------------------------------------------------*/
7276 static void genAnd (iCode *ic, iCode *ifx)
7278 operand *left, *right, *result;
7280 unsigned long lit = 0L;
7286 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7287 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7288 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7290 resolveIfx(&rIfx,ifx);
7292 /* if left is a literal & right is not then exchange them */
7293 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7294 AOP_NEEDSACC(left)) {
7295 operand *tmp = right ;
7300 /* if result = right then exchange them */
7301 if(pic16_sameRegs(AOP(result),AOP(right))){
7302 operand *tmp = right ;
7307 /* if right is bit then exchange them */
7308 if (AOP_TYPE(right) == AOP_CRY &&
7309 AOP_TYPE(left) != AOP_CRY){
7310 operand *tmp = right ;
7314 if(AOP_TYPE(right) == AOP_LIT)
7315 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7317 size = AOP_SIZE(result);
7319 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7322 // result = bit & yy;
7323 if (AOP_TYPE(left) == AOP_CRY){
7324 // c = bit & literal;
7325 if(AOP_TYPE(right) == AOP_LIT){
7327 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7330 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7333 if(size && (AOP_TYPE(result) == AOP_CRY)){
7334 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7337 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7341 pic16_emitcode("clr","c");
7344 if (AOP_TYPE(right) == AOP_CRY){
7346 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7347 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7350 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7352 pic16_emitcode("rrc","a");
7353 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7359 pic16_outBitC(result);
7361 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7362 genIfxJump(ifx, "c");
7366 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7367 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7368 if((AOP_TYPE(right) == AOP_LIT) &&
7369 (AOP_TYPE(result) == AOP_CRY) &&
7370 (AOP_TYPE(left) != AOP_CRY)){
7371 int posbit = isLiteralBit(lit);
7375 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7378 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7384 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7385 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7387 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7388 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7391 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7392 size = AOP_SIZE(left);
7395 int bp = posbit, ofs=0;
7402 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7403 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7407 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7408 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7410 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7417 symbol *tlbl = newiTempLabel(NULL);
7418 int sizel = AOP_SIZE(left);
7424 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7426 /* patch provided by Aaron Colwell */
7427 if((posbit = isLiteralBit(bytelit)) != 0) {
7428 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7429 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7430 (posbit-1),0, PO_GPR_REGISTER));
7432 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7433 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7435 if (bytelit == 0xff) {
7436 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7437 * a peephole could optimize it out -- VR */
7438 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7440 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7441 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7444 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7445 pic16_popGetLabel(tlbl->key));
7449 /* old code, left here for reference -- VR 09/2004 */
7450 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7452 if((posbit = isLiteralBit(bytelit)) != 0)
7453 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7455 if(bytelit != 0x0FFL)
7456 pic16_emitcode("anl","a,%s",
7457 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7458 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7464 // bit = left & literal
7467 pic16_emitpLabel(tlbl->key);
7469 // if(left & literal)
7472 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7475 pic16_emitpLabel(tlbl->key);
7480 pic16_outBitC(result);
7484 /* if left is same as result */
7485 if(pic16_sameRegs(AOP(result),AOP(left))){
7487 for(;size--; offset++,lit>>=8) {
7488 if(AOP_TYPE(right) == AOP_LIT){
7489 switch(lit & 0xff) {
7491 /* and'ing with 0 has clears the result */
7492 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7493 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7496 /* and'ing with 0xff is a nop when the result and left are the same */
7501 int p = pic16_my_powof2( (~lit) & 0xff );
7503 /* only one bit is set in the literal, so use a bcf instruction */
7504 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7505 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7508 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7509 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7510 if(know_W != (lit&0xff))
7511 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7513 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7518 if (AOP_TYPE(left) == AOP_ACC) {
7519 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7521 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7522 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7529 // left & result in different registers
7530 if(AOP_TYPE(result) == AOP_CRY){
7532 // if(size), result in bit
7533 // if(!size && ifx), conditional oper: if(left & right)
7534 symbol *tlbl = newiTempLabel(NULL);
7535 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7537 pic16_emitcode("setb","c");
7539 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7540 pic16_emitcode("anl","a,%s",
7541 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7542 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7547 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7548 pic16_outBitC(result);
7550 jmpTrueOrFalse(ifx, tlbl);
7552 for(;(size--);offset++) {
7554 // result = left & right
7555 if(AOP_TYPE(right) == AOP_LIT){
7556 int t = (lit >> (offset*8)) & 0x0FFL;
7559 pic16_emitcode("clrf","%s",
7560 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7561 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7564 pic16_emitcode("movf","%s,w",
7565 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7566 pic16_emitcode("movwf","%s",
7567 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7568 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7569 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7572 pic16_emitcode("movlw","0x%x",t);
7573 pic16_emitcode("andwf","%s,w",
7574 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7575 pic16_emitcode("movwf","%s",
7576 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7579 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7580 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7585 if (AOP_TYPE(left) == AOP_ACC) {
7586 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7587 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7589 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7590 pic16_emitcode("andwf","%s,w",
7591 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7592 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7593 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7595 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7596 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7602 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7603 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7604 pic16_freeAsmop(result,NULL,ic,TRUE);
7607 /*-----------------------------------------------------------------*/
7608 /* genOr - code for or */
7609 /*-----------------------------------------------------------------*/
7610 static void genOr (iCode *ic, iCode *ifx)
7612 operand *left, *right, *result;
7614 unsigned long lit = 0L;
7616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7618 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7619 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7620 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7622 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7624 /* if left is a literal & right is not then exchange them */
7625 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7626 AOP_NEEDSACC(left)) {
7627 operand *tmp = right ;
7632 /* if result = right then exchange them */
7633 if(pic16_sameRegs(AOP(result),AOP(right))){
7634 operand *tmp = right ;
7639 /* if right is bit then exchange them */
7640 if (AOP_TYPE(right) == AOP_CRY &&
7641 AOP_TYPE(left) != AOP_CRY){
7642 operand *tmp = right ;
7647 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7649 if(AOP_TYPE(right) == AOP_LIT)
7650 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7652 size = AOP_SIZE(result);
7656 if (AOP_TYPE(left) == AOP_CRY){
7657 if(AOP_TYPE(right) == AOP_LIT){
7658 // c = bit & literal;
7660 // lit != 0 => result = 1
7661 if(AOP_TYPE(result) == AOP_CRY){
7663 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7664 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7665 // AOP(result)->aopu.aop_dir,
7666 // AOP(result)->aopu.aop_dir);
7668 continueIfTrue(ifx);
7672 // lit == 0 => result = left
7673 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7675 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7678 if (AOP_TYPE(right) == AOP_CRY){
7679 if(pic16_sameRegs(AOP(result),AOP(left))){
7681 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7682 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7683 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7685 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7686 AOP(result)->aopu.aop_dir,
7687 AOP(result)->aopu.aop_dir);
7688 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7689 AOP(right)->aopu.aop_dir,
7690 AOP(right)->aopu.aop_dir);
7691 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7692 AOP(result)->aopu.aop_dir,
7693 AOP(result)->aopu.aop_dir);
7695 if( AOP_TYPE(result) == AOP_ACC) {
7696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7697 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7698 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7703 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7704 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7705 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7706 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7708 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7709 AOP(result)->aopu.aop_dir,
7710 AOP(result)->aopu.aop_dir);
7711 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7712 AOP(right)->aopu.aop_dir,
7713 AOP(right)->aopu.aop_dir);
7714 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7715 AOP(left)->aopu.aop_dir,
7716 AOP(left)->aopu.aop_dir);
7717 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7718 AOP(result)->aopu.aop_dir,
7719 AOP(result)->aopu.aop_dir);
7724 symbol *tlbl = newiTempLabel(NULL);
7725 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7728 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7729 if( AOP_TYPE(right) == AOP_ACC) {
7730 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7732 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7733 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7738 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7739 pic16_emitcode(";XXX setb","c");
7740 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7741 AOP(left)->aopu.aop_dir,tlbl->key+100);
7742 pic16_toBoolean(right);
7743 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7744 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7745 jmpTrueOrFalse(ifx, tlbl);
7749 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7756 pic16_outBitC(result);
7758 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7759 genIfxJump(ifx, "c");
7763 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7764 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7765 if((AOP_TYPE(right) == AOP_LIT) &&
7766 (AOP_TYPE(result) == AOP_CRY) &&
7767 (AOP_TYPE(left) != AOP_CRY)){
7769 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7772 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7774 continueIfTrue(ifx);
7777 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7778 // lit = 0, result = boolean(left)
7780 pic16_emitcode(";XXX setb","c");
7781 pic16_toBoolean(right);
7783 symbol *tlbl = newiTempLabel(NULL);
7784 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7786 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7788 genIfxJump (ifx,"a");
7792 pic16_outBitC(result);
7796 /* if left is same as result */
7797 if(pic16_sameRegs(AOP(result),AOP(left))){
7799 for(;size--; offset++,lit>>=8) {
7800 if(AOP_TYPE(right) == AOP_LIT){
7801 if((lit & 0xff) == 0)
7802 /* or'ing with 0 has no effect */
7805 int p = pic16_my_powof2(lit & 0xff);
7807 /* only one bit is set in the literal, so use a bsf instruction */
7808 pic16_emitpcode(POC_BSF,
7809 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7811 if(know_W != (lit & 0xff))
7812 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7813 know_W = lit & 0xff;
7814 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7819 if (AOP_TYPE(left) == AOP_ACC) {
7820 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7821 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7823 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7824 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7826 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7827 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7833 // left & result in different registers
7834 if(AOP_TYPE(result) == AOP_CRY){
7836 // if(size), result in bit
7837 // if(!size && ifx), conditional oper: if(left | right)
7838 symbol *tlbl = newiTempLabel(NULL);
7839 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7840 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7844 pic16_emitcode(";XXX setb","c");
7846 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7847 pic16_emitcode(";XXX orl","a,%s",
7848 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7849 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7854 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7855 pic16_outBitC(result);
7857 jmpTrueOrFalse(ifx, tlbl);
7858 } else for(;(size--);offset++){
7860 // result = left & right
7861 if(AOP_TYPE(right) == AOP_LIT){
7862 int t = (lit >> (offset*8)) & 0x0FFL;
7865 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7866 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7868 // pic16_emitcode("movf","%s,w",
7869 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7870 // pic16_emitcode("movwf","%s",
7871 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7874 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7875 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7876 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7878 // pic16_emitcode("movlw","0x%x",t);
7879 // pic16_emitcode("iorwf","%s,w",
7880 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7881 // pic16_emitcode("movwf","%s",
7882 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7888 // faster than result <- left, anl result,right
7889 // and better if result is SFR
7890 if (AOP_TYPE(left) == AOP_ACC) {
7891 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7892 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7895 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7897 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 // pic16_emitcode("iorwf","%s,w",
7899 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7901 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7902 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7907 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7908 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7909 pic16_freeAsmop(result,NULL,ic,TRUE);
7912 /*-----------------------------------------------------------------*/
7913 /* genXor - code for xclusive or */
7914 /*-----------------------------------------------------------------*/
7915 static void genXor (iCode *ic, iCode *ifx)
7917 operand *left, *right, *result;
7919 unsigned long lit = 0L;
7921 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7923 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7924 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7925 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7927 /* if left is a literal & right is not ||
7928 if left needs acc & right does not */
7929 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7930 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7931 operand *tmp = right ;
7936 /* if result = right then exchange them */
7937 if(pic16_sameRegs(AOP(result),AOP(right))){
7938 operand *tmp = right ;
7943 /* if right is bit then exchange them */
7944 if (AOP_TYPE(right) == AOP_CRY &&
7945 AOP_TYPE(left) != AOP_CRY){
7946 operand *tmp = right ;
7950 if(AOP_TYPE(right) == AOP_LIT)
7951 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7953 size = AOP_SIZE(result);
7957 if (AOP_TYPE(left) == AOP_CRY){
7958 if(AOP_TYPE(right) == AOP_LIT){
7959 // c = bit & literal;
7961 // lit>>1 != 0 => result = 1
7962 if(AOP_TYPE(result) == AOP_CRY){
7964 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7965 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7967 continueIfTrue(ifx);
7970 pic16_emitcode("setb","c");
7974 // lit == 0, result = left
7975 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7977 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7979 // lit == 1, result = not(left)
7980 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7981 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7982 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7983 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7986 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7987 pic16_emitcode("cpl","c");
7994 symbol *tlbl = newiTempLabel(NULL);
7995 if (AOP_TYPE(right) == AOP_CRY){
7997 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8000 int sizer = AOP_SIZE(right);
8002 // if val>>1 != 0, result = 1
8003 pic16_emitcode("setb","c");
8005 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8007 // test the msb of the lsb
8008 pic16_emitcode("anl","a,#0xfe");
8009 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8013 pic16_emitcode("rrc","a");
8015 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8016 pic16_emitcode("cpl","c");
8017 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8022 pic16_outBitC(result);
8024 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8025 genIfxJump(ifx, "c");
8029 if(pic16_sameRegs(AOP(result),AOP(left))){
8030 /* if left is same as result */
8031 for(;size--; offset++) {
8032 if(AOP_TYPE(right) == AOP_LIT){
8033 int t = (lit >> (offset*8)) & 0x0FFL;
8037 if (IS_AOP_PREG(left)) {
8038 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8039 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8040 pic16_aopPut(AOP(result),"a",offset);
8042 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8043 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8044 pic16_emitcode("xrl","%s,%s",
8045 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8046 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8049 if (AOP_TYPE(left) == AOP_ACC)
8050 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8052 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8053 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8055 if (IS_AOP_PREG(left)) {
8056 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8057 pic16_aopPut(AOP(result),"a",offset);
8059 pic16_emitcode("xrl","%s,a",
8060 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8066 // left & result in different registers
8067 if(AOP_TYPE(result) == AOP_CRY){
8069 // if(size), result in bit
8070 // if(!size && ifx), conditional oper: if(left ^ right)
8071 symbol *tlbl = newiTempLabel(NULL);
8072 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8074 pic16_emitcode("setb","c");
8076 if((AOP_TYPE(right) == AOP_LIT) &&
8077 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8078 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8080 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8081 pic16_emitcode("xrl","a,%s",
8082 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8084 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8089 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8090 pic16_outBitC(result);
8092 jmpTrueOrFalse(ifx, tlbl);
8093 } else for(;(size--);offset++){
8095 // result = left & right
8096 if(AOP_TYPE(right) == AOP_LIT){
8097 int t = (lit >> (offset*8)) & 0x0FFL;
8100 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8101 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8102 pic16_emitcode("movf","%s,w",
8103 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8104 pic16_emitcode("movwf","%s",
8105 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8108 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8109 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8110 pic16_emitcode("comf","%s,w",
8111 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8112 pic16_emitcode("movwf","%s",
8113 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8117 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8118 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8119 pic16_emitcode("movlw","0x%x",t);
8120 pic16_emitcode("xorwf","%s,w",
8121 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8122 pic16_emitcode("movwf","%s",
8123 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8129 // faster than result <- left, anl result,right
8130 // and better if result is SFR
8131 if (AOP_TYPE(left) == AOP_ACC) {
8132 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8133 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8135 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8136 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8137 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8138 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8140 if ( AOP_TYPE(result) != AOP_ACC){
8141 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8142 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8148 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8149 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8150 pic16_freeAsmop(result,NULL,ic,TRUE);
8153 /*-----------------------------------------------------------------*/
8154 /* genInline - write the inline code out */
8155 /*-----------------------------------------------------------------*/
8156 static void genInline (iCode *ic)
8158 char *buffer, *bp, *bp1;
8160 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8162 _G.inLine += (!options.asmpeep);
8164 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8165 strcpy(buffer,IC_INLINE(ic));
8167 while((bp1=strstr(bp, "\\n"))) {
8175 /* This is an experimental code for #pragma inline
8176 and is temporarily disabled for 2.5.0 release */
8184 cbuf = Safe_strdup(buffer);
8185 cblen = strlen(buffer)+1;
8186 memset(cbuf, 0, cblen);
8191 if(*bp != '%')*bp1++ = *bp++;
8197 if(i>elementsInSet(asmInlineMap))break;
8200 s = indexSet(asmInlineMap, i);
8201 DEBUGpc("searching symbol s = `%s'", s);
8202 sym = findSym(SymbolTab, NULL, s);
8205 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8207 strcat(bp1, sym->rname);
8213 if(strlen(bp1) > cblen - 16) {
8214 int i = strlen(cbuf);
8216 cbuf = realloc(cbuf, cblen);
8217 memset(cbuf+i, 0, 50);
8223 buffer = Safe_strdup( cbuf );
8230 /* emit each line as a code */
8236 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8244 /* print label, use this special format with NULL directive
8245 * to denote that the argument should not be indented with tab */
8246 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8249 /* advance to end of line (prevent splitting of comments at ':' */
8250 while (*bp && *bp != '\n') {
8258 if ((bp1 != bp) && *bp1)
8259 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8264 _G.inLine -= (!options.asmpeep);
8267 /*-----------------------------------------------------------------*/
8268 /* genRRC - rotate right with carry */
8269 /*-----------------------------------------------------------------*/
8270 static void genRRC (iCode *ic)
8272 operand *left , *result ;
8273 int size, offset = 0, same;
8275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8277 /* rotate right with carry */
8279 result=IC_RESULT(ic);
8280 pic16_aopOp (left,ic,FALSE);
8281 pic16_aopOp (result,ic,TRUE);
8283 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8285 same = pic16_sameRegs(AOP(result),AOP(left));
8287 size = AOP_SIZE(result);
8289 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8291 /* get the lsb and put it into the carry */
8292 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8299 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8301 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8302 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8308 pic16_freeAsmop(left,NULL,ic,TRUE);
8309 pic16_freeAsmop(result,NULL,ic,TRUE);
8312 /*-----------------------------------------------------------------*/
8313 /* genRLC - generate code for rotate left with carry */
8314 /*-----------------------------------------------------------------*/
8315 static void genRLC (iCode *ic)
8317 operand *left , *result ;
8318 int size, offset = 0;
8321 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8322 /* rotate right with carry */
8324 result=IC_RESULT(ic);
8325 pic16_aopOp (left,ic,FALSE);
8326 pic16_aopOp (result,ic,TRUE);
8328 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8330 same = pic16_sameRegs(AOP(result),AOP(left));
8332 /* move it to the result */
8333 size = AOP_SIZE(result);
8335 /* get the msb and put it into the carry */
8336 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8343 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8345 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8353 pic16_freeAsmop(left,NULL,ic,TRUE);
8354 pic16_freeAsmop(result,NULL,ic,TRUE);
8358 /* gpasm can get the highest order bit with HIGH/UPPER
8359 * so the following probably is not needed -- VR */
8361 /*-----------------------------------------------------------------*/
8362 /* genGetHbit - generates code get highest order bit */
8363 /*-----------------------------------------------------------------*/
8364 static void genGetHbit (iCode *ic)
8366 operand *left, *result;
8368 result=IC_RESULT(ic);
8369 pic16_aopOp (left,ic,FALSE);
8370 pic16_aopOp (result,ic,FALSE);
8372 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8373 /* get the highest order byte into a */
8374 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8375 if(AOP_TYPE(result) == AOP_CRY){
8376 pic16_emitcode("rlc","a");
8377 pic16_outBitC(result);
8380 pic16_emitcode("rl","a");
8381 pic16_emitcode("anl","a,#0x01");
8382 pic16_outAcc(result);
8386 pic16_freeAsmop(left,NULL,ic,TRUE);
8387 pic16_freeAsmop(result,NULL,ic,TRUE);
8391 /*-----------------------------------------------------------------*/
8392 /* AccRol - rotate left accumulator by known count */
8393 /*-----------------------------------------------------------------*/
8394 static void AccRol (int shCount)
8396 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8397 shCount &= 0x0007; // shCount : 0..7
8402 pic16_emitcode("rl","a");
8405 pic16_emitcode("rl","a");
8406 pic16_emitcode("rl","a");
8409 pic16_emitcode("swap","a");
8410 pic16_emitcode("rr","a");
8413 pic16_emitcode("swap","a");
8416 pic16_emitcode("swap","a");
8417 pic16_emitcode("rl","a");
8420 pic16_emitcode("rr","a");
8421 pic16_emitcode("rr","a");
8424 pic16_emitcode("rr","a");
8430 /*-----------------------------------------------------------------*/
8431 /* AccLsh - left shift accumulator by known count */
8432 /*-----------------------------------------------------------------*/
8433 static void AccLsh (int shCount, int doMask)
8435 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8441 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8449 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8452 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8455 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8456 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8459 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467 /* no masking is required in genPackBits */
8468 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8472 /*-----------------------------------------------------------------*/
8473 /* AccRsh - right shift accumulator by known count */
8474 /*-----------------------------------------------------------------*/
8475 static void AccRsh (int shCount, int andmask)
8477 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8482 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8485 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8486 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8489 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8490 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8493 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8496 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8497 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8500 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8501 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8504 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8509 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8511 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8515 /*-----------------------------------------------------------------*/
8516 /* AccSRsh - signed right shift accumulator by known count */
8517 /*-----------------------------------------------------------------*/
8518 static void AccSRsh (int shCount)
8521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8524 pic16_emitcode("mov","c,acc.7");
8525 pic16_emitcode("rrc","a");
8526 } else if(shCount == 2){
8527 pic16_emitcode("mov","c,acc.7");
8528 pic16_emitcode("rrc","a");
8529 pic16_emitcode("mov","c,acc.7");
8530 pic16_emitcode("rrc","a");
8532 tlbl = newiTempLabel(NULL);
8533 /* rotate right accumulator */
8534 AccRol(8 - shCount);
8535 /* and kill the higher order bits */
8536 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8537 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8538 pic16_emitcode("orl","a,#0x%02x",
8539 (unsigned char)~SRMask[shCount]);
8540 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8546 /*-----------------------------------------------------------------*/
8547 /* shiftR1Left2Result - shift right one byte from left to result */
8548 /*-----------------------------------------------------------------*/
8549 static void shiftR1Left2ResultSigned (operand *left, int offl,
8550 operand *result, int offr,
8555 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8557 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8561 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8563 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8565 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8566 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8572 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8574 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8576 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8577 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8579 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8580 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8586 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8588 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8592 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8593 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8594 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8596 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8597 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8599 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8603 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8604 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8605 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8606 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8607 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8611 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8613 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8614 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8616 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8617 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8618 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8619 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8620 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8625 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8626 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8627 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8628 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8629 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8630 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8632 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8633 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8634 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8635 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8636 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8642 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8643 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8644 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8645 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8647 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8648 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8649 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8657 /*-----------------------------------------------------------------*/
8658 /* shiftR1Left2Result - shift right one byte from left to result */
8659 /*-----------------------------------------------------------------*/
8660 static void shiftR1Left2Result (operand *left, int offl,
8661 operand *result, int offr,
8662 int shCount, int sign)
8666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8668 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8670 /* Copy the msb into the carry if signed. */
8672 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8682 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8684 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8685 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8694 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8702 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8704 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8709 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8715 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8716 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8717 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8721 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8722 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8723 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8725 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8730 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8731 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8732 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8733 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8734 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8739 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8740 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8741 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8750 /*-----------------------------------------------------------------*/
8751 /* shiftL1Left2Result - shift left one byte from left to result */
8752 /*-----------------------------------------------------------------*/
8753 static void shiftL1Left2Result (operand *left, int offl,
8754 operand *result, int offr, int shCount)
8759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8761 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8762 DEBUGpic16_emitcode ("; ***","same = %d",same);
8763 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8765 /* shift left accumulator */
8766 //AccLsh(shCount, 1); // don't comment out just yet...
8767 // pic16_aopPut(AOP(result),"a",offr);
8771 /* Shift left 1 bit position */
8772 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8774 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8776 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8783 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8788 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8789 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8795 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8796 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8799 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8800 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8801 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8802 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8805 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8806 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8807 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8808 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8812 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8813 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8814 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8818 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8823 /*-----------------------------------------------------------------*/
8824 /* movLeft2Result - move byte from left to result */
8825 /*-----------------------------------------------------------------*/
8826 static void movLeft2Result (operand *left, int offl,
8827 operand *result, int offr)
8830 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8831 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8832 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8834 if (*l == '@' && (IS_AOP_PREG(result))) {
8835 pic16_emitcode("mov","a,%s",l);
8836 pic16_aopPut(AOP(result),"a",offr);
8838 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8839 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8844 /*-----------------------------------------------------------------*/
8845 /* shiftL2Left2Result - shift left two bytes from left to result */
8846 /*-----------------------------------------------------------------*/
8847 static void shiftL2Left2Result (operand *left, int offl,
8848 operand *result, int offr, int shCount)
8850 int same = pic16_sameRegs(AOP(result), AOP(left));
8853 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8855 if (same && (offl != offr)) { // shift bytes
8858 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8861 } else { // just treat as different later on
8874 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8880 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8881 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8887 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8888 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8889 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8890 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8893 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8895 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8896 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8900 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8901 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8902 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8903 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8904 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8905 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8906 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8907 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8909 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8912 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8913 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8914 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8915 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8916 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8926 /* note, use a mov/add for the shift since the mov has a
8927 chance of getting optimized out */
8928 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8930 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8931 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8932 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8936 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8937 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8943 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8944 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8946 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8949 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8954 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8960 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8968 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8974 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8975 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8976 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8977 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8983 /*-----------------------------------------------------------------*/
8984 /* shiftR2Left2Result - shift right two bytes from left to result */
8985 /*-----------------------------------------------------------------*/
8986 static void shiftR2Left2Result (operand *left, int offl,
8987 operand *result, int offr,
8988 int shCount, int sign)
8990 int same = pic16_sameRegs(AOP(result), AOP(left));
8992 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8994 if (same && (offl != offr)) { // shift right bytes
8997 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8998 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9000 } else { // just treat as different later on
9012 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9017 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9018 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9021 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9023 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9040 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9045 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9046 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9049 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9050 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9052 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9053 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9054 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9055 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9056 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9060 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9061 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9066 pic16_emitpcode(POC_BTFSC,
9067 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9068 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9076 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9077 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9079 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9081 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9082 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9084 pic16_emitpcode(POC_BTFSC,
9085 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9086 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9088 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9090 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9091 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9094 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9095 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9096 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9099 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9100 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9102 pic16_emitpcode(POC_BTFSC,
9103 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9104 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9106 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9107 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9115 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9116 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9117 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9120 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9122 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9127 /*-----------------------------------------------------------------*/
9128 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9129 /*-----------------------------------------------------------------*/
9130 static void shiftLLeftOrResult (operand *left, int offl,
9131 operand *result, int offr, int shCount)
9133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9135 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9136 /* shift left accumulator */
9138 /* or with result */
9139 /* back to result */
9140 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9143 /*-----------------------------------------------------------------*/
9144 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9145 /*-----------------------------------------------------------------*/
9146 static void shiftRLeftOrResult (operand *left, int offl,
9147 operand *result, int offr, int shCount)
9149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9151 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9152 /* shift right accumulator */
9154 /* or with result */
9155 /* back to result */
9156 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9159 /*-----------------------------------------------------------------*/
9160 /* genlshOne - left shift a one byte quantity by known count */
9161 /*-----------------------------------------------------------------*/
9162 static void genlshOne (operand *result, operand *left, int shCount)
9164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9165 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9168 /*-----------------------------------------------------------------*/
9169 /* genlshTwo - left shift two bytes by known amount != 0 */
9170 /*-----------------------------------------------------------------*/
9171 static void genlshTwo (operand *result,operand *left, int shCount)
9175 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9176 size = pic16_getDataSize(result);
9178 /* if shCount >= 8 */
9184 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9186 movLeft2Result(left, LSB, result, MSB16);
9188 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9191 /* 1 <= shCount <= 7 */
9194 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9196 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9200 /*-----------------------------------------------------------------*/
9201 /* shiftLLong - shift left one long from left to result */
9202 /* offr = LSB or MSB16 */
9203 /*-----------------------------------------------------------------*/
9204 static void shiftLLong (operand *left, operand *result, int offr )
9206 int size = AOP_SIZE(result);
9207 int same = pic16_sameRegs(AOP(left),AOP(result));
9210 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9212 if (same && (offr == MSB16)) { //shift one byte
9213 for(i=size-1;i>=MSB16;i--) {
9214 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9215 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9218 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9221 if (size > LSB+offr ){
9223 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9225 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9226 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9230 if(size > MSB16+offr){
9232 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9234 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9235 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9239 if(size > MSB24+offr){
9241 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9243 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9244 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9248 if(size > MSB32+offr){
9250 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9252 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9253 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9257 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9261 /*-----------------------------------------------------------------*/
9262 /* genlshFour - shift four byte by a known amount != 0 */
9263 /*-----------------------------------------------------------------*/
9264 static void genlshFour (operand *result, operand *left, int shCount)
9268 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9269 size = AOP_SIZE(result);
9271 /* if shifting more that 3 bytes */
9272 if (shCount >= 24 ) {
9275 /* lowest order of left goes to the highest
9276 order of the destination */
9277 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9279 movLeft2Result(left, LSB, result, MSB32);
9281 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9282 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9283 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9288 /* more than two bytes */
9289 else if ( shCount >= 16 ) {
9290 /* lower order two bytes goes to higher order two bytes */
9292 /* if some more remaining */
9294 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9296 movLeft2Result(left, MSB16, result, MSB32);
9297 movLeft2Result(left, LSB, result, MSB24);
9299 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9300 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9304 /* if more than 1 byte */
9305 else if ( shCount >= 8 ) {
9306 /* lower order three bytes goes to higher order three bytes */
9310 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9312 movLeft2Result(left, LSB, result, MSB16);
9314 else{ /* size = 4 */
9316 movLeft2Result(left, MSB24, result, MSB32);
9317 movLeft2Result(left, MSB16, result, MSB24);
9318 movLeft2Result(left, LSB, result, MSB16);
9319 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9321 else if(shCount == 1)
9322 shiftLLong(left, result, MSB16);
9324 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9325 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9326 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9327 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9332 /* 1 <= shCount <= 7 */
9333 else if(shCount <= 3)
9335 shiftLLong(left, result, LSB);
9336 while(--shCount >= 1)
9337 shiftLLong(result, result, LSB);
9339 /* 3 <= shCount <= 7, optimize */
9341 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9342 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9343 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9347 /*-----------------------------------------------------------------*/
9348 /* genLeftShiftLiteral - left shifting by known count */
9349 /*-----------------------------------------------------------------*/
9350 void pic16_genLeftShiftLiteral (operand *left,
9355 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9359 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9360 pic16_freeAsmop(right,NULL,ic,TRUE);
9362 pic16_aopOp(left,ic,FALSE);
9363 pic16_aopOp(result,ic,TRUE);
9365 size = getSize(operandType(result));
9368 pic16_emitcode("; shift left ","result %d, left %d",size,
9372 /* I suppose that the left size >= result size */
9375 movLeft2Result(left, size, result, size);
9379 else if(shCount >= (size * 8))
9381 pic16_aopPut(AOP(result),zero,size);
9385 genlshOne (result,left,shCount);
9390 genlshTwo (result,left,shCount);
9394 genlshFour (result,left,shCount);
9398 pic16_freeAsmop(left,NULL,ic,TRUE);
9399 pic16_freeAsmop(result,NULL,ic,TRUE);
9402 /*-----------------------------------------------------------------*
9403 * genMultiAsm - repeat assembly instruction for size of register.
9404 * if endian == 1, then the high byte (i.e base address + size of
9405 * register) is used first else the low byte is used first;
9406 *-----------------------------------------------------------------*/
9407 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9412 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9425 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9431 #if !(USE_GENERIC_SIGNED_SHIFT)
9432 /*-----------------------------------------------------------------*/
9433 /* genLeftShift - generates code for left shifting */
9434 /*-----------------------------------------------------------------*/
9435 static void genLeftShift (iCode *ic)
9437 operand *left,*right, *result;
9440 symbol *tlbl , *tlbl1;
9443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9445 right = IC_RIGHT(ic);
9447 result = IC_RESULT(ic);
9449 pic16_aopOp(right,ic,FALSE);
9451 /* if the shift count is known then do it
9452 as efficiently as possible */
9453 if (AOP_TYPE(right) == AOP_LIT) {
9454 pic16_genLeftShiftLiteral (left,right,result,ic);
9458 /* shift count is unknown then we have to form
9459 * a loop. Get the loop count in WREG : Note: we take
9460 * only the lower order byte since shifting
9461 * more than 32 bits make no sense anyway, ( the
9462 * largest size of an object can be only 32 bits ) */
9464 pic16_aopOp(left,ic,FALSE);
9465 pic16_aopOp(result,ic,FALSE);
9467 /* now move the left to the result if they are not the
9468 * same, and if size > 1,
9469 * and if right is not same to result (!!!) -- VR */
9470 if (!pic16_sameRegs(AOP(left),AOP(result))
9471 && (AOP_SIZE(result) > 1)) {
9473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9475 size = AOP_SIZE(result);
9480 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9481 if (*l == '@' && (IS_AOP_PREG(result))) {
9483 pic16_emitcode("mov","a,%s",l);
9484 pic16_aopPut(AOP(result),"a",offset);
9488 /* we don't know if left is a literal or a register, take care -- VR */
9489 pic16_mov2f(AOP(result), AOP(left), offset);
9495 size = AOP_SIZE(result);
9497 /* if it is only one byte then */
9499 if(optimized_for_speed) {
9500 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9501 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9502 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9503 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9504 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9505 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9506 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9507 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9508 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9509 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9510 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9511 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9516 tlbl = newiTempLabel(NULL);
9519 /* this is already done, why change it? */
9520 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9521 pic16_mov2f(AOP(result), AOP(left), 0);
9525 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9526 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9527 pic16_emitpLabel(tlbl->key);
9528 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9529 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9531 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9536 if (pic16_sameRegs(AOP(left),AOP(result))) {
9538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9540 tlbl = newiTempLabel(NULL);
9541 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9542 genMultiAsm(POC_RRCF, result, size,1);
9543 pic16_emitpLabel(tlbl->key);
9544 genMultiAsm(POC_RLCF, result, size,0);
9545 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9547 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9551 //tlbl = newiTempLabel(NULL);
9553 //tlbl1 = newiTempLabel(NULL);
9555 //reAdjustPreg(AOP(result));
9557 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9558 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9559 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9561 //pic16_emitcode("add","a,acc");
9562 //pic16_aopPut(AOP(result),"a",offset++);
9564 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9566 // pic16_emitcode("rlc","a");
9567 // pic16_aopPut(AOP(result),"a",offset++);
9569 //reAdjustPreg(AOP(result));
9571 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9572 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9575 tlbl = newiTempLabel(NULL);
9576 tlbl1= newiTempLabel(NULL);
9578 size = AOP_SIZE(result);
9581 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9583 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9585 /* offset should be 0, 1 or 3 */
9587 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9589 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9591 pic16_emitpcode(POC_MOVWF, pctemp);
9594 pic16_emitpLabel(tlbl->key);
9597 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9599 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9601 pic16_emitpcode(POC_DECFSZ, pctemp);
9602 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9603 pic16_emitpLabel(tlbl1->key);
9605 pic16_popReleaseTempReg(pctemp,1);
9609 pic16_freeAsmop (right,NULL,ic,TRUE);
9610 pic16_freeAsmop(left,NULL,ic,TRUE);
9611 pic16_freeAsmop(result,NULL,ic,TRUE);
9617 #error old code (left here for reference)
9618 /*-----------------------------------------------------------------*/
9619 /* genLeftShift - generates code for left shifting */
9620 /*-----------------------------------------------------------------*/
9621 static void genLeftShift (iCode *ic)
9623 operand *left,*right, *result;
9626 symbol *tlbl , *tlbl1;
9629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9631 right = IC_RIGHT(ic);
9633 result = IC_RESULT(ic);
9635 pic16_aopOp(right,ic,FALSE);
9637 /* if the shift count is known then do it
9638 as efficiently as possible */
9639 if (AOP_TYPE(right) == AOP_LIT) {
9640 pic16_genLeftShiftLiteral (left,right,result,ic);
9644 /* shift count is unknown then we have to form
9645 a loop get the loop count in B : Note: we take
9646 only the lower order byte since shifting
9647 more that 32 bits make no sense anyway, ( the
9648 largest size of an object can be only 32 bits ) */
9651 pic16_aopOp(left,ic,FALSE);
9652 pic16_aopOp(result,ic,FALSE);
9654 /* now move the left to the result if they are not the
9656 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9657 AOP_SIZE(result) > 1) {
9659 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9661 size = AOP_SIZE(result);
9664 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9665 if (*l == '@' && (IS_AOP_PREG(result))) {
9667 pic16_emitcode("mov","a,%s",l);
9668 pic16_aopPut(AOP(result),"a",offset);
9671 /* we don't know if left is a literal or a register, take care -- VR */
9672 pic16_mov2f(AOP(result), AOP(left), offset);
9678 size = AOP_SIZE(result);
9680 /* if it is only one byte then */
9682 if(optimized_for_speed) {
9683 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9684 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9685 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9686 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9688 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9689 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9690 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9691 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9692 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9693 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9694 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9699 tlbl = newiTempLabel(NULL);
9700 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9701 pic16_mov2f(AOP(result), AOP(left), 0);
9703 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9704 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9707 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9708 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9709 pic16_emitpLabel(tlbl->key);
9710 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9711 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9713 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9718 if (pic16_sameRegs(AOP(left),AOP(result))) {
9720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9722 tlbl = newiTempLabel(NULL);
9723 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9724 genMultiAsm(POC_RRCF, result, size,1);
9725 pic16_emitpLabel(tlbl->key);
9726 genMultiAsm(POC_RLCF, result, size,0);
9727 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9733 //tlbl = newiTempLabel(NULL);
9735 //tlbl1 = newiTempLabel(NULL);
9737 //reAdjustPreg(AOP(result));
9739 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9740 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9741 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9743 //pic16_emitcode("add","a,acc");
9744 //pic16_aopPut(AOP(result),"a",offset++);
9746 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9748 // pic16_emitcode("rlc","a");
9749 // pic16_aopPut(AOP(result),"a",offset++);
9751 //reAdjustPreg(AOP(result));
9753 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9754 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9757 tlbl = newiTempLabel(NULL);
9758 tlbl1= newiTempLabel(NULL);
9760 size = AOP_SIZE(result);
9763 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9765 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9767 /* offset should be 0, 1 or 3 */
9769 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9771 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9773 pic16_emitpcode(POC_MOVWF, pctemp);
9776 pic16_emitpLabel(tlbl->key);
9779 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9781 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9783 pic16_emitpcode(POC_DECFSZ, pctemp);
9784 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9785 pic16_emitpLabel(tlbl1->key);
9787 pic16_popReleaseTempReg(pctemp,1);
9791 pic16_freeAsmop (right,NULL,ic,TRUE);
9792 pic16_freeAsmop(left,NULL,ic,TRUE);
9793 pic16_freeAsmop(result,NULL,ic,TRUE);
9797 /*-----------------------------------------------------------------*/
9798 /* genrshOne - right shift a one byte quantity by known count */
9799 /*-----------------------------------------------------------------*/
9800 static void genrshOne (operand *result, operand *left,
9801 int shCount, int sign)
9803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9804 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9807 /*-----------------------------------------------------------------*/
9808 /* genrshTwo - right shift two bytes by known amount != 0 */
9809 /*-----------------------------------------------------------------*/
9810 static void genrshTwo (operand *result,operand *left,
9811 int shCount, int sign)
9813 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9814 /* if shCount >= 8 */
9818 shiftR1Left2Result(left, MSB16, result, LSB,
9821 movLeft2Result(left, MSB16, result, LSB);
9823 pic16_addSign (result, 1, sign);
9826 /* 1 <= shCount <= 7 */
9828 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9831 /*-----------------------------------------------------------------*/
9832 /* shiftRLong - shift right one long from left to result */
9833 /* offl = LSB or MSB16 */
9834 /*-----------------------------------------------------------------*/
9835 static void shiftRLong (operand *left, int offl,
9836 operand *result, int sign)
9838 int size = AOP_SIZE(result);
9839 int same = pic16_sameRegs(AOP(left),AOP(result));
9841 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9843 if (same && (offl == MSB16)) { //shift one byte right
9844 for(i=MSB16;i<size;i++) {
9845 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9846 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9851 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9857 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9859 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9864 /* add sign of "a" */
9865 pic16_addSign(result, MSB32, sign);
9869 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9871 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9876 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9878 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9879 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9883 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9886 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9887 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9892 /*-----------------------------------------------------------------*/
9893 /* genrshFour - shift four byte by a known amount != 0 */
9894 /*-----------------------------------------------------------------*/
9895 static void genrshFour (operand *result, operand *left,
9896 int shCount, int sign)
9898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9899 /* if shifting more that 3 bytes */
9900 if(shCount >= 24 ) {
9903 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9905 movLeft2Result(left, MSB32, result, LSB);
9907 pic16_addSign(result, MSB16, sign);
9909 else if(shCount >= 16){
9912 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9914 movLeft2Result(left, MSB24, result, LSB);
9915 movLeft2Result(left, MSB32, result, MSB16);
9917 pic16_addSign(result, MSB24, sign);
9919 else if(shCount >= 8){
9922 shiftRLong(left, MSB16, result, sign);
9923 else if(shCount == 0){
9924 movLeft2Result(left, MSB16, result, LSB);
9925 movLeft2Result(left, MSB24, result, MSB16);
9926 movLeft2Result(left, MSB32, result, MSB24);
9927 pic16_addSign(result, MSB32, sign);
9929 else{ //shcount >= 2
9930 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9931 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9932 /* the last shift is signed */
9933 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9934 pic16_addSign(result, MSB32, sign);
9937 else{ /* 1 <= shCount <= 7 */
9939 shiftRLong(left, LSB, result, sign);
9941 shiftRLong(result, LSB, result, sign);
9944 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9945 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9946 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9951 /*-----------------------------------------------------------------*/
9952 /* genRightShiftLiteral - right shifting by known count */
9953 /*-----------------------------------------------------------------*/
9954 static void genRightShiftLiteral (operand *left,
9960 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9963 pic16_freeAsmop(right,NULL,ic,TRUE);
9965 pic16_aopOp(left,ic,FALSE);
9966 pic16_aopOp(result,ic,TRUE);
9968 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9971 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9975 lsize = pic16_getDataSize(left);
9976 res_size = pic16_getDataSize(result);
9977 /* test the LEFT size !!! */
9979 /* I suppose that the left size >= result size */
9981 assert (res_size <= lsize);
9982 while (res_size--) {
9983 pic16_mov2f (AOP(result), AOP(left), res_size);
9987 else if(shCount >= (lsize * 8)){
9990 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9992 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9993 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9998 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9999 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10000 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10007 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10012 switch (res_size) {
10014 genrshOne (result,left,shCount,sign);
10018 genrshTwo (result,left,shCount,sign);
10022 genrshFour (result,left,shCount,sign);
10030 pic16_freeAsmop(left,NULL,ic,TRUE);
10031 pic16_freeAsmop(result,NULL,ic,TRUE);
10034 #if !(USE_GENERIC_SIGNED_SHIFT)
10035 /*-----------------------------------------------------------------*/
10036 /* genSignedRightShift - right shift of signed number */
10037 /*-----------------------------------------------------------------*/
10038 static void genSignedRightShift (iCode *ic)
10040 operand *right, *left, *result;
10043 symbol *tlbl, *tlbl1 ;
10046 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10048 /* we do it the hard way put the shift count in b
10049 and loop thru preserving the sign */
10050 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10052 right = IC_RIGHT(ic);
10053 left = IC_LEFT(ic);
10054 result = IC_RESULT(ic);
10056 pic16_aopOp(right,ic,FALSE);
10057 pic16_aopOp(left,ic,FALSE);
10058 pic16_aopOp(result,ic,FALSE);
10061 if ( AOP_TYPE(right) == AOP_LIT) {
10062 genRightShiftLiteral (left,right,result,ic,1);
10065 /* shift count is unknown then we have to form
10066 a loop get the loop count in B : Note: we take
10067 only the lower order byte since shifting
10068 more that 32 bits make no sense anyway, ( the
10069 largest size of an object can be only 32 bits ) */
10071 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10072 //pic16_emitcode("inc","b");
10073 //pic16_freeAsmop (right,NULL,ic,TRUE);
10074 //pic16_aopOp(left,ic,FALSE);
10075 //pic16_aopOp(result,ic,FALSE);
10077 /* now move the left to the result if they are not the
10079 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10080 AOP_SIZE(result) > 1) {
10082 size = AOP_SIZE(result);
10086 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10087 if (*l == '@' && IS_AOP_PREG(result)) {
10089 pic16_emitcode("mov","a,%s",l);
10090 pic16_aopPut(AOP(result),"a",offset);
10092 pic16_aopPut(AOP(result),l,offset);
10094 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10095 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10101 /* mov the highest order bit to OVR */
10102 tlbl = newiTempLabel(NULL);
10103 tlbl1= newiTempLabel(NULL);
10105 size = AOP_SIZE(result);
10108 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10110 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10112 /* offset should be 0, 1 or 3 */
10113 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10115 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10117 pic16_emitpcode(POC_MOVWF, pctemp);
10120 pic16_emitpLabel(tlbl->key);
10122 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10123 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10126 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10129 pic16_emitpcode(POC_DECFSZ, pctemp);
10130 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10131 pic16_emitpLabel(tlbl1->key);
10133 pic16_popReleaseTempReg(pctemp,1);
10135 size = AOP_SIZE(result);
10137 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10138 pic16_emitcode("rlc","a");
10139 pic16_emitcode("mov","ov,c");
10140 /* if it is only one byte then */
10142 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10144 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10145 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10146 pic16_emitcode("mov","c,ov");
10147 pic16_emitcode("rrc","a");
10148 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10149 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10150 pic16_aopPut(AOP(result),"a",0);
10154 reAdjustPreg(AOP(result));
10155 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10156 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10157 pic16_emitcode("mov","c,ov");
10159 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10161 pic16_emitcode("rrc","a");
10162 pic16_aopPut(AOP(result),"a",offset--);
10164 reAdjustPreg(AOP(result));
10165 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10166 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10171 pic16_freeAsmop(left,NULL,ic,TRUE);
10172 pic16_freeAsmop(result,NULL,ic,TRUE);
10173 pic16_freeAsmop(right,NULL,ic,TRUE);
10177 #if !(USE_GENERIC_SIGNED_SHIFT)
10178 #warning This implementation of genRightShift() is incomplete!
10179 /*-----------------------------------------------------------------*/
10180 /* genRightShift - generate code for right shifting */
10181 /*-----------------------------------------------------------------*/
10182 static void genRightShift (iCode *ic)
10184 operand *right, *left, *result;
10188 symbol *tlbl, *tlbl1 ;
10190 /* if signed then we do it the hard way preserve the
10191 sign bit moving it inwards */
10192 letype = getSpec(operandType(IC_LEFT(ic)));
10193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10195 if (!SPEC_USIGN(letype)) {
10196 genSignedRightShift (ic);
10200 /* signed & unsigned types are treated the same : i.e. the
10201 signed is NOT propagated inwards : quoting from the
10202 ANSI - standard : "for E1 >> E2, is equivalent to division
10203 by 2**E2 if unsigned or if it has a non-negative value,
10204 otherwise the result is implementation defined ", MY definition
10205 is that the sign does not get propagated */
10207 right = IC_RIGHT(ic);
10208 left = IC_LEFT(ic);
10209 result = IC_RESULT(ic);
10211 pic16_aopOp(right,ic,FALSE);
10213 /* if the shift count is known then do it
10214 as efficiently as possible */
10215 if (AOP_TYPE(right) == AOP_LIT) {
10216 genRightShiftLiteral (left,right,result,ic, 0);
10220 /* shift count is unknown then we have to form
10221 a loop get the loop count in B : Note: we take
10222 only the lower order byte since shifting
10223 more that 32 bits make no sense anyway, ( the
10224 largest size of an object can be only 32 bits ) */
10226 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10227 pic16_emitcode("inc","b");
10228 pic16_aopOp(left,ic,FALSE);
10229 pic16_aopOp(result,ic,FALSE);
10231 /* now move the left to the result if they are not the
10233 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10234 AOP_SIZE(result) > 1) {
10236 size = AOP_SIZE(result);
10239 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10240 if (*l == '@' && IS_AOP_PREG(result)) {
10242 pic16_emitcode("mov","a,%s",l);
10243 pic16_aopPut(AOP(result),"a",offset);
10245 pic16_aopPut(AOP(result),l,offset);
10250 tlbl = newiTempLabel(NULL);
10251 tlbl1= newiTempLabel(NULL);
10252 size = AOP_SIZE(result);
10255 /* if it is only one byte then */
10258 tlbl = newiTempLabel(NULL);
10259 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10260 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10264 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10265 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10266 pic16_emitpLabel(tlbl->key);
10267 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10268 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10270 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10275 reAdjustPreg(AOP(result));
10276 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10277 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10280 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10282 pic16_emitcode("rrc","a");
10283 pic16_aopPut(AOP(result),"a",offset--);
10285 reAdjustPreg(AOP(result));
10287 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10288 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10291 pic16_freeAsmop(left,NULL,ic,TRUE);
10292 pic16_freeAsmop (right,NULL,ic,TRUE);
10293 pic16_freeAsmop(result,NULL,ic,TRUE);
10297 #if (USE_GENERIC_SIGNED_SHIFT)
10298 /*-----------------------------------------------------------------*/
10299 /* genGenericShift - generates code for left or right shifting */
10300 /*-----------------------------------------------------------------*/
10301 static void genGenericShift (iCode *ic, int isShiftLeft) {
10302 operand *left,*right, *result;
10304 int sign, signedCount;
10305 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10306 PIC_OPCODE pos_shift, neg_shift;
10310 right = IC_RIGHT(ic);
10311 left = IC_LEFT(ic);
10312 result = IC_RESULT(ic);
10314 pic16_aopOp(right,ic,FALSE);
10315 pic16_aopOp(left,ic,FALSE);
10316 pic16_aopOp(result,ic,TRUE);
10318 sign = !SPEC_USIGN(operandType (left));
10319 signedCount = !SPEC_USIGN(operandType (right));
10321 /* if the shift count is known then do it
10322 as efficiently as possible */
10323 if (AOP_TYPE(right) == AOP_LIT) {
10324 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10325 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10326 // we should modify right->aopu.aop_lit here!
10327 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10328 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10330 pic16_genLeftShiftLiteral (left,right,result,ic);
10332 genRightShiftLiteral (left,right,result,ic, sign);
10335 } // if (right is literal)
10337 /* shift count is unknown then we have to form a loop.
10338 * Note: we take only the lower order byte since shifting
10339 * more than 32 bits make no sense anyway, ( the
10340 * largest size of an object can be only 32 bits )
10341 * Note: we perform arithmetic shifts if the left operand is
10342 * signed and we do an (effective) right shift, i. e. we
10343 * shift in the sign bit from the left. */
10345 label_complete = newiTempLabel ( NULL );
10346 label_loop_pos = newiTempLabel ( NULL );
10347 label_loop_neg = NULL;
10348 label_negative = NULL;
10349 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10350 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10353 // additional labels needed
10354 label_loop_neg = newiTempLabel ( NULL );
10355 label_negative = newiTempLabel ( NULL );
10358 // copy source to result -- this will effectively truncate the left operand to the size of result!
10359 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10360 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10361 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10362 pic16_mov2f (AOP(result),AOP(left), offset);
10365 // if result is longer than left, fill with zeros (or sign)
10366 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10367 if (sign && AOP_SIZE(left) > 0) {
10368 // shift signed operand -- fill with sign
10369 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10370 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10371 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10372 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10373 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10376 // shift unsigned operand -- fill result with zeros
10377 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10378 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10381 } // if (size mismatch)
10383 pic16_mov2w (AOP(right), 0);
10384 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10385 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10388 // perform a shift by one (shift count is positive)
10389 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10390 // 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])
10391 pic16_emitpLabel (label_loop_pos->key);
10393 if (sign && (pos_shift == POC_RRCF)) {
10394 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10397 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10398 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10399 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10401 // perform a shift by one (shift count is positive)
10402 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10403 // 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])
10404 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10405 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10407 pic16_emitpLabel (label_loop_pos->key);
10408 if (sign && (pos_shift == POC_RRCF)) {
10409 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10412 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10413 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10414 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10415 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10419 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10421 pic16_emitpLabel (label_negative->key);
10422 // perform a shift by -1 (shift count is negative)
10423 // 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)
10425 pic16_emitpLabel (label_loop_neg->key);
10426 if (sign && (neg_shift == POC_RRCF)) {
10427 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10430 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10431 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10432 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10433 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10434 } // if (signedCount)
10436 pic16_emitpLabel (label_complete->key);
10439 pic16_freeAsmop (right,NULL,ic,TRUE);
10440 pic16_freeAsmop(left,NULL,ic,TRUE);
10441 pic16_freeAsmop(result,NULL,ic,TRUE);
10444 static void genLeftShift (iCode *ic) {
10445 genGenericShift (ic, 1);
10448 static void genRightShift (iCode *ic) {
10449 genGenericShift (ic, 0);
10454 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10455 void pic16_loadFSR0(operand *op, int lit)
10457 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10458 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10460 assert (!OP_SYMBOL(op)->remat);
10461 // set up FSR0 with address of result
10462 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10463 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10467 /*----------------------------------------------------------------*/
10468 /* pic16_derefPtr - move one byte from the location ptr points to */
10469 /* to WREG (doWrite == 0) or one byte from WREG */
10470 /* to the location ptr points to (doWrite != 0) */
10471 /*----------------------------------------------------------------*/
10472 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10474 if (!IS_PTR(operandType(ptr)))
10476 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10477 else pic16_mov2w (AOP(ptr), 0);
10481 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10482 /* We might determine pointer type right here: */
10483 p_type = DCL_TYPE(operandType(ptr));
10488 if (!fsr0_setup || !*fsr0_setup)
10490 pic16_loadFSR0( ptr, 0 );
10491 if (fsr0_setup) *fsr0_setup = 1;
10494 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10496 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10500 if (AOP(ptr)->aopu.aop_reg[2]) {
10501 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10502 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10503 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10504 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10505 pic16_mov2w(AOP(ptr), 2);
10506 pic16_callGenericPointerRW(doWrite, 1);
10508 // data pointer (just 2 byte given)
10509 if (!fsr0_setup || !*fsr0_setup)
10511 pic16_loadFSR0( ptr, 0 );
10512 if (fsr0_setup) *fsr0_setup = 1;
10515 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10517 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10522 assert (0 && "invalid pointer type specified");
10527 /*-----------------------------------------------------------------*/
10528 /* genUnpackBits - generates code for unpacking bits */
10529 /*-----------------------------------------------------------------*/
10530 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10533 sym_link *etype, *letype;
10534 int blen=0, bstr=0;
10539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10540 etype = getSpec(operandType(result));
10541 letype = getSpec(operandType(left));
10543 // if(IS_BITFIELD(etype)) {
10544 blen = SPEC_BLEN(etype);
10545 bstr = SPEC_BSTR(etype);
10548 lbstr = SPEC_BSTR( letype );
10550 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10551 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10554 if((blen == 1) && (bstr < 8)
10555 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10556 /* it is a single bit, so use the appropriate bit instructions */
10557 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10559 same = pic16_sameRegs(AOP(left),AOP(result));
10560 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10561 pic16_emitpcode(POC_CLRF, op);
10563 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10564 /* workaround to reduce the extra lfsr instruction */
10565 pic16_emitpcode(POC_BTFSC,
10566 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10568 assert (PIC_IS_DATA_PTR (operandType(left)));
10569 pic16_loadFSR0 (left, 0);
10570 pic16_emitpcode(POC_BTFSC,
10571 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10574 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10575 /* unsigned bitfields result in either 0 or 1 */
10576 pic16_emitpcode(POC_INCF, op);
10578 /* signed bitfields result in either 0 or -1 */
10579 pic16_emitpcode(POC_DECF, op);
10582 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10585 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10591 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10592 // access symbol directly
10593 pic16_mov2w (AOP(left), 0);
10595 pic16_derefPtr (left, ptype, 0, NULL);
10598 /* if we have bitdisplacement then it fits */
10599 /* into this byte completely or if length is */
10600 /* less than a byte */
10601 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10603 /* shift right acc */
10606 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10607 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10609 /* VR -- normally I would use the following, but since we use the hack,
10610 * to avoid the masking from AccRsh, why not mask it right now? */
10613 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10616 /* extend signed bitfields to 8 bits */
10617 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10619 assert (blen + bstr > 0);
10620 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10621 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10626 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10630 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10631 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10638 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10640 int size, offset = 0, leoffset=0 ;
10642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10643 pic16_aopOp(result, ic, TRUE);
10647 size = AOP_SIZE(result);
10648 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10652 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10653 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10654 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10659 if(AOP(left)->aopu.pcop->type == PO_DIR)
10660 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10662 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10665 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10667 // pic16_DumpOp("(result)",result);
10668 if(is_LitAOp(AOP(result))) {
10669 pic16_mov2w(AOP(left), offset); // patch 8
10670 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10672 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10673 pic16_popGet(AOP(left), offset), //patch 8
10674 pic16_popGet(AOP(result), offset)));
10682 pic16_freeAsmop(result,NULL,ic,TRUE);
10687 /*-----------------------------------------------------------------*/
10688 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10689 /*-----------------------------------------------------------------*/
10690 static void genNearPointerGet (operand *left,
10694 // asmop *aop = NULL;
10695 //regs *preg = NULL ;
10696 sym_link *rtype, *retype;
10697 sym_link *ltype, *letype;
10701 rtype = operandType(result);
10702 retype= getSpec(rtype);
10703 ltype = operandType(left);
10704 letype= getSpec(ltype);
10706 pic16_aopOp(left,ic,FALSE);
10708 // pic16_DumpOp("(left)",left);
10709 // pic16_DumpOp("(result)",result);
10711 /* if left is rematerialisable and
10712 * result is not bit variable type and
10713 * the left is pointer to data space i.e
10714 * lower 128 bytes of space */
10716 if (AOP_TYPE(left) == AOP_PCODE
10717 && !IS_BITFIELD(retype)
10718 && DCL_TYPE(ltype) == POINTER) {
10720 genDataPointerGet (left,result,ic);
10721 pic16_freeAsmop(left, NULL, ic, TRUE);
10725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10726 pic16_aopOp (result,ic,TRUE);
10728 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10731 if(IS_BITFIELD( retype )
10732 && (SPEC_BLEN(operandType(result))==1)
10736 int bitstrt, bytestrt;
10738 /* if this is bitfield of size 1, see if we are checking the value
10739 * of a single bit in an if-statement,
10740 * if yes, then don't generate usual code, but execute the
10741 * genIfx directly -- VR */
10745 /* CHECK: if next iCode is IFX
10746 * and current result operand is nextic's conditional operand
10747 * and current result operand live ranges ends at nextic's key number
10749 if((nextic->op == IFX)
10750 && (result == IC_COND(nextic))
10751 && (OP_LIVETO(result) == nextic->seq)
10752 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10754 /* everything is ok then */
10755 /* find a way to optimize the genIfx iCode */
10757 bytestrt = SPEC_BSTR(operandType(result))/8;
10758 bitstrt = SPEC_BSTR(operandType(result))%8;
10760 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10762 genIfxpCOpJump(nextic, jop);
10764 pic16_freeAsmop(left, NULL, ic, TRUE);
10765 pic16_freeAsmop(result, NULL, ic, TRUE);
10771 /* if bitfield then unpack the bits */
10772 if (IS_BITFIELD(letype))
10773 genUnpackBits (result, left, NULL, POINTER);
10775 /* we have can just get the values */
10776 int size = AOP_SIZE(result);
10779 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10781 pic16_loadFSR0( left, 0 );
10785 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10786 pic16_popGet(AOP(result), offset++)));
10788 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10789 pic16_popGet(AOP(result), offset++)));
10795 /* now some housekeeping stuff */
10797 /* we had to allocate for this iCode */
10798 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10799 pic16_freeAsmop(NULL,aop,ic,TRUE);
10801 /* we did not allocate which means left
10802 * already in a pointer register, then
10803 * if size > 0 && this could be used again
10804 * we have to point it back to where it
10806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10807 if (AOP_SIZE(result) > 1
10808 && !OP_SYMBOL(left)->remat
10809 && ( OP_SYMBOL(left)->liveTo > ic->seq
10811 // int size = AOP_SIZE(result) - 1;
10813 // pic16_emitcode("dec","%s",rname);
10819 pic16_freeAsmop(left,NULL,ic,TRUE);
10820 pic16_freeAsmop(result,NULL,ic,TRUE);
10823 /*-----------------------------------------------------------------*/
10824 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10825 /*-----------------------------------------------------------------*/
10826 static void genPagedPointerGet (operand *left,
10831 regs *preg = NULL ;
10833 sym_link *rtype, *retype;
10835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10837 rtype = operandType(result);
10838 retype= getSpec(rtype);
10840 pic16_aopOp(left,ic,FALSE);
10842 /* if the value is already in a pointer register
10843 then don't need anything more */
10844 if (!AOP_INPREG(AOP(left))) {
10845 /* otherwise get a free pointer register */
10847 preg = getFreePtr(ic,&aop,FALSE);
10848 pic16_emitcode("mov","%s,%s",
10850 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10851 rname = preg->name ;
10853 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10855 pic16_freeAsmop(left,NULL,ic,TRUE);
10856 pic16_aopOp (result,ic,TRUE);
10858 /* if bitfield then unpack the bits */
10859 if (IS_BITFIELD(retype))
10860 genUnpackBits (result,left,rname,PPOINTER);
10862 /* we have can just get the values */
10863 int size = AOP_SIZE(result);
10868 pic16_emitcode("movx","a,@%s",rname);
10869 pic16_aopPut(AOP(result),"a",offset);
10874 pic16_emitcode("inc","%s",rname);
10878 /* now some housekeeping stuff */
10880 /* we had to allocate for this iCode */
10881 pic16_freeAsmop(NULL,aop,ic,TRUE);
10883 /* we did not allocate which means left
10884 already in a pointer register, then
10885 if size > 0 && this could be used again
10886 we have to point it back to where it
10888 if (AOP_SIZE(result) > 1 &&
10889 !OP_SYMBOL(left)->remat &&
10890 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10892 int size = AOP_SIZE(result) - 1;
10894 pic16_emitcode("dec","%s",rname);
10899 pic16_freeAsmop(result,NULL,ic,TRUE);
10905 /* This code is not adjusted to PIC16 and fails utterly.
10906 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10908 /*-----------------------------------------------------------------*/
10909 /* genFarPointerGet - gget value from far space */
10910 /*-----------------------------------------------------------------*/
10911 static void genFarPointerGet (operand *left,
10912 operand *result, iCode *ic)
10915 sym_link *retype = getSpec(operandType(result));
10917 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10919 pic16_aopOp(left,ic,FALSE);
10921 /* if the operand is already in dptr
10922 then we do nothing else we move the value to dptr */
10923 if (AOP_TYPE(left) != AOP_STR) {
10924 /* if this is remateriazable */
10925 if (AOP_TYPE(left) == AOP_IMMD)
10926 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10927 else { /* we need to get it byte by byte */
10928 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10929 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10930 if (options.model == MODEL_FLAT24)
10932 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10936 /* so dptr know contains the address */
10937 pic16_freeAsmop(left,NULL,ic,TRUE);
10938 pic16_aopOp(result,ic,TRUE);
10940 /* if bit then unpack */
10941 if (IS_BITFIELD(retype))
10942 genUnpackBits(result,left,"dptr",FPOINTER);
10944 size = AOP_SIZE(result);
10948 pic16_emitcode("movx","a,@dptr");
10949 pic16_aopPut(AOP(result),"a",offset++);
10951 pic16_emitcode("inc","dptr");
10955 pic16_freeAsmop(result,NULL,ic,TRUE);
10960 /*-----------------------------------------------------------------*/
10961 /* genCodePointerGet - get value from code space */
10962 /*-----------------------------------------------------------------*/
10963 static void genCodePointerGet (operand *left,
10964 operand *result, iCode *ic)
10967 sym_link *retype = getSpec(operandType(result));
10969 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10971 pic16_aopOp(left,ic,FALSE);
10973 /* if the operand is already in dptr
10974 then we do nothing else we move the value to dptr */
10975 if (AOP_TYPE(left) != AOP_STR) {
10976 /* if this is remateriazable */
10977 if (AOP_TYPE(left) == AOP_IMMD)
10978 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10979 else { /* we need to get it byte by byte */
10980 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10981 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10982 if (options.model == MODEL_FLAT24)
10984 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10988 /* so dptr know contains the address */
10989 pic16_freeAsmop(left,NULL,ic,TRUE);
10990 pic16_aopOp(result,ic,FALSE);
10992 /* if bit then unpack */
10993 if (IS_BITFIELD(retype))
10994 genUnpackBits(result,left,"dptr",CPOINTER);
10996 size = AOP_SIZE(result);
11000 pic16_emitcode("clr","a");
11001 pic16_emitcode("movc","a,@a+dptr");
11002 pic16_aopPut(AOP(result),"a",offset++);
11004 pic16_emitcode("inc","dptr");
11008 pic16_freeAsmop(result,NULL,ic,TRUE);
11013 /*-----------------------------------------------------------------*/
11014 /* genGenPointerGet - gget value from generic pointer space */
11015 /*-----------------------------------------------------------------*/
11016 static void genGenPointerGet (operand *left,
11017 operand *result, iCode *ic)
11019 int size, offset, lit;
11020 sym_link *retype = getSpec(operandType(result));
11022 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11023 pic16_aopOp(left,ic,FALSE);
11024 pic16_aopOp(result,ic,FALSE);
11025 size = AOP_SIZE(result);
11027 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11029 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11031 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11032 // load FSR0 from immediate
11033 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11035 // pic16_loadFSR0( left );
11040 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11042 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11049 else { /* we need to get it byte by byte */
11050 // set up FSR0 with address from left
11051 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11052 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11058 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11060 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11067 /* if bit then unpack */
11068 if (IS_BITFIELD(retype))
11069 genUnpackBits(result,left,"BAD",GPOINTER);
11072 pic16_freeAsmop(left,NULL,ic,TRUE);
11073 pic16_freeAsmop(result,NULL,ic,TRUE);
11079 /*-----------------------------------------------------------------*/
11080 /* genGenPointerGet - gget value from generic pointer space */
11081 /*-----------------------------------------------------------------*/
11082 static void genGenPointerGet (operand *left,
11083 operand *result, iCode *ic)
11085 int size, offset, lit;
11086 sym_link *letype = getSpec(operandType(left));
11088 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11089 pic16_aopOp(left,ic,FALSE);
11090 pic16_aopOp(result,ic,TRUE);
11091 size = AOP_SIZE(result);
11093 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11095 /* if bit then unpack */
11096 if (IS_BITFIELD(letype)) {
11097 genUnpackBits(result,left,"BAD",GPOINTER);
11101 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11103 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11104 // load FSR0 from immediate
11105 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11107 werror(W_POSSBUG2, __FILE__, __LINE__);
11112 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11114 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11121 } else { /* we need to get it byte by byte */
11123 /* set up WREG:PRODL:FSR0L with address from left */
11124 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11125 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11126 pic16_mov2w(AOP(left), 2);
11127 pic16_callGenericPointerRW(0, size);
11129 assignResultValue(result, 1);
11135 pic16_freeAsmop(left,NULL,ic,TRUE);
11136 pic16_freeAsmop(result,NULL,ic,TRUE);
11139 /*-----------------------------------------------------------------*/
11140 /* genConstPointerGet - get value from const generic pointer space */
11141 /*-----------------------------------------------------------------*/
11142 static void genConstPointerGet (operand *left,
11143 operand *result, iCode *ic)
11145 //sym_link *retype = getSpec(operandType(result));
11146 // symbol *albl = newiTempLabel(NULL); // patch 15
11147 // symbol *blbl = newiTempLabel(NULL); //
11148 // PIC_OPCODE poc; // patch 15
11152 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11153 pic16_aopOp(left,ic,FALSE);
11154 pic16_aopOp(result,ic,TRUE);
11155 size = AOP_SIZE(result);
11157 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11159 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11161 // set up table pointer
11162 if( (AOP_TYPE(left) == AOP_PCODE)
11163 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11164 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11166 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11167 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11168 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11169 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11170 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11171 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11173 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11174 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11175 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11179 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11180 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11184 pic16_freeAsmop(left,NULL,ic,TRUE);
11185 pic16_freeAsmop(result,NULL,ic,TRUE);
11189 /*-----------------------------------------------------------------*/
11190 /* genPointerGet - generate code for pointer get */
11191 /*-----------------------------------------------------------------*/
11192 static void genPointerGet (iCode *ic)
11194 operand *left, *result ;
11195 sym_link *type, *etype;
11200 left = IC_LEFT(ic);
11201 result = IC_RESULT(ic) ;
11203 /* depending on the type of pointer we need to
11204 move it to the correct pointer register */
11205 type = operandType(left);
11206 etype = getSpec(type);
11209 if (IS_PTR_CONST(type))
11211 if (IS_CODEPTR(type))
11213 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11215 /* if left is of type of pointer then it is simple */
11216 if (IS_PTR(type) && !IS_FUNC(type->next))
11217 p_type = DCL_TYPE(type);
11219 /* we have to go by the storage class */
11220 p_type = PTR_TYPE(SPEC_OCLS(etype));
11222 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11224 if (SPEC_OCLS(etype)->codesp ) {
11225 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11226 //p_type = CPOINTER ;
11228 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11229 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11230 /*p_type = FPOINTER ;*/
11232 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11233 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11234 /* p_type = PPOINTER; */
11236 if (SPEC_OCLS(etype) == idata ) {
11237 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11238 /* p_type = IPOINTER; */
11240 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11241 /* p_type = POINTER ; */
11245 /* now that we have the pointer type we assign
11246 the pointer values */
11251 genNearPointerGet (left,result,ic);
11255 genPagedPointerGet(left,result,ic);
11259 /* PICs do not support FAR pointers... */
11260 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11262 genFarPointerGet (left,result,ic);
11267 genConstPointerGet (left,result,ic);
11268 //pic16_emitcodePointerGet (left,result,ic);
11273 if (IS_PTR_CONST(type))
11274 genConstPointerGet (left,result,ic);
11277 genGenPointerGet (left,result,ic);
11281 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11282 "genPointerGet: illegal pointer type");
11287 /*-----------------------------------------------------------------*/
11288 /* genPackBits - generates code for packed bit storage */
11289 /*-----------------------------------------------------------------*/
11290 static void genPackBits (sym_link *etype , operand *result,
11292 char *rname, int p_type)
11298 int shifted_and_masked = 0;
11299 unsigned long lit = (unsigned long)-1;
11302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11303 blen = SPEC_BLEN(etype);
11304 bstr = SPEC_BSTR(etype);
11306 retype = getSpec(operandType(right));
11308 if(AOP_TYPE(right) == AOP_LIT) {
11309 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11311 if((blen == 1) && (bstr < 8)) {
11312 /* it is a single bit, so use the appropriate bit instructions */
11314 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11316 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11317 /* workaround to reduce the extra lfsr instruction */
11319 pic16_emitpcode(POC_BSF,
11320 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11322 pic16_emitpcode(POC_BCF,
11323 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11326 if (PIC_IS_DATA_PTR(operandType(result))) {
11327 pic16_loadFSR0(result, 0);
11328 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11329 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11331 /* get old value */
11332 pic16_derefPtr (result, p_type, 0, NULL);
11333 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11334 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11335 /* write back new value */
11336 pic16_derefPtr (result, p_type, 1, NULL);
11342 /* IORLW below is more efficient */
11343 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11344 lit = (lit & ((1UL << blen) - 1)) << bstr;
11345 shifted_and_masked = 1;
11348 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11349 && IS_BITFIELD(retype)
11350 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11354 rblen = SPEC_BLEN( retype );
11355 rbstr = SPEC_BSTR( retype );
11357 if(IS_BITFIELD(etype)) {
11358 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11359 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11361 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11364 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11366 if(IS_BITFIELD(etype)) {
11367 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11369 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11372 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11376 /* move right to W */
11377 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11380 /* if the bit length is less than or */
11381 /* it exactly fits a byte then */
11382 if((shCnt=SPEC_BSTR(etype))
11383 || SPEC_BLEN(etype) <= 8 ) {
11384 int fsr0_setup = 0;
11386 if (blen != 8 || bstr != 0) {
11387 // we need to combine the value with the old value
11388 if(!shifted_and_masked)
11390 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11392 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11393 SPEC_BSTR(etype), SPEC_BLEN(etype));
11395 /* shift left acc, do NOT mask the result again */
11398 /* using PRODH as a temporary register here */
11399 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11402 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11403 || IS_DIRECT(result)) {
11404 /* access symbol directly */
11405 pic16_mov2w (AOP(result), 0);
11407 /* get old value */
11408 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11411 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11412 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11413 (unsigned char)(0xff >> (8-bstr))) ));
11414 if (!shifted_and_masked) {
11415 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11417 /* We have the shifted and masked (literal) right value in `lit' */
11419 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11421 } // if (blen != 8 || bstr != 0)
11423 /* write new value back */
11424 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11425 || IS_DIRECT(result)) {
11426 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11428 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11437 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11438 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11443 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11444 rLen = SPEC_BLEN(etype)-8;
11446 /* now generate for lengths greater than one byte */
11450 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11456 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11462 pic16_emitcode("movx","@dptr,a");
11467 DEBUGpic16_emitcode(";lcall","__gptrput");
11475 pic16_mov2w(AOP(right), offset++);
11478 /* last last was not complete */
11480 /* save the byte & read byte */
11483 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11484 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11489 pic16_emitcode ("mov","b,a");
11490 pic16_emitcode("movx","a,@dptr");
11494 pic16_emitcode ("push","b");
11495 pic16_emitcode ("push","acc");
11496 pic16_emitcode ("lcall","__gptrget");
11497 pic16_emitcode ("pop","b");
11503 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11504 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11505 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11506 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11507 // pic16_emitcode ("orl","a,b");
11510 // if (p_type == GPOINTER)
11511 // pic16_emitcode("pop","b");
11516 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11517 // pic16_emitcode("mov","@%s,a",rname);
11521 pic16_emitcode("movx","@dptr,a");
11525 DEBUGpic16_emitcode(";lcall","__gptrput");
11532 // pic16_freeAsmop(right, NULL, ic, TRUE);
11535 /*-----------------------------------------------------------------*/
11536 /* genDataPointerSet - remat pointer to data space */
11537 /*-----------------------------------------------------------------*/
11538 static void genDataPointerSet(operand *right,
11542 int size, offset = 0, resoffset=0 ;
11544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11545 pic16_aopOp(right,ic,FALSE);
11547 size = AOP_SIZE(right);
11549 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11552 if ( AOP_TYPE(result) == AOP_PCODE) {
11553 fprintf(stderr,"genDataPointerSet %s, %d\n",
11554 AOP(result)->aopu.pcop->name,
11555 (AOP(result)->aopu.pcop->type == PO_DIR)?
11556 PCOR(AOP(result)->aopu.pcop)->instance:
11557 PCOI(AOP(result)->aopu.pcop)->offset);
11561 if(AOP(result)->aopu.pcop->type == PO_DIR)
11562 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11565 if (AOP_TYPE(right) == AOP_LIT) {
11568 if(!IS_FLOAT(operandType( right )))
11569 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11572 unsigned long lit_int;
11576 /* take care if literal is a float */
11577 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11578 lit = info.lit_int;
11580 lit = lit >> (8*offset);
11581 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11583 pic16_mov2w(AOP(right), offset);
11584 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11590 pic16_freeAsmop(right,NULL,ic,TRUE);
11595 /*-----------------------------------------------------------------*/
11596 /* genNearPointerSet - pic16_emitcode for near pointer put */
11597 /*-----------------------------------------------------------------*/
11598 static void genNearPointerSet (operand *right,
11604 sym_link *ptype = operandType(result);
11605 sym_link *resetype;
11607 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11608 retype= getSpec(operandType(right));
11609 resetype = getSpec(operandType(result));
11611 pic16_aopOp(result,ic,FALSE);
11613 /* if the result is rematerializable &
11614 * in data space & not a bit variable */
11616 /* and result is not a bit variable */
11617 if (AOP_TYPE(result) == AOP_PCODE
11618 // && AOP_TYPE(result) == AOP_IMMD
11619 && DCL_TYPE(ptype) == POINTER
11620 && !IS_BITFIELD(retype)
11621 && !IS_BITFIELD(resetype)) {
11623 genDataPointerSet (right,result,ic);
11624 pic16_freeAsmop(result,NULL,ic,TRUE);
11628 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11629 pic16_aopOp(right,ic,FALSE);
11630 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11632 /* if bitfield then unpack the bits */
11633 if (IS_BITFIELD(resetype)) {
11634 genPackBits (resetype, result, right, NULL, POINTER);
11636 /* we have can just get the values */
11637 int size = AOP_SIZE(right);
11640 pic16_loadFSR0(result, 0);
11642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11644 if (AOP_TYPE(right) == AOP_LIT) {
11645 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11647 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11649 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11651 } else { // no literal
11653 pic16_emitpcode(POC_MOVFF,
11654 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11655 pic16_popCopyReg(&pic16_pc_postinc0)));
11657 pic16_emitpcode(POC_MOVFF,
11658 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11659 pic16_popCopyReg(&pic16_pc_indf0)));
11667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11668 /* now some housekeeping stuff */
11670 /* we had to allocate for this iCode */
11671 pic16_freeAsmop(NULL,aop,ic,TRUE);
11673 /* we did not allocate which means left
11674 * already in a pointer register, then
11675 * if size > 0 && this could be used again
11676 * we have to point it back to where it
11678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11679 if (AOP_SIZE(right) > 1
11680 && !OP_SYMBOL(result)->remat
11681 && ( OP_SYMBOL(result)->liveTo > ic->seq
11684 int size = AOP_SIZE(right) - 1;
11687 pic16_emitcode("decf","fsr0,f");
11688 //pic16_emitcode("dec","%s",rname);
11692 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11695 pic16_freeAsmop(right,NULL,ic,TRUE);
11696 pic16_freeAsmop(result,NULL,ic,TRUE);
11699 /*-----------------------------------------------------------------*/
11700 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11701 /*-----------------------------------------------------------------*/
11702 static void genPagedPointerSet (operand *right,
11707 regs *preg = NULL ;
11711 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11713 retype= getSpec(operandType(right));
11715 pic16_aopOp(result,ic,FALSE);
11717 /* if the value is already in a pointer register
11718 then don't need anything more */
11719 if (!AOP_INPREG(AOP(result))) {
11720 /* otherwise get a free pointer register */
11722 preg = getFreePtr(ic,&aop,FALSE);
11723 pic16_emitcode("mov","%s,%s",
11725 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11726 rname = preg->name ;
11728 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11730 pic16_freeAsmop(result,NULL,ic,TRUE);
11731 pic16_aopOp (right,ic,FALSE);
11733 /* if bitfield then unpack the bits */
11734 if (IS_BITFIELD(retype))
11735 genPackBits (retype,result,right,rname,PPOINTER);
11737 /* we have can just get the values */
11738 int size = AOP_SIZE(right);
11742 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11745 pic16_emitcode("movx","@%s,a",rname);
11748 pic16_emitcode("inc","%s",rname);
11754 /* now some housekeeping stuff */
11756 /* we had to allocate for this iCode */
11757 pic16_freeAsmop(NULL,aop,ic,TRUE);
11759 /* we did not allocate which means left
11760 already in a pointer register, then
11761 if size > 0 && this could be used again
11762 we have to point it back to where it
11764 if (AOP_SIZE(right) > 1 &&
11765 !OP_SYMBOL(result)->remat &&
11766 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11768 int size = AOP_SIZE(right) - 1;
11770 pic16_emitcode("dec","%s",rname);
11775 pic16_freeAsmop(right,NULL,ic,TRUE);
11781 /* This code is not adjusted to PIC16 and fails utterly...
11782 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11784 /*-----------------------------------------------------------------*/
11785 /* genFarPointerSet - set value from far space */
11786 /*-----------------------------------------------------------------*/
11787 static void genFarPointerSet (operand *right,
11788 operand *result, iCode *ic)
11791 sym_link *retype = getSpec(operandType(right));
11793 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11794 pic16_aopOp(result,ic,FALSE);
11796 /* if the operand is already in dptr
11797 then we do nothing else we move the value to dptr */
11798 if (AOP_TYPE(result) != AOP_STR) {
11799 /* if this is remateriazable */
11800 if (AOP_TYPE(result) == AOP_IMMD)
11801 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11802 else { /* we need to get it byte by byte */
11803 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11804 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11805 if (options.model == MODEL_FLAT24)
11807 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11811 /* so dptr know contains the address */
11812 pic16_freeAsmop(result,NULL,ic,TRUE);
11813 pic16_aopOp(right,ic,FALSE);
11815 /* if bit then unpack */
11816 if (IS_BITFIELD(retype))
11817 genPackBits(retype,result,right,"dptr",FPOINTER);
11819 size = AOP_SIZE(right);
11823 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11825 pic16_emitcode("movx","@dptr,a");
11827 pic16_emitcode("inc","dptr");
11831 pic16_freeAsmop(right,NULL,ic,TRUE);
11835 /*-----------------------------------------------------------------*/
11836 /* genGenPointerSet - set value from generic pointer space */
11837 /*-----------------------------------------------------------------*/
11839 static void genGenPointerSet (operand *right,
11840 operand *result, iCode *ic)
11842 int i, size, offset, lit;
11843 sym_link *retype = getSpec(operandType(right));
11845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11847 pic16_aopOp(result,ic,FALSE);
11848 pic16_aopOp(right,ic,FALSE);
11849 size = AOP_SIZE(right);
11852 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11854 /* if the operand is already in dptr
11855 then we do nothing else we move the value to dptr */
11856 if (AOP_TYPE(result) != AOP_STR) {
11857 /* if this is remateriazable */
11858 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11859 // WARNING: anythig until "else" is untested!
11860 if (AOP_TYPE(result) == AOP_IMMD) {
11861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11862 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11863 // load FSR0 from immediate
11864 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11876 else { /* we need to get it byte by byte */
11877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11878 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11880 // set up FSR0 with address of result
11881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11884 /* hack hack! see if this the FSR. If so don't load W */
11885 if(AOP_TYPE(right) != AOP_ACC) {
11887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11889 if(AOP_TYPE(right) == AOP_LIT)
11892 // note: pic16_popGet handles sign extension
11893 for(i=0;i<size;i++) {
11894 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11896 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11898 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11903 for(i=0;i<size;i++) {
11905 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11906 pic16_popCopyReg(&pic16_pc_postinc0)));
11908 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11909 pic16_popCopyReg(&pic16_pc_indf0)));
11915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11916 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11918 } // if (AOP_TYPE(result) != AOP_IMMD)
11920 } // if (AOP_TYPE(result) != AOP_STR)
11921 /* so dptr know contains the address */
11924 /* if bit then unpack */
11925 if (IS_BITFIELD(retype))
11926 genPackBits(retype,result,right,"dptr",GPOINTER);
11928 size = AOP_SIZE(right);
11931 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11933 // set up FSR0 with address of result
11934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11935 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11938 if (AOP_TYPE(right) == AOP_LIT) {
11939 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11941 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11943 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11945 } else { // no literal
11947 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11949 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11957 pic16_freeAsmop(right,NULL,ic,TRUE);
11958 pic16_freeAsmop(result,NULL,ic,TRUE);
11962 static void genGenPointerSet (operand *right,
11963 operand *result, iCode *ic)
11966 sym_link *retype = getSpec(operandType(result));
11968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11970 pic16_aopOp(result,ic,FALSE);
11971 pic16_aopOp(right,ic,FALSE);
11972 size = AOP_SIZE(right);
11974 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11977 /* if bit then unpack */
11978 if (IS_BITFIELD(retype)) {
11979 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11980 genPackBits(retype,result,right,"dptr",GPOINTER);
11984 size = AOP_SIZE(right);
11986 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11989 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11991 /* value of right+0 is placed on stack, which will be retrieved
11992 * by the support function thus restoring the stack. The important
11993 * thing is that there is no need to manually restore stack pointer
11995 pushaop(AOP(right), 0);
11996 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11997 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11998 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11999 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12001 /* load address to write to in WREG:FSR0H:FSR0L */
12002 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12003 pic16_popCopyReg(&pic16_pc_fsr0l)));
12004 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12005 pic16_popCopyReg(&pic16_pc_prodl)));
12006 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12008 pic16_callGenericPointerRW(1, size);
12011 pic16_freeAsmop(right,NULL,ic,TRUE);
12012 pic16_freeAsmop(result,NULL,ic,TRUE);
12015 /*-----------------------------------------------------------------*/
12016 /* genPointerSet - stores the value into a pointer location */
12017 /*-----------------------------------------------------------------*/
12018 static void genPointerSet (iCode *ic)
12020 operand *right, *result ;
12021 sym_link *type, *etype;
12026 right = IC_RIGHT(ic);
12027 result = IC_RESULT(ic) ;
12029 /* depending on the type of pointer we need to
12030 move it to the correct pointer register */
12031 type = operandType(result);
12032 etype = getSpec(type);
12034 /* if left is of type of pointer then it is simple */
12035 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12036 p_type = DCL_TYPE(type);
12039 /* we have to go by the storage class */
12040 p_type = PTR_TYPE(SPEC_OCLS(etype));
12042 /* if (SPEC_OCLS(etype)->codesp ) { */
12043 /* p_type = CPOINTER ; */
12046 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12047 /* p_type = FPOINTER ; */
12049 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12050 /* p_type = PPOINTER ; */
12052 /* if (SPEC_OCLS(etype) == idata ) */
12053 /* p_type = IPOINTER ; */
12055 /* p_type = POINTER ; */
12058 /* now that we have the pointer type we assign
12059 the pointer values */
12064 genNearPointerSet (right,result,ic);
12068 genPagedPointerSet (right,result,ic);
12072 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12074 genFarPointerSet (right,result,ic);
12079 genGenPointerSet (right,result,ic);
12083 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12084 "genPointerSet: illegal pointer type");
12088 /*-----------------------------------------------------------------*/
12089 /* genIfx - generate code for Ifx statement */
12090 /*-----------------------------------------------------------------*/
12091 static void genIfx (iCode *ic, iCode *popIc)
12093 operand *cond = IC_COND(ic);
12098 pic16_aopOp(cond,ic,FALSE);
12100 /* get the value into acc */
12101 if (AOP_TYPE(cond) != AOP_CRY)
12102 pic16_toBoolean(cond);
12105 /* the result is now in the accumulator */
12106 pic16_freeAsmop(cond,NULL,ic,TRUE);
12108 /* if there was something to be popped then do it */
12112 /* if the condition is a bit variable */
12113 if (isbit && IS_ITEMP(cond) &&
12115 genIfxJump(ic,"c");
12116 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12118 if (isbit && !IS_ITEMP(cond))
12119 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12121 genIfxJump(ic,"a");
12126 /*-----------------------------------------------------------------*/
12127 /* genAddrOf - generates code for address of */
12128 /*-----------------------------------------------------------------*/
12129 static void genAddrOf (iCode *ic)
12131 operand *result, *left;
12133 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12134 pCodeOp *pcop0, *pcop1, *pcop2;
12138 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12140 sym = OP_SYMBOL( IC_LEFT(ic) );
12143 /* get address of symbol on stack */
12144 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12146 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12147 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12150 // operands on stack are accessible via "FSR2 + index" with index
12151 // starting at 2 for arguments and growing from 0 downwards for
12152 // local variables (index == 0 is not assigned so we add one here)
12154 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12157 assert (soffs < 0);
12161 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12162 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12163 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12164 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12165 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12166 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12167 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12173 // if(pic16_debug_verbose) {
12174 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12175 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12178 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12179 size = AOP_SIZE(IC_RESULT(ic));
12181 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12182 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12183 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12186 pic16_emitpcode(POC_MOVLW, pcop0);
12187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12188 pic16_emitpcode(POC_MOVLW, pcop1);
12189 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12190 pic16_emitpcode(POC_MOVLW, pcop2);
12191 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12194 pic16_emitpcode(POC_MOVLW, pcop0);
12195 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12196 pic16_emitpcode(POC_MOVLW, pcop1);
12197 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12199 pic16_emitpcode(POC_MOVLW, pcop0);
12200 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12203 pic16_freeAsmop(left, NULL, ic, FALSE);
12205 pic16_freeAsmop(result,NULL,ic,TRUE);
12210 /*-----------------------------------------------------------------*/
12211 /* genFarFarAssign - assignment when both are in far space */
12212 /*-----------------------------------------------------------------*/
12213 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12215 int size = AOP_SIZE(right);
12218 /* first push the right side on to the stack */
12220 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12222 pic16_emitcode ("push","acc");
12225 pic16_freeAsmop(right,NULL,ic,FALSE);
12226 /* now assign DPTR to result */
12227 pic16_aopOp(result,ic,FALSE);
12228 size = AOP_SIZE(result);
12230 pic16_emitcode ("pop","acc");
12231 pic16_aopPut(AOP(result),"a",--offset);
12233 pic16_freeAsmop(result,NULL,ic,FALSE);
12238 /*-----------------------------------------------------------------*/
12239 /* genAssign - generate code for assignment */
12240 /*-----------------------------------------------------------------*/
12241 static void genAssign (iCode *ic)
12243 operand *result, *right;
12244 sym_link *restype, *rtype;
12245 int size, offset,know_W;
12246 unsigned long lit = 0L;
12248 result = IC_RESULT(ic);
12249 right = IC_RIGHT(ic) ;
12253 /* if they are the same */
12254 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12257 /* reversed order operands are aopOp'ed so that result operand
12258 * is effective in case right is a stack symbol. This maneauver
12259 * allows to use the _G.resDirect flag later */
12260 pic16_aopOp(result,ic,TRUE);
12261 pic16_aopOp(right,ic,FALSE);
12263 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12265 /* if they are the same registers */
12266 if (pic16_sameRegs(AOP(right),AOP(result)))
12269 /* if the result is a bit */
12270 if (AOP_TYPE(result) == AOP_CRY) {
12271 /* if the right size is a literal then
12272 we know what the value is */
12273 if (AOP_TYPE(right) == AOP_LIT) {
12275 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12276 pic16_popGet(AOP(result),0));
12278 if (((int) operandLitValue(right)))
12279 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12280 AOP(result)->aopu.aop_dir,
12281 AOP(result)->aopu.aop_dir);
12283 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12284 AOP(result)->aopu.aop_dir,
12285 AOP(result)->aopu.aop_dir);
12290 /* the right is also a bit variable */
12291 if (AOP_TYPE(right) == AOP_CRY) {
12292 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12293 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12294 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12299 /* we need to or */
12300 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12301 pic16_toBoolean(right);
12303 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12304 //pic16_aopPut(AOP(result),"a",0);
12308 /* bit variables done */
12310 size = AOP_SIZE(result);
12313 /* bit variables done */
12315 size = AOP_SIZE(result);
12316 restype = operandType(result);
12317 rtype = operandType(right);
12320 if(AOP_TYPE(right) == AOP_LIT) {
12321 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12323 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12325 /* patch tag for literals that are cast to pointers */
12326 if (IS_CODEPTR(restype)) {
12327 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12328 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12330 if (IS_GENPTR(restype))
12332 if (IS_CODEPTR(rtype)) {
12333 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12334 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12335 } else if (PIC_IS_DATA_PTR(rtype)) {
12336 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12337 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12338 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12339 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12340 } else if (IS_PTR(rtype)) {
12341 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12342 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12348 unsigned long lit_int;
12353 if(IS_FIXED16X16(operandType(right))) {
12354 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12356 /* take care if literal is a float */
12357 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12358 lit = info.lit_int;
12363 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12364 // sizeof(unsigned long int), sizeof(float));
12367 if (AOP_TYPE(right) == AOP_REG) {
12368 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12370 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12375 /* when do we have to read the program memory?
12376 * - if right itself is a symbol in code space
12377 * (we don't care what it points to if it's a pointer)
12378 * - AND right is not a function (we would want its address)
12380 if(AOP_TYPE(right) != AOP_LIT
12381 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12382 && !IS_FUNC(OP_SYM_TYPE(right))
12383 && !IS_ITEMP(right)) {
12385 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12386 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12388 // set up table pointer
12389 if(is_LitOp(right)) {
12390 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12391 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12392 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12393 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12394 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12395 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12396 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12398 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12399 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12400 pic16_popCopyReg(&pic16_pc_tblptrl)));
12401 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12402 pic16_popCopyReg(&pic16_pc_tblptrh)));
12403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12404 pic16_popCopyReg(&pic16_pc_tblptru)));
12407 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12408 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12410 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12411 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12412 pic16_popGet(AOP(result),offset)));
12416 /* FIXME: for pointers we need to extend differently (according
12417 * to pointer type DATA/CODE/EEPROM/... :*/
12418 size = getSize(OP_SYM_TYPE(right));
12419 if(AOP_SIZE(result) > size) {
12420 size = AOP_SIZE(result) - size;
12422 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12430 /* VR - What is this?! */
12431 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12434 if(aopIdx(AOP(result),0) == 4) {
12435 /* this is a workaround to save value of right into wreg too,
12436 * value of wreg is going to be used later */
12437 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12438 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12443 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12449 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12450 if(AOP_TYPE(right) == AOP_LIT) {
12452 if(know_W != (lit&0xff))
12453 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12455 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12457 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12461 } else if (AOP_TYPE(right) == AOP_CRY) {
12462 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12464 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12465 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12466 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12468 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12469 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12470 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12474 if(!_G.resDirect) /* use this aopForSym feature */
12475 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12482 pic16_freeAsmop (right,NULL,ic,FALSE);
12483 pic16_freeAsmop (result,NULL,ic,TRUE);
12486 /*-----------------------------------------------------------------*/
12487 /* genJumpTab - generates code for jump table */
12488 /*-----------------------------------------------------------------*/
12489 static void genJumpTab (iCode *ic)
12494 pCodeOp *jt_offs_hi;
12499 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12500 /* get the condition into accumulator */
12501 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12503 /* multiply by three */
12504 pic16_emitcode("add","a,acc");
12505 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12507 jtab = newiTempLabel(NULL);
12508 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12509 pic16_emitcode("jmp","@a+dptr");
12510 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12513 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12514 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12516 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12517 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12518 pic16_emitpLabel(jtab->key);
12522 jt_offs = pic16_popGetTempReg(0);
12523 jt_offs_hi = pic16_popGetTempReg(1);
12524 jt_label = pic16_popGetLabel (jtab->key);
12525 //fprintf (stderr, "Creating jump table...\n");
12527 // calculate offset into jump table (idx * sizeof (GOTO))
12528 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12529 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12530 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12531 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12532 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12533 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12534 pic16_emitpcode(POC_MOVWF , jt_offs);
12536 // prepare PCLATx (set to first entry in jump table)
12537 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12538 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12539 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12540 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12541 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12543 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12544 pic16_emitpcode(POC_ADDWF , jt_offs);
12545 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12546 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12548 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12550 // release temporaries and prepare jump into table (new PCL --> WREG)
12551 pic16_emitpcode(POC_MOVFW , jt_offs);
12552 pic16_popReleaseTempReg (jt_offs_hi, 1);
12553 pic16_popReleaseTempReg (jt_offs, 0);
12555 // jump into the table
12556 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12558 pic16_emitpLabelFORCE(jtab->key);
12561 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12562 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12564 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12565 /* now generate the jump labels */
12566 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12567 jtab = setNextItem(IC_JTLABELS(ic))) {
12568 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12569 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12572 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12576 /*-----------------------------------------------------------------*/
12577 /* genMixedOperation - gen code for operators between mixed types */
12578 /*-----------------------------------------------------------------*/
12580 TSD - Written for the PIC port - but this unfortunately is buggy.
12581 This routine is good in that it is able to efficiently promote
12582 types to different (larger) sizes. Unfortunately, the temporary
12583 variables that are optimized out by this routine are sometimes
12584 used in other places. So until I know how to really parse the
12585 iCode tree, I'm going to not be using this routine :(.
12587 static int genMixedOperation (iCode *ic)
12590 operand *result = IC_RESULT(ic);
12591 sym_link *ctype = operandType(IC_LEFT(ic));
12592 operand *right = IC_RIGHT(ic);
12598 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12600 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12606 nextright = IC_RIGHT(nextic);
12607 nextleft = IC_LEFT(nextic);
12608 nextresult = IC_RESULT(nextic);
12610 pic16_aopOp(right,ic,FALSE);
12611 pic16_aopOp(result,ic,FALSE);
12612 pic16_aopOp(nextright, nextic, FALSE);
12613 pic16_aopOp(nextleft, nextic, FALSE);
12614 pic16_aopOp(nextresult, nextic, FALSE);
12616 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12618 operand *t = right;
12622 pic16_emitcode(";remove right +","");
12624 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12626 operand *t = right;
12630 pic16_emitcode(";remove left +","");
12634 big = AOP_SIZE(nextleft);
12635 small = AOP_SIZE(nextright);
12637 switch(nextic->op) {
12640 pic16_emitcode(";optimize a +","");
12641 /* if unsigned or not an integral type */
12642 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12643 pic16_emitcode(";add a bit to something","");
12646 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12648 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12649 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12650 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12652 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12660 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12661 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12662 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12665 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12667 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12668 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12669 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12670 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12671 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12674 pic16_emitcode("rlf","known_zero,w");
12681 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12682 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12683 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12685 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12695 pic16_freeAsmop(right,NULL,ic,TRUE);
12696 pic16_freeAsmop(result,NULL,ic,TRUE);
12697 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12698 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12700 nextic->generated = 1;
12707 /*-----------------------------------------------------------------*/
12708 /* genCast - gen code for casting */
12709 /*-----------------------------------------------------------------*/
12710 static void genCast (iCode *ic)
12712 operand *result = IC_RESULT(ic);
12713 sym_link *ctype = operandType(IC_LEFT(ic));
12714 sym_link *rtype = operandType(IC_RIGHT(ic));
12715 sym_link *restype = operandType(IC_RESULT(ic));
12716 operand *right = IC_RIGHT(ic);
12722 /* if they are equivalent then do nothing */
12723 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12726 pic16_aopOp(result,ic,FALSE);
12727 pic16_aopOp(right,ic,FALSE) ;
12729 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12732 /* if the result is a bit */
12733 if (AOP_TYPE(result) == AOP_CRY) {
12735 /* if the right size is a literal then
12736 * we know what the value is */
12737 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12739 if (AOP_TYPE(right) == AOP_LIT) {
12740 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12741 pic16_popGet(AOP(result),0));
12743 if (((int) operandLitValue(right)))
12744 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12745 AOP(result)->aopu.aop_dir,
12746 AOP(result)->aopu.aop_dir);
12748 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12749 AOP(result)->aopu.aop_dir,
12750 AOP(result)->aopu.aop_dir);
12754 /* the right is also a bit variable */
12755 if (AOP_TYPE(right) == AOP_CRY) {
12757 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12759 pic16_emitcode("clrc","");
12760 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12761 AOP(right)->aopu.aop_dir,
12762 AOP(right)->aopu.aop_dir);
12763 pic16_aopPut(AOP(result),"c",0);
12767 /* we need to or */
12768 if (AOP_TYPE(right) == AOP_REG) {
12769 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12770 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12771 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12773 pic16_toBoolean(right);
12774 pic16_aopPut(AOP(result),"a",0);
12778 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12781 size = AOP_SIZE(result);
12783 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12785 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12786 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12787 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12790 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12795 if(IS_BITFIELD(getSpec(restype))
12796 && IS_BITFIELD(getSpec(rtype))) {
12797 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12800 /* port from pic14 to cope with generic pointers */
12801 if (PIC_IS_TAGGED(restype))
12803 operand *result = IC_RESULT(ic);
12804 //operand *left = IC_LEFT(ic);
12805 operand *right = IC_RIGHT(ic);
12808 /* copy common part */
12809 int max, size = AOP_SIZE(result);
12810 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12811 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12816 pic16_mov2w (AOP(right), size);
12817 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12820 /* upcast into generic pointer type? */
12821 if (IS_GENPTR(restype)
12822 && !PIC_IS_TAGGED(rtype)
12823 && (AOP_SIZE(result) > max))
12825 /* determine appropriate tag for right */
12826 if (PIC_IS_DATA_PTR(rtype))
12827 tag = GPTR_TAG_DATA;
12828 else if (IS_CODEPTR(rtype))
12829 tag = GPTR_TAG_CODE;
12830 else if (PIC_IS_DATA_PTR(ctype)) {
12831 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12832 tag = GPTR_TAG_DATA;
12833 } else if (IS_CODEPTR(ctype)) {
12834 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12835 tag = GPTR_TAG_CODE;
12836 } else if (IS_PTR(rtype)) {
12837 PERFORM_ONCE(weirdcast,
12838 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12840 tag = GPTR_TAG_DATA;
12842 PERFORM_ONCE(weirdcast,
12843 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12845 tag = GPTR_TAG_DATA;
12848 assert (AOP_SIZE(result) == 3);
12849 /* zero-extend address... */
12850 for (size = max; size < AOP_SIZE(result)-1; size++)
12851 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12852 /* ...and add tag */
12853 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12854 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12855 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12856 for (size = max; size < AOP_SIZE(result)-1; size++)
12857 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12858 /* add __code tag */
12859 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12860 } else if (AOP_SIZE(result) > max) {
12861 /* extend non-pointers */
12862 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12863 pic16_addSign(result, max, 0);
12868 /* if they are the same size : or less */
12869 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12871 /* if they are in the same place */
12872 if (pic16_sameRegs(AOP(right),AOP(result)))
12875 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12877 if (IS_PTR_CONST(rtype))
12879 if (IS_CODEPTR(rtype))
12881 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12884 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12886 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12888 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12891 if(AOP_TYPE(right) == AOP_IMMD) {
12892 pCodeOp *pcop0, *pcop1, *pcop2;
12893 symbol *sym = OP_SYMBOL( right );
12895 size = AOP_SIZE(result);
12897 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12899 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12901 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12904 pic16_emitpcode(POC_MOVLW, pcop0);
12905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12906 pic16_emitpcode(POC_MOVLW, pcop1);
12907 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12908 pic16_emitpcode(POC_MOVLW, pcop2);
12909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12912 pic16_emitpcode(POC_MOVLW, pcop0);
12913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12914 pic16_emitpcode(POC_MOVLW, pcop1);
12915 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12917 pic16_emitpcode(POC_MOVLW, pcop0);
12918 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12922 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12923 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12924 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12925 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12927 if(AOP_SIZE(result) <2)
12928 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12930 /* if they in different places then copy */
12931 size = AOP_SIZE(result);
12934 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12942 /* if the result is of type pointer */
12943 if (IS_PTR(ctype)) {
12945 sym_link *type = operandType(right);
12946 sym_link *etype = getSpec(type);
12948 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12950 /* pointer to generic pointer */
12951 if (IS_GENPTR(ctype)) {
12955 p_type = DCL_TYPE(type);
12957 /* we have to go by the storage class */
12958 p_type = PTR_TYPE(SPEC_OCLS(etype));
12960 /* if (SPEC_OCLS(etype)->codesp ) */
12961 /* p_type = CPOINTER ; */
12963 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12964 /* p_type = FPOINTER ; */
12966 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12967 /* p_type = PPOINTER; */
12969 /* if (SPEC_OCLS(etype) == idata ) */
12970 /* p_type = IPOINTER ; */
12972 /* p_type = POINTER ; */
12975 /* the first two bytes are known */
12976 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12977 size = GPTRSIZE - 1;
12980 if(offset < AOP_SIZE(right)) {
12981 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12982 pic16_mov2f(AOP(result), AOP(right), offset);
12984 if ((AOP_TYPE(right) == AOP_PCODE) &&
12985 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12986 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12990 pic16_aopPut(AOP(result),
12991 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12996 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12999 /* the last byte depending on type */
13004 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13008 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13012 pic16_emitcode(";BUG!? ","%d",__LINE__);
13017 if (GPTRSIZE > AOP_SIZE(right)) {
13018 // assume __data pointer... THIS MIGHT BE WRONG!
13019 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13021 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13026 /* this should never happen */
13027 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13028 "got unknown pointer type");
13031 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13037 /* just copy the pointers */
13038 size = AOP_SIZE(result);
13041 pic16_aopPut(AOP(result),
13042 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13051 /* so we now know that the size of destination is greater
13052 than the size of the source.
13053 Now, if the next iCode is an operator then we might be
13054 able to optimize the operation without performing a cast.
13056 if(genMixedOperation(ic))
13059 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13061 /* we move to result for the size of source */
13062 size = AOP_SIZE(right);
13067 pic16_mov2f(AOP(result), AOP(right), offset);
13071 /* now depending on the sign of the destination */
13072 size = AOP_SIZE(result) - AOP_SIZE(right);
13073 /* if unsigned or not an integral type */
13074 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13076 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13078 /* we need to extend the sign :( */
13081 /* Save one instruction of casting char to int */
13082 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13083 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13084 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13086 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13089 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13091 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13093 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13096 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13101 pic16_freeAsmop(right,NULL,ic,TRUE);
13102 pic16_freeAsmop(result,NULL,ic,TRUE);
13106 /*-----------------------------------------------------------------*/
13107 /* genDjnz - generate decrement & jump if not zero instrucion */
13108 /*-----------------------------------------------------------------*/
13109 static int genDjnz (iCode *ic, iCode *ifx)
13111 symbol *lbl, *lbl1;
13112 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13117 /* if the if condition has a false label
13118 then we cannot save */
13122 /* if the minus is not of the form
13124 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13125 !IS_OP_LITERAL(IC_RIGHT(ic)))
13128 if (operandLitValue(IC_RIGHT(ic)) != 1)
13131 /* if the size of this greater than one then no
13133 if (getSize(operandType(IC_RESULT(ic))) > 1)
13136 /* otherwise we can save BIG */
13137 lbl = newiTempLabel(NULL);
13138 lbl1= newiTempLabel(NULL);
13140 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13142 if (IS_AOP_PREG(IC_RESULT(ic))) {
13143 pic16_emitcode("dec","%s",
13144 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13145 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13146 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13150 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13151 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13153 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13154 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13158 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13159 ifx->generated = 1;
13163 /*-----------------------------------------------------------------*/
13164 /* genReceive - generate code for a receive iCode */
13165 /*-----------------------------------------------------------------*/
13166 static void genReceive (iCode *ic)
13172 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13173 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13175 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13177 if (isOperandInFarSpace(IC_RESULT(ic))
13178 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13179 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13181 int size = getSize(operandType(IC_RESULT(ic)));
13182 int offset = pic16_fReturnSizePic - size;
13186 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13187 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13191 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13193 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13194 size = AOP_SIZE(IC_RESULT(ic));
13197 pic16_emitcode ("pop","acc");
13198 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13201 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13203 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13206 /* set pseudo stack pointer to where it should be - dw*/
13207 GpsuedoStkPtr = ic->parmBytes;
13209 /* setting GpsuedoStkPtr has side effects here: */
13210 assignResultValue(IC_RESULT(ic), 0);
13213 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13216 /*-----------------------------------------------------------------*/
13217 /* genDummyRead - generate code for dummy read of volatiles */
13218 /*-----------------------------------------------------------------*/
13220 genDummyRead (iCode * ic)
13226 if (op && IS_SYMOP(op)) {
13227 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13228 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13231 pic16_aopOp (op, ic, FALSE);
13232 for (i=0; i < AOP_SIZE(op); i++) {
13233 // may need to protect this from the peepholer -- this is not nice but works...
13234 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13235 pic16_mov2w (AOP(op),i);
13236 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13238 pic16_freeAsmop (op, NULL, ic, TRUE);
13240 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13244 /*-----------------------------------------------------------------*/
13245 /* genpic16Code - generate code for pic16 based controllers */
13246 /*-----------------------------------------------------------------*/
13248 * At this point, ralloc.c has gone through the iCode and attempted
13249 * to optimize in a way suitable for a PIC. Now we've got to generate
13250 * PIC instructions that correspond to the iCode.
13252 * Once the instructions are generated, we'll pass through both the
13253 * peep hole optimizer and the pCode optimizer.
13254 *-----------------------------------------------------------------*/
13256 void genpic16Code (iCode *lic)
13261 lineHead = lineCurr = NULL;
13263 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13264 pic16_addpBlock(pb);
13267 /* if debug information required */
13268 if (options.debug && currFunc) {
13270 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13275 for (ic = lic ; ic ; ic = ic->next ) {
13277 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13278 if ( cln != ic->lineno ) {
13279 if ( options.debug ) {
13280 debugFile->writeCLine (ic);
13283 if(!options.noCcodeInAsm) {
13284 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13285 printCLine(ic->filename, ic->lineno)));
13291 if(options.iCodeInAsm) {
13294 /* insert here code to print iCode as comment */
13295 l = Safe_strdup(printILine(ic));
13296 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13299 /* if the result is marked as
13300 * spilt and rematerializable or code for
13301 * this has already been generated then
13303 if (resultRemat(ic) || ic->generated )
13306 /* depending on the operation */
13325 /* IPOP happens only when trying to restore a
13326 * spilt live range, if there is an ifx statement
13327 * following this pop then the if statement might
13328 * be using some of the registers being popped which
13329 * would destroy the contents of the register so
13330 * we need to check for this condition and handle it */
13332 && ic->next->op == IFX
13333 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13334 genIfx (ic->next,ic);
13352 genEndFunction (ic);
13368 pic16_genPlus (ic) ;
13372 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13373 pic16_genMinus (ic);
13389 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13393 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13399 /* note these two are xlated by algebraic equivalence
13400 * during parsing SDCC.y */
13401 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13402 "got '>=' or '<=' shouldn't have come here");
13406 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13418 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13422 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13426 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13450 genRightShift (ic);
13453 case GET_VALUE_AT_ADDRESS:
13458 if (POINTER_SET(ic))
13485 addSet(&_G.sendSet,ic);
13488 case DUMMY_READ_VOLATILE:
13498 /* now we are ready to call the
13499 peep hole optimizer */
13500 if (!options.nopeep)
13501 peepHole (&lineHead);
13503 /* now do the actual printing */
13504 printLine (lineHead, codeOutFile);
13507 DFPRINTF((stderr,"printing pBlock\n\n"));
13508 pic16_printpBlock(stdout,pb);