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 = (unsigned char *)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 = (unsigned char *)lb;
280 if(!pic16_debug_verbose)
287 sprintf(lb,"%s\t",inst);
289 sprintf(lb,"%s",inst);
290 vsprintf(lb+(strlen(lb)),fmt,ap);
294 while (isspace(*lbp)) lbp++;
297 lineCurr = (lineCurr ?
298 connectLine(lineCurr,newLineNode(lb)) :
299 (lineHead = newLineNode(lb)));
300 lineCurr->isInline = _G.inLine;
301 lineCurr->isDebug = _G.debugLine;
303 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
306 // fprintf(stderr, "%s\n", lb);
311 void pic16_emitpLabel(int key)
313 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
316 void pic16_emitpLabelFORCE(int key)
318 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322 * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
327 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
329 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
335 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
337 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
343 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
349 #define pic16_emitcode DEBUGpic16_emitcode
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
357 char lb[INITIAL_INLINEASM];
358 unsigned char *lbp = lb;
364 sprintf(lb,"%s\t",inst);
366 sprintf(lb,"%s",inst);
367 vsprintf(lb+(strlen(lb)),fmt,ap);
371 while (isspace(*lbp)) lbp++;
374 lineCurr = (lineCurr ?
375 connectLine(lineCurr,newLineNode(lb)) :
376 (lineHead = newLineNode(lb)));
377 lineCurr->isInline = _G.inLine;
378 lineCurr->isDebug = _G.debugLine;
380 // VR fprintf(stderr, "lb = <%s>\n", lbp);
382 // if(pic16_debug_verbose)
383 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location */
392 /* with a debugger symbol */
393 /*-----------------------------------------------------------------*/
395 pic16_emitDebuggerSymbol (char * debugSym)
398 pic16_emitcode (";", "%s ==.", debugSym);
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
408 // bool r0iu = FALSE , r1iu = FALSE;
409 // bool r0ou = FALSE , r1ou = FALSE;
410 bool fsr0iu = FALSE, fsr0ou;
411 bool fsr2iu = FALSE, fsr2ou;
413 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
416 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
419 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
422 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
427 if(!fsr0iu && !fsr0ou) {
428 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429 (*aopp)->type = AOP_FSR0;
431 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
433 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
437 /* no usage of FSR2 */
438 if(!fsr2iu && !fsr2ou) {
439 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440 (*aopp)->type = AOP_FSR2;
442 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
446 /* now we know they both have usage */
447 /* if fsr0 not used in this instruction */
449 if (!_G.fsr0Pushed) {
450 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
455 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456 (*aopp)->type = AOP_FSR0;
458 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
460 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
464 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
469 /* the logic: if r0 & r1 used in the instruction
470 then we are in trouble otherwise */
472 /* first check if r0 & r1 are used by this
473 instruction, in which case we are in trouble */
474 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
480 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
483 /* if no usage of r0 then return it */
484 if (!r0iu && !r0ou) {
485 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486 (*aopp)->type = AOP_R0;
488 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491 /* if no usage of r1 then return it */
492 if (!r1iu && !r1ou) {
493 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494 (*aopp)->type = AOP_R1;
496 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
499 /* now we know they both have usage */
500 /* if r0 not used in this instruction */
502 /* push it if not already pushed */
504 //pic16_emitcode ("push","%s",
505 // pic16_regWithIdx(R0_IDX)->dname);
509 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510 (*aopp)->type = AOP_R0;
512 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
515 /* if r1 not used then */
518 /* push it if not already pushed */
520 //pic16_emitcode ("push","%s",
521 // pic16_regWithIdx(R1_IDX)->dname);
525 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526 (*aopp)->type = AOP_R1;
527 return pic16_regWithIdx(R1_IDX);
531 /* I said end of world but not quite end of world yet */
532 /* if this is a result then we can push it on the stack*/
534 (*aopp)->type = AOP_STK;
538 /* other wise this is true end of the world */
539 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540 "getFreePtr should never reach here");
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
552 aop = Safe_calloc(1,sizeof(asmop));
557 static void genSetDPTR(int n)
561 pic16_emitcode(";", "Select standard DPTR");
562 pic16_emitcode("mov", "dps, #0x00");
566 pic16_emitcode(";", "Select alternate DPTR");
567 pic16_emitcode("mov", "dps, #0x01");
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for */
573 /* generating code */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
579 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585 resIfx->condition = 1; /* assume that the ifx is true */
586 resIfx->generated = 0; /* indicate that the ifx has not been used */
589 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
592 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593 __FUNCTION__,__LINE__,resIfx->lbl->key);
598 resIfx->lbl = IC_TRUE(ifx);
600 resIfx->lbl = IC_FALSE(ifx);
601 resIfx->condition = 0;
606 DEBUGpic16_emitcode("; +++","ifx true is non-null");
608 DEBUGpic16_emitcode("; +++","ifx true is null");
610 DEBUGpic16_emitcode("; +++","ifx false is non-null");
612 DEBUGpic16_emitcode("; +++","ifx false is null");
616 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
626 return PTR_TYPE(SPEC_OCLS(etype));
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
636 symbol *sym=OP_SYMBOL(op);
638 memmap *space= SPEC_OCLS(sym->etype);
642 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
644 // sym = OP_SYMBOL(op);
646 /* if already has one */
648 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
653 /* if symbol was initially placed onStack then we must re-place it
654 * to direct memory, since pic16 does not have a specific stack */
656 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
664 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
666 sym->aop = aop = newAsmop (AOP_PAGED);
667 aop->aopu.aop_dir = sym->rname ;
668 aop->size = getSize(sym->type);
669 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670 pic16_allocDirReg( IC_LEFT(ic) );
678 /* assign depending on the storage class */
679 /* if it is on the stack or indirectly addressable */
680 /* space we need to assign either r0 or r1 to it */
681 if (sym->onStack) // || sym->iaccess)
686 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
689 /* acquire a temporary register -- it is saved in function */
691 sym->aop = aop = newAsmop(AOP_STA);
692 aop->aopu.stk.stk = sym->stack;
693 aop->size = getSize(sym->type);
696 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
701 for(i=0;i<aop->size;i++)
702 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
705 if(1 && ic->op == SEND) {
707 /* if SEND do the send here */
710 for(i=0;i<aop->size;i++) {
711 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
712 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
717 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
720 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
722 // we do not need to load the value if it is to be defined...
723 if (result) return aop;
726 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
729 for(i=0;i<aop->size;i++) {
731 /* initialise for stack access via frame pointer */
732 // operands on stack are accessible via "{FRAME POINTER} + index" with index
733 // starting at 2 for arguments and growing from 0 downwards for
734 // local variables (index == 0 is not assigned so we add one here)
736 int soffs = sym->stack;
742 if(1 && ic->op == SEND) {
743 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
744 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
745 pic16_popCopyReg( pic16_frame_plusw ),
746 pic16_popCopyReg(pic16_stack_postdec )));
748 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
749 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
750 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
756 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
763 /* now assign the address of the variable to
764 the pointer register */
765 if (aop->type != AOP_STK) {
769 pic16_emitcode("push","acc");
771 pic16_emitcode("mov","a,_bp");
772 pic16_emitcode("add","a,#0x%02x",
774 ((char)(sym->stack - _G.nRegsSaved )) :
775 ((char)sym->stack)) & 0xff);
776 pic16_emitcode("mov","%s,a",
777 aop->aopu.aop_ptr->name);
780 pic16_emitcode("pop","acc");
782 pic16_emitcode("mov","%s,#%s",
783 aop->aopu.aop_ptr->name,
785 aop->paged = space->paged;
787 aop->aopu.aop_stk = sym->stack;
795 if (sym->onStack && options.stack10bit)
797 /* It's on the 10 bit stack, which is located in
801 //DEBUGpic16_emitcode(";","%d",__LINE__);
804 pic16_emitcode("push","acc");
806 pic16_emitcode("mov","a,_bp");
807 pic16_emitcode("add","a,#0x%02x",
809 ((char)(sym->stack - _G.nRegsSaved )) :
810 ((char)sym->stack)) & 0xff);
813 pic16_emitcode ("mov","dpx1,#0x40");
814 pic16_emitcode ("mov","dph1,#0x00");
815 pic16_emitcode ("mov","dpl1, a");
819 pic16_emitcode("pop","acc");
821 sym->aop = aop = newAsmop(AOP_DPTR2);
822 aop->size = getSize(sym->type);
828 /* special case for a function */
829 if (IS_FUNC(sym->type)) {
830 sym->aop = aop = newAsmop(AOP_PCODE);
831 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
832 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
833 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
834 PCOI(aop->aopu.pcop)->index = 0;
835 aop->size = FPTRSIZE;
836 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
843 //DEBUGpic16_emitcode(";","%d",__LINE__);
844 /* if in bit space */
845 if (IN_BITSPACE(space)) {
846 sym->aop = aop = newAsmop (AOP_CRY);
847 aop->aopu.aop_dir = sym->rname ;
848 aop->size = getSize(sym->type);
849 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
852 /* if it is in direct space */
853 if (IN_DIRSPACE(space)) {
854 if(!strcmp(sym->rname, "_WREG")) {
855 sym->aop = aop = newAsmop (AOP_ACC);
856 aop->size = getSize(sym->type); /* should always be 1 */
857 assert(aop->size == 1);
858 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
861 sym->aop = aop = newAsmop (AOP_DIR);
862 aop->aopu.aop_dir = sym->rname ;
863 aop->size = getSize(sym->type);
864 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
865 pic16_allocDirReg( IC_LEFT(ic) );
870 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
871 sym->aop = aop = newAsmop (AOP_DIR);
872 aop->aopu.aop_dir = sym->rname ;
873 aop->size = getSize(sym->type);
874 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
875 pic16_allocDirReg( IC_LEFT(ic) );
880 /* only remaining is far space */
881 sym->aop = aop = newAsmop(AOP_PCODE);
883 /* change the next if to 1 to revert to good old immediate code */
884 if(IN_CODESPACE(space)) {
885 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
886 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
887 PCOI(aop->aopu.pcop)->index = 0;
889 /* try to allocate via direct register */
890 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
891 // aop->size = getSize( sym->type );
894 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
895 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
898 if(!pic16_allocDirReg (IC_LEFT(ic)))
902 if(IN_DIRSPACE( space ))
904 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
905 aop->size = FPTRSIZE;
906 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
907 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
908 else if(sym->onStack) {
911 if(SPEC_SCLS(sym->etype) == S_PDATA) {
912 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
913 aop->size = FPTRSIZE;
918 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
920 /* if it is in code space */
921 if (IN_CODESPACE(space))
927 /*-----------------------------------------------------------------*/
928 /* aopForRemat - rematerialzes an object */
929 /*-----------------------------------------------------------------*/
930 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
932 symbol *sym = OP_SYMBOL(op);
934 iCode *ic = NULL, *oldic;
935 asmop *aop = newAsmop(AOP_PCODE);
942 ic = sym->rematiCode;
944 if(IS_OP_POINTER(op)) {
945 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
948 // if(!result) /* fixme-vr */
952 // pic16_emitpcomment("ic: %s\n", printILine(ic));
955 val += (int) operandLitValue(IC_RIGHT(ic));
956 } else if (ic->op == '-') {
957 val -= (int) operandLitValue(IC_RIGHT(ic));
961 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
964 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
967 if(!op->isaddr)viaimmd++; else viaimmd=0;
969 /* set the following if to 1 to revert to good old immediate code */
970 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
973 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
975 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
978 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
980 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
983 PCOI(aop->aopu.pcop)->index = val;
985 aop->size = getSize( sym->type );
987 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
989 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
990 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
992 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
996 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
997 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
999 val, IS_PTR_CONST(operandType(op)));
1001 val, IS_CODEPTR(operandType(op)));
1004 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1006 pic16_allocDirReg (IC_LEFT(ic));
1008 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1015 static int aopIdx (asmop *aop, int offset)
1020 if(aop->type != AOP_REG)
1023 return aop->aopu.aop_reg[offset]->rIdx;
1028 /*-----------------------------------------------------------------*/
1029 /* regsInCommon - two operands have some registers in common */
1030 /*-----------------------------------------------------------------*/
1031 static bool regsInCommon (operand *op1, operand *op2)
1033 symbol *sym1, *sym2;
1036 /* if they have registers in common */
1037 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1040 sym1 = OP_SYMBOL(op1);
1041 sym2 = OP_SYMBOL(op2);
1043 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1046 for (i = 0 ; i < sym1->nRegs ; i++) {
1051 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1055 if (sym2->regs[j] == sym1->regs[i])
1063 /*-----------------------------------------------------------------*/
1064 /* operandsEqu - equivalent */
1065 /*-----------------------------------------------------------------*/
1066 static bool operandsEqu ( operand *op1, operand *op2)
1068 symbol *sym1, *sym2;
1070 /* if they not symbols */
1071 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1074 sym1 = OP_SYMBOL(op1);
1075 sym2 = OP_SYMBOL(op2);
1077 /* if both are itemps & one is spilt
1078 and the other is not then false */
1079 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1080 sym1->isspilt != sym2->isspilt )
1083 /* if they are the same */
1087 if (sym1->rname[0] && sym2->rname[0]
1088 && strcmp (sym1->rname, sym2->rname) == 0)
1092 /* if left is a tmp & right is not */
1093 if (IS_ITEMP(op1) &&
1096 (sym1->usl.spillLoc == sym2))
1099 if (IS_ITEMP(op2) &&
1103 (sym2->usl.spillLoc == sym1))
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_sameRegs - two asmops have the same registers */
1111 /*-----------------------------------------------------------------*/
1112 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1119 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1120 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1122 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1124 if (aop1->type != AOP_REG ||
1125 aop2->type != AOP_REG )
1128 /* This is a bit too restrictive if one is a subset of the other...
1129 if (aop1->size != aop2->size )
1133 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1134 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1136 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1137 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1144 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1146 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1147 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1149 if(aop1 == aop2)return TRUE;
1150 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1152 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_aopOp - allocates an asmop for an operand : */
1160 /*-----------------------------------------------------------------*/
1161 void pic16_aopOp (operand *op, iCode *ic, bool result)
1170 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1172 /* if this a literal */
1173 if (IS_OP_LITERAL(op)) {
1174 op->aop = aop = newAsmop(AOP_LIT);
1175 aop->aopu.aop_lit = op->operand.valOperand;
1176 aop->size = getSize(operandType(op));
1181 sym_link *type = operandType(op);
1183 if(IS_PTR_CONST(type))
1185 if(IS_CODEPTR(type))
1187 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1190 /* if already has a asmop then continue */
1194 /* if the underlying symbol has a aop */
1195 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1196 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1197 op->aop = OP_SYMBOL(op)->aop;
1201 /* if this is a true symbol */
1202 if (IS_TRUE_SYMOP(op)) {
1203 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1204 op->aop = aopForSym(ic, op, result);
1208 /* this is a temporary : this has
1214 e) can be a return use only */
1216 sym = OP_SYMBOL(op);
1218 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1219 /* if the type is a conditional */
1220 if (sym->regType == REG_CND) {
1221 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1226 /* if it is spilt then two situations
1228 b) has a spill location */
1229 if (sym->isspilt || sym->nRegs == 0) {
1231 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1232 DEBUGpic16_emitcode(";","%d",__LINE__);
1233 /* rematerialize it NOW */
1236 sym->aop = op->aop = aop = aopForRemat (op, result);
1237 // aop->size = getSize(sym->type);
1238 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1245 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1246 aop->size = getSize(sym->type);
1247 for ( i = 0 ; i < 1 ; i++ ) {
1248 aop->aopu.aop_str[i] = accUse[i];
1249 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1251 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1252 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1260 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1261 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1262 //pic16_allocDirReg (IC_LEFT(ic));
1263 aop->size = getSize(sym->type);
1268 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1269 aop->size = getSize(sym->type);
1270 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1271 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1273 DEBUGpic16_emitcode(";","%d",__LINE__);
1277 /* else spill location */
1278 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1279 /* force a new aop if sizes differ */
1280 sym->usl.spillLoc->aop = NULL;
1284 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1285 __FUNCTION__,__LINE__,
1286 sym->usl.spillLoc->rname,
1287 sym->rname, sym->usl.spillLoc->offset);
1290 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1291 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1295 sym->usl.spillLoc->offset, op);
1297 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1298 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1299 assert (getSize(sym->type) <= 1);
1300 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1302 aop->size = getSize(sym->type);
1308 sym_link *type = operandType(op);
1310 if(IS_PTR_CONST(type))
1312 if(IS_CODEPTR(type))
1314 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1317 /* must be in a register */
1318 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1319 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1320 aop->size = sym->nRegs;
1321 for ( i = 0 ; i < sym->nRegs ;i++)
1322 aop->aopu.aop_reg[i] = sym->regs[i];
1325 /*-----------------------------------------------------------------*/
1326 /* pic16_freeAsmop - free up the asmop given to an operand */
1327 /*----------------------------------------------------------------*/
1328 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1345 /* depending on the asmop type only three cases need work AOP_RO
1346 , AOP_R1 && AOP_STK */
1348 switch (aop->type) {
1350 if (_G.fsr0Pushed ) {
1352 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1353 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1354 // pic16_emitcode ("pop","ar0");
1358 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1362 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1368 pic16_emitcode ("pop","ar0");
1372 bitVectUnSetBit(ic->rUsed,R0_IDX);
1378 pic16_emitcode ("pop","ar1");
1382 bitVectUnSetBit(ic->rUsed,R1_IDX);
1389 /* we must store the result on stack */
1390 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1391 // operands on stack are accessible via "FSR2 + index" with index
1392 // starting at 2 for arguments and growing from 0 downwards for
1393 // local variables (index == 0 is not assigned so we add one here)
1394 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1399 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1400 for(i=0;i<aop->size;i++) {
1401 /* initialise for stack access via frame pointer */
1402 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1404 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1407 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1411 for(i=0;i<aop->size;i++) {
1412 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1414 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1415 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1426 int stk = aop->aopu.aop_stk + aop->size;
1427 bitVectUnSetBit(ic->rUsed,R0_IDX);
1428 bitVectUnSetBit(ic->rUsed,R1_IDX);
1430 getFreePtr(ic,&aop,FALSE);
1432 if (options.stack10bit)
1434 /* I'm not sure what to do here yet... */
1437 "*** Warning: probably generating bad code for "
1438 "10 bit stack mode.\n");
1442 pic16_emitcode ("mov","a,_bp");
1443 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1444 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1446 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1450 pic16_emitcode("pop","acc");
1451 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1453 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1456 pic16_freeAsmop(op,NULL,ic,TRUE);
1458 pic16_emitcode("pop","ar0");
1463 pic16_emitcode("pop","ar1");
1473 /* all other cases just dealloc */
1477 OP_SYMBOL(op)->aop = NULL;
1478 /* if the symbol has a spill */
1480 SPIL_LOC(op)->aop = NULL;
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_aopGet - for fetching value of the aop */
1487 /*-----------------------------------------------------------------*/
1488 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1493 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1495 /* offset is greater than size then zero */
1496 if (offset > (aop->size - 1) &&
1497 aop->type != AOP_LIT)
1500 /* depending on type */
1501 switch (aop->type) {
1505 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1506 rs = Safe_calloc(1, strlen(s)+1);
1511 /* if we need to increment it */
1512 while (offset > aop->coff)
1514 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1518 while (offset < aop->coff)
1520 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1526 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1527 return (dname ? "acc" : "a");
1529 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1530 rs = Safe_calloc (1, strlen (s) + 1);
1538 sprintf (s,"%s",aop->aopu.aop_immd);
1541 sprintf(s,"(%s >> %d)",
1546 aop->aopu.aop_immd);
1547 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1548 rs = Safe_calloc(1,strlen(s)+1);
1554 sprintf(s,"(%s + %d)",
1557 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1559 sprintf(s,"%s",aop->aopu.aop_dir);
1560 rs = Safe_calloc(1,strlen(s)+1);
1565 return aop->aopu.aop_reg[offset]->name;
1568 return aop->aopu.aop_dir;
1571 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1572 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1574 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1575 rs = Safe_strdup("WREG");
1579 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1580 rs = Safe_calloc(1,strlen(s)+1);
1585 aop->coff = offset ;
1587 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1590 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1591 aop->type = AOP_ACC;
1592 return Safe_strdup("_WREG");
1594 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1596 return aop->aopu.aop_str[offset];
1600 pCodeOp *pcop = aop->aopu.pcop;
1601 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1603 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1604 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1606 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1608 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1611 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1614 rs = Safe_calloc(1,strlen(s)+1);
1620 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1622 sprintf(s,"(%s + %d)",
1626 sprintf(s,"%s",aop->aopu.aop_dir);
1627 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1628 rs = Safe_calloc(1,strlen(s)+1);
1634 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1638 // pCodeOp *pcop = aop->aop
1643 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1644 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1645 "aopget got unsupported aop->type");
1651 /* lock has the following meaning: When allocating temporary registers
1652 * for stack variables storage, the value of the temporary register is
1653 * saved on stack. Its value is restored at the end. This procedure is
1654 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1655 * a possibility that before a call to pic16_aopOp, a temporary register
1656 * is allocated for a while and it is freed after some time, this will
1657 * mess the stack and values will not be restored properly. So use lock=1
1658 * to allocate temporary registers used internally by the programmer, and
1659 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1660 * to inform the compiler developer about a possible bug. This is an internal
1661 * feature for developing the compiler -- VR */
1663 int _TempReg_lock = 0;
1664 /*-----------------------------------------------------------------*/
1665 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1666 /*-----------------------------------------------------------------*/
1667 pCodeOp *pic16_popGetTempReg(int lock)
1672 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1674 // werror(W_POSSBUG2, __FILE__, __LINE__);
1677 _TempReg_lock += lock;
1687 /* this code might seem better but it does the *same* job with
1688 * the old code, it all depends on ralloc.c to get a free/unused
1692 while(i < pic16_nRegs) {
1693 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1694 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1695 if((!rr || (rr && rr->isFree))
1696 && !bitVectBitValue(cfunc->regsUsed, i)) {
1697 pcop = pic16_newpCodeOpReg( i );
1698 PCOR(pcop)->r->wasUsed = 1;
1699 PCOR(pcop)->r->isFree = 0;
1706 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1710 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1711 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1712 PCOR(pcop)->r->wasUsed=1;
1713 PCOR(pcop)->r->isFree=0;
1715 /* push value on stack */
1716 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1727 /* is not part of f, but don't save if */
1729 /*-----------------------------------------------------------------*/
1730 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1736 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1739 // werror(W_POSSBUG2, __FILE__, __LINE__);
1742 _TempReg_lock += lock;
1747 i = bitVectFirstBit(f);
1750 /* bypass registers that are used by function */
1751 if(!bitVectBitValue(f, i)) {
1753 /* bypass registers that are already allocated for stack access */
1754 if(!bitVectBitValue(v, i)) {
1756 // debugf("getting register rIdx = %d\n", i);
1757 /* ok, get the operand */
1758 pcop = pic16_newpCodeOpReg( i );
1760 /* should never by NULL */
1761 assert( pcop != NULL );
1765 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1768 PCOR(pcop)->r->wasUsed=1;
1769 PCOR(pcop)->r->isFree=0;
1775 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1777 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1778 /* already used in previous steps, break */
1785 /* caller takes care of the following */
1786 // bitVectSetBit(v, i);
1789 /* push value on stack */
1790 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1791 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1807 /*-----------------------------------------------------------------*/
1808 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1809 /*-----------------------------------------------------------------*/
1810 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1814 _TempReg_lock -= lock;
1816 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1817 PCOR(pcop)->r->isFree = 1;
1819 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLabel(int key)
1828 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1833 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1836 /*-----------------------------------------------------------------*/
1837 /* pic16_popCopyReg - copy a pcode operator */
1838 /*-----------------------------------------------------------------*/
1839 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1843 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1844 memcpy (pcor, pc, sizeof (pCodeOpReg));
1845 pcor->r->wasUsed = 1;
1847 //pcor->pcop.type = pc->pcop.type;
1849 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1850 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1852 pcor->pcop.name = NULL;
1855 //pcor->rIdx = pc->rIdx;
1856 //pcor->r->wasUsed=1;
1857 //pcor->instance = pc->instance;
1859 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popGetLit - asm operator to pcode operator conversion */
1866 /*-----------------------------------------------------------------*/
1867 pCodeOp *pic16_popGetLit(int lit)
1869 return pic16_newpCodeOpLit(lit);
1872 /* Allow for 12 bit literals (LFSR x, <here!>). */
1873 pCodeOp *pic16_popGetLit12(int lit)
1875 return pic16_newpCodeOpLit12(lit);
1878 /*-----------------------------------------------------------------*/
1879 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1880 /*-----------------------------------------------------------------*/
1881 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1883 return pic16_newpCodeOpLit2(lit, arg2);
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1892 return pic16_newpCodeOpImmd(name, offset,index, 0);
1896 /*-----------------------------------------------------------------*/
1897 /* pic16_popGet - asm operator to pcode operator conversion */
1898 /*-----------------------------------------------------------------*/
1899 pCodeOp *pic16_popGetWithString(char *str)
1905 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1909 pcop = pic16_newpCodeOp(str,PO_STR);
1914 /*-----------------------------------------------------------------*/
1915 /* pic16_popRegFromString - */
1916 /*-----------------------------------------------------------------*/
1917 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1920 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1921 pcop->type = PO_DIR;
1923 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1924 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1929 pcop->name = Safe_calloc(1,strlen(str)+1);
1930 strcpy(pcop->name,str);
1932 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1934 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1935 // PCOR(pcop)->r->wasUsed = 1;
1937 /* make sure that register doesn't exist,
1938 * and operand isn't NULL
1939 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1940 if((PCOR(pcop)->r == NULL)
1942 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1943 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1944 // __FUNCTION__, __LINE__, str, size, offset);
1946 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1947 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1950 PCOR(pcop)->instance = offset;
1955 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1959 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1960 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1962 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1963 PCOR(pcop)->rIdx = rIdx;
1964 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1966 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1968 PCOR(pcop)->r->isFree = 0;
1969 PCOR(pcop)->r->wasUsed = 1;
1971 pcop->type = PCOR(pcop)->r->pc_type;
1976 /*---------------------------------------------------------------------------------*/
1977 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1979 /*---------------------------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1985 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1987 /* comment the following check, so errors to throw up */
1988 // if(!pcop2)return NULL;
1990 temp = pic16_popGet(aop_dst, offset);
1991 pcop2->pcop2 = temp;
1998 /*--------------------------------------------------------------------------------.-*/
1999 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2000 /* VR 030601 , adapted by Hans Dorn */
2001 /*--------------------------------------------------------------------------------.-*/
2002 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2006 pcop2 = (pCodeOpReg2 *)src;
2014 /*---------------------------------------------------------------------------------*/
2015 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2016 /* movff instruction */
2017 /*---------------------------------------------------------------------------------*/
2018 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2023 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2024 pcop2->pcop2 = pic16_popCopyReg(dst);
2026 /* the pCodeOp may be already allocated */
2027 pcop2 = (pCodeOpReg2 *)(src);
2028 pcop2->pcop2 = (pCodeOp *)(dst);
2035 /*-----------------------------------------------------------------*/
2036 /* pic16_popGet - asm operator to pcode operator conversion */
2037 /*-----------------------------------------------------------------*/
2038 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2040 // char *s = buffer ;
2045 /* offset is greater than
2048 // if (offset > (aop->size - 1) &&
2049 // aop->type != AOP_LIT)
2050 // return NULL; //zero;
2052 /* depending on type */
2053 switch (aop->type) {
2058 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2059 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2065 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2066 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2067 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2068 PCOR(pcop)->r->wasUsed = 1;
2069 PCOR(pcop)->r->isFree = 0;
2071 PCOR(pcop)->instance = offset;
2072 pcop->type = PCOR(pcop)->r->pc_type;
2076 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2077 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2080 /* pCodeOp is already allocated from aopForSym */
2081 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2082 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2087 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2089 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2091 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2093 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2094 PCOR(pcop)->rIdx = rIdx;
2095 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2096 PCOR(pcop)->r->wasUsed=1;
2097 PCOR(pcop)->r->isFree=0;
2099 PCOR(pcop)->instance = offset;
2100 pcop->type = PCOR(pcop)->r->pc_type;
2101 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2105 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2106 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2112 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2113 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2117 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2118 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2124 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2125 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2127 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2129 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2130 // pcop->type = PO_GPR_REGISTER;
2131 PCOR(pcop)->rIdx = rIdx;
2132 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2133 PCOR(pcop)->r->wasUsed=1;
2134 PCOR(pcop)->r->isFree=0;
2136 PCOR(pcop)->instance = offset;
2137 pcop->type = PCOR(pcop)->r->pc_type;
2139 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2140 // rs = aop->aopu.aop_reg[offset]->name;
2141 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2146 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2148 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2149 PCOR(pcop)->instance = offset;
2150 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2151 //if(PCOR(pcop)->r == NULL)
2152 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2156 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2157 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2160 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2161 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2164 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2165 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2166 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2167 pcop->type = PCOR(pcop)->r->pc_type;
2168 pcop->name = PCOR(pcop)->r->name;
2174 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2176 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2177 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2178 switch( aop->aopu.pcop->type ) {
2179 case PO_DIR: PCOR(pcop)->instance += offset; break;
2180 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2185 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2186 assert( 0 ); /* should never reach here */;
2191 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2192 "pic16_popGet got unsupported aop->type");
2195 /*-----------------------------------------------------------------*/
2196 /* pic16_aopPut - puts a string for a aop */
2197 /*-----------------------------------------------------------------*/
2198 void pic16_aopPut (asmop *aop, char *s, int offset)
2205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2207 if (aop->size && offset > ( aop->size - 1)) {
2208 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2209 "pic16_aopPut got offset > aop->size");
2213 /* will assign value to value */
2214 /* depending on where it is ofcourse */
2215 switch (aop->type) {
2218 sprintf(d,"(%s + %d)",
2219 aop->aopu.aop_dir,offset);
2220 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2223 sprintf(d,"%s",aop->aopu.aop_dir);
2226 DEBUGpic16_emitcode(";","%d",__LINE__);
2228 pic16_emitcode("movf","%s,w",s);
2229 pic16_emitcode("movwf","%s",d);
2232 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2233 if(offset >= aop->size) {
2234 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2237 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2240 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2247 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2248 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2251 strcmp(s,"r0") == 0 ||
2252 strcmp(s,"r1") == 0 ||
2253 strcmp(s,"r2") == 0 ||
2254 strcmp(s,"r3") == 0 ||
2255 strcmp(s,"r4") == 0 ||
2256 strcmp(s,"r5") == 0 ||
2257 strcmp(s,"r6") == 0 ||
2258 strcmp(s,"r7") == 0 )
2259 pic16_emitcode("mov","%s,%s ; %d",
2260 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2264 if(strcmp(s,"W")==0 )
2265 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2267 pic16_emitcode("movwf","%s",
2268 aop->aopu.aop_reg[offset]->name);
2270 if(strcmp(s,zero)==0) {
2271 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2273 } else if(strcmp(s,"W")==0) {
2274 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2275 pcop->type = PO_GPR_REGISTER;
2277 PCOR(pcop)->rIdx = -1;
2278 PCOR(pcop)->r = NULL;
2280 DEBUGpic16_emitcode(";","%d",__LINE__);
2281 pcop->name = Safe_strdup(s);
2282 pic16_emitpcode(POC_MOVFW,pcop);
2283 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2284 } else if(strcmp(s,one)==0) {
2285 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2286 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2288 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2296 if (aop->type == AOP_DPTR2)
2302 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2303 "pic16_aopPut writting to code space");
2307 while (offset > aop->coff) {
2309 pic16_emitcode ("inc","dptr");
2312 while (offset < aop->coff) {
2314 pic16_emitcode("lcall","__decdptr");
2319 /* if not in accumulater */
2322 pic16_emitcode ("movx","@dptr,a");
2324 if (aop->type == AOP_DPTR2)
2332 while (offset > aop->coff) {
2334 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2336 while (offset < aop->coff) {
2338 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2344 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2349 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2351 if (strcmp(s,"r0") == 0 ||
2352 strcmp(s,"r1") == 0 ||
2353 strcmp(s,"r2") == 0 ||
2354 strcmp(s,"r3") == 0 ||
2355 strcmp(s,"r4") == 0 ||
2356 strcmp(s,"r5") == 0 ||
2357 strcmp(s,"r6") == 0 ||
2358 strcmp(s,"r7") == 0 ) {
2360 sprintf(buffer,"a%s",s);
2361 pic16_emitcode("mov","@%s,%s",
2362 aop->aopu.aop_ptr->name,buffer);
2364 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2369 if (strcmp(s,"a") == 0)
2370 pic16_emitcode("push","acc");
2372 pic16_emitcode("push","%s",s);
2377 /* if bit variable */
2378 if (!aop->aopu.aop_dir) {
2379 pic16_emitcode("clr","a");
2380 pic16_emitcode("rlc","a");
2383 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2386 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2389 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2391 lbl = newiTempLabel(NULL);
2393 if (strcmp(s,"a")) {
2396 pic16_emitcode("clr","c");
2397 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2398 pic16_emitcode("cpl","c");
2399 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2400 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2407 if (strcmp(aop->aopu.aop_str[offset],s))
2408 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2413 if (!offset && (strcmp(s,"acc") == 0))
2416 if (strcmp(aop->aopu.aop_str[offset],s))
2417 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2421 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2422 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2423 // "pic16_aopPut got unsupported aop->type");
2429 /*-----------------------------------------------------------------*/
2430 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2431 /*-----------------------------------------------------------------*/
2432 void pic16_mov2w (asmop *aop, int offset)
2434 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2437 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2439 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2442 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2444 if(is_LitAOp(src)) {
2445 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2446 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2448 if(pic16_sameRegsOfs(src, dst, offset))return;
2449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2450 pic16_popGet(dst, offset)));
2454 static void pic16_movLit2f(pCodeOp *pc, int lit)
2456 if (0 == (lit & 0x00ff))
2458 pic16_emitpcode (POC_CLRF, pc);
2459 } else if (0xff == (lit & 0x00ff))
2461 pic16_emitpcode (POC_SETF, pc);
2463 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2464 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2468 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2470 if(is_LitAOp(src)) {
2471 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2472 pic16_emitpcode(POC_MOVWF, dst);
2474 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2478 void pic16_testStackOverflow(void)
2480 #define GSTACK_TEST_NAME "_gstack_test"
2482 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2487 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2488 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2489 // strcpy(sym->rname, GSTACK_TEST_NAME);
2490 checkAddSym(&externs, sym);
2495 /* push pcop into stack */
2496 void pic16_pushpCodeOp(pCodeOp *pcop)
2498 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2499 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2500 if(pic16_options.gstack)
2501 pic16_testStackOverflow();
2505 /* pop pcop from stack */
2506 void pic16_poppCodeOp(pCodeOp *pcop)
2508 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2509 if(pic16_options.gstack)
2510 pic16_testStackOverflow();
2514 /*-----------------------------------------------------------------*/
2515 /* pushw - pushes wreg to stack */
2516 /*-----------------------------------------------------------------*/
2519 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2520 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2521 if(pic16_options.gstack)
2522 pic16_testStackOverflow();
2526 /*-----------------------------------------------------------------*/
2527 /* pushaop - pushes aop to stack */
2528 /*-----------------------------------------------------------------*/
2529 void pushaop(asmop *aop, int offset)
2531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2533 if(_G.resDirect)return;
2535 if(is_LitAOp(aop)) {
2536 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2539 pic16_emitpcode(POC_MOVFF,
2540 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2543 if(pic16_options.gstack)
2544 pic16_testStackOverflow();
2547 /*-----------------------------------------------------------------*/
2548 /* popaop - pops aop from stack */
2549 /*-----------------------------------------------------------------*/
2550 void popaop(asmop *aop, int offset)
2552 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2553 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2554 if(pic16_options.gstack)
2555 pic16_testStackOverflow();
2558 void popaopidx(asmop *aop, int offset, int index)
2562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2564 if(STACK_MODEL_LARGE)ofs++;
2566 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2567 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2568 if(pic16_options.gstack)
2569 pic16_testStackOverflow();
2572 #if !(USE_GENERIC_SIGNED_SHIFT)
2573 /*-----------------------------------------------------------------*/
2574 /* reAdjustPreg - points a register back to where it should */
2575 /*-----------------------------------------------------------------*/
2576 static void reAdjustPreg (asmop *aop)
2580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2582 if ((size = aop->size) <= 1)
2585 switch (aop->type) {
2589 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2593 if (aop->type == AOP_DPTR2)
2599 pic16_emitcode("lcall","__decdptr");
2602 if (aop->type == AOP_DPTR2)
2614 /*-----------------------------------------------------------------*/
2615 /* opIsGptr: returns non-zero if the passed operand is */
2616 /* a generic pointer type. */
2617 /*-----------------------------------------------------------------*/
2618 static int opIsGptr(operand *op)
2620 sym_link *type = operandType(op);
2622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2623 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2631 /*-----------------------------------------------------------------*/
2632 /* pic16_getDataSize - get the operand data size */
2633 /*-----------------------------------------------------------------*/
2634 int pic16_getDataSize(operand *op)
2636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2639 return AOP_SIZE(op);
2641 // tsd- in the pic port, the genptr size is 1, so this code here
2642 // fails. ( in the 8051 port, the size was 4).
2645 size = AOP_SIZE(op);
2646 if (size == GPTRSIZE)
2648 sym_link *type = operandType(op);
2649 if (IS_GENPTR(type))
2651 /* generic pointer; arithmetic operations
2652 * should ignore the high byte (pointer type).
2655 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2662 /*-----------------------------------------------------------------*/
2663 /* pic16_outAcc - output Acc */
2664 /*-----------------------------------------------------------------*/
2665 void pic16_outAcc(operand *result)
2668 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2669 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2672 size = pic16_getDataSize(result);
2674 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2677 /* unsigned or positive */
2679 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2684 /*-----------------------------------------------------------------*/
2685 /* pic16_outBitC - output a bit C */
2686 /* Move to result the value of Carry flag -- VR */
2687 /*-----------------------------------------------------------------*/
2688 void pic16_outBitC(operand *result)
2692 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2694 /* if the result is bit */
2695 if (AOP_TYPE(result) == AOP_CRY) {
2696 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2697 pic16_aopPut(AOP(result),"c",0);
2700 i = AOP_SIZE(result);
2702 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2704 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2708 /*-----------------------------------------------------------------*/
2709 /* pic16_outBitOp - output a bit from Op */
2710 /* Move to result the value of set/clr op -- VR */
2711 /*-----------------------------------------------------------------*/
2712 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2718 /* if the result is bit */
2719 if (AOP_TYPE(result) == AOP_CRY) {
2720 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2721 pic16_aopPut(AOP(result),"c",0);
2724 i = AOP_SIZE(result);
2726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2728 pic16_emitpcode(POC_RRCF, pcop);
2729 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2733 /*-----------------------------------------------------------------*/
2734 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2735 /*-----------------------------------------------------------------*/
2736 void pic16_toBoolean(operand *oper)
2738 int size = AOP_SIZE(oper) - 1;
2741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2743 if ( AOP_TYPE(oper) != AOP_ACC) {
2744 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2747 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2751 /*-----------------------------------------------------------------*/
2752 /* genUminusFloat - unary minus for floating points */
2753 /*-----------------------------------------------------------------*/
2754 static void genUminusFloat(operand *op,operand *result)
2756 int size ,offset =0 ;
2759 /* for this we just need to flip the
2760 first it then copy the rest in place */
2761 size = AOP_SIZE(op);
2762 assert( size == AOP_SIZE(result) );
2765 pic16_mov2f(AOP(result), AOP(op), offset);
2769 /* toggle the MSB's highest bit */
2770 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2773 /*-----------------------------------------------------------------*/
2774 /* genUminus - unary minus code generation */
2775 /*-----------------------------------------------------------------*/
2776 static void genUminus (iCode *ic)
2779 sym_link *optype, *rtype;
2786 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2787 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2789 /* if both in bit space then special case */
2790 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2791 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2793 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2794 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2795 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2799 optype = operandType(IC_LEFT(ic));
2800 rtype = operandType(IC_RESULT(ic));
2803 /* if float then do float stuff */
2804 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2805 if(IS_FIXED(optype))
2806 debugf("implement fixed16x16 type\n", 0);
2808 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2812 /* otherwise subtract from zero by taking the 2's complement */
2813 size = AOP_SIZE(IC_LEFT(ic));
2814 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2815 label = newiTempLabel ( NULL );
2817 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2818 for (i=size-1; i > 0; i--) {
2819 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2821 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2822 for (i=1; i < size; i++) {
2823 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2824 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2827 for (i=size-1; i >= 0; i--) {
2828 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2829 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2832 for (i=0; i < size-2; i++) {
2833 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2834 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2836 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2838 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2841 pic16_emitpLabel (label->key);
2844 /* release the aops */
2845 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2846 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2850 /*-----------------------------------------------------------------*/
2851 /* saveRegisters - will look for a call and save the registers */
2852 /*-----------------------------------------------------------------*/
2853 static void saveRegisters(iCode *lic)
2860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2862 for (ic = lic ; ic ; ic = ic->next)
2863 if (ic->op == CALL || ic->op == PCALL)
2867 fprintf(stderr,"found parameter push with no function call\n");
2871 /* if the registers have been saved already then
2873 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2876 /* find the registers in use at this time
2877 and push them away to safety */
2878 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2882 if (options.useXstack) {
2883 if (bitVectBitValue(rsave,R0_IDX))
2884 pic16_emitcode("mov","b,r0");
2885 pic16_emitcode("mov","r0,%s",spname);
2886 for (i = 0 ; i < pic16_nRegs ; i++) {
2887 if (bitVectBitValue(rsave,i)) {
2889 pic16_emitcode("mov","a,b");
2891 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2892 pic16_emitcode("movx","@r0,a");
2893 pic16_emitcode("inc","r0");
2896 pic16_emitcode("mov","%s,r0",spname);
2897 if (bitVectBitValue(rsave,R0_IDX))
2898 pic16_emitcode("mov","r0,b");
2900 //for (i = 0 ; i < pic16_nRegs ; i++) {
2901 // if (bitVectBitValue(rsave,i))
2902 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2905 dtype = operandType(IC_LEFT(ic));
2906 if (currFunc && dtype &&
2907 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2908 IFFUNC_ISISR(currFunc->type) &&
2911 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2914 /*-----------------------------------------------------------------*/
2915 /* unsaveRegisters - pop the pushed registers */
2916 /*-----------------------------------------------------------------*/
2917 static void unsaveRegisters (iCode *ic)
2922 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2923 /* find the registers in use at this time
2924 and push them away to safety */
2925 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2928 if (options.useXstack) {
2929 pic16_emitcode("mov","r0,%s",spname);
2930 for (i = pic16_nRegs ; i >= 0 ; i--) {
2931 if (bitVectBitValue(rsave,i)) {
2932 pic16_emitcode("dec","r0");
2933 pic16_emitcode("movx","a,@r0");
2935 pic16_emitcode("mov","b,a");
2937 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2941 pic16_emitcode("mov","%s,r0",spname);
2942 if (bitVectBitValue(rsave,R0_IDX))
2943 pic16_emitcode("mov","r0,b");
2945 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2946 // if (bitVectBitValue(rsave,i))
2947 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2954 /*-----------------------------------------------------------------*/
2956 /*-----------------------------------------------------------------*/
2957 static void pushSide(operand * oper, int size)
2960 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2962 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2963 if (AOP_TYPE(oper) != AOP_REG &&
2964 AOP_TYPE(oper) != AOP_DIR &&
2966 pic16_emitcode("mov","a,%s",l);
2967 pic16_emitcode("push","acc");
2969 pic16_emitcode("push","%s",l);
2974 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2976 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2977 pic16_emitpcode(POC_MOVFW, src);
2978 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2980 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2981 src, pic16_popGet(AOP(op), offset)));
2986 /*-----------------------------------------------------------------*/
2987 /* assignResultValue - assign results to oper, rescall==1 is */
2988 /* called from genCall() or genPcall() */
2989 /*-----------------------------------------------------------------*/
2990 static void assignResultValue(operand * oper, int rescall)
2992 int size = AOP_SIZE(oper);
2996 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2997 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3000 /* assign result from a call/pcall function() */
3002 /* function results are stored in a special order,
3003 * see top of file with Function return policy, or manual */
3006 /* 8-bits, result in WREG */
3007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3010 /* 16-bits, result in PRODL:WREG */
3011 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3015 /* 24-bits, result in PRODH:PRODL:WREG */
3016 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3020 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3021 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3025 /* >32-bits, result on stack, and FSR0 points to beginning.
3026 * Fix stack when done */
3028 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3030 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3031 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3033 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3038 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3039 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3040 if(STACK_MODEL_LARGE) {
3042 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3046 int areg = 0; /* matching argument register */
3048 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3049 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3052 /* its called from genReceive (probably) -- VR */
3053 /* I hope this code will not be called from somewhere else in the future!
3054 * We manually set the pseudo stack pointer in genReceive. - dw
3056 if(!GpsuedoStkPtr && _G.useWreg) {
3057 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3059 /* The last byte in the assignment is in W */
3060 if(areg <= GpsuedoStkPtr) {
3062 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3064 // debugf("receive from WREG\n", 0);
3066 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3069 _G.stack_lat = AOP_SIZE(oper)-1;
3074 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3075 // debugf("receive from STACK\n", 0);
3082 /*-----------------------------------------------------------------*/
3083 /* genIpush - generate code for pushing this gets a little complex */
3084 /*-----------------------------------------------------------------*/
3085 static void genIpush (iCode *ic)
3087 // int size, offset=0;
3090 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3093 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3095 /* send to stack as normal */
3096 addSet(&_G.sendSet,ic);
3097 // addSetHead(&_G.sendSet,ic);
3098 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3103 int size, offset = 0 ;
3107 /* if this is not a parm push : ie. it is spill push
3108 and spill push is always done on the local stack */
3109 if (!ic->parmPush) {
3111 /* and the item is spilt then do nothing */
3112 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3115 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3116 size = AOP_SIZE(IC_LEFT(ic));
3117 /* push it on the stack */
3119 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3124 pic16_emitcode("push","%s",l);
3129 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3133 /*-----------------------------------------------------------------*/
3134 /* genIpop - recover the registers: can happen only for spilling */
3135 /*-----------------------------------------------------------------*/
3136 static void genIpop (iCode *ic)
3139 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3144 /* if the temp was not pushed then */
3145 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3148 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3149 size = AOP_SIZE(IC_LEFT(ic));
3152 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3155 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3160 /*-----------------------------------------------------------------*/
3161 /* unsaverbank - restores the resgister bank from stack */
3162 /*-----------------------------------------------------------------*/
3163 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3165 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3173 if (options.useXstack) {
3175 r = getFreePtr(ic,&aop,FALSE);
3178 pic16_emitcode("mov","%s,_spx",r->name);
3179 pic16_emitcode("movx","a,@%s",r->name);
3180 pic16_emitcode("mov","psw,a");
3181 pic16_emitcode("dec","%s",r->name);
3184 pic16_emitcode ("pop","psw");
3187 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3188 if (options.useXstack) {
3189 pic16_emitcode("movx","a,@%s",r->name);
3190 //pic16_emitcode("mov","(%s+%d),a",
3191 // regspic16[i].base,8*bank+regspic16[i].offset);
3192 pic16_emitcode("dec","%s",r->name);
3195 pic16_emitcode("pop",""); //"(%s+%d)",
3196 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3199 if (options.useXstack) {
3201 pic16_emitcode("mov","_spx,%s",r->name);
3202 pic16_freeAsmop(NULL,aop,ic,TRUE);
3208 /*-----------------------------------------------------------------*/
3209 /* saverbank - saves an entire register bank on the stack */
3210 /*-----------------------------------------------------------------*/
3211 static void saverbank (int bank, iCode *ic, bool pushPsw)
3213 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3220 if (options.useXstack) {
3223 r = getFreePtr(ic,&aop,FALSE);
3224 pic16_emitcode("mov","%s,_spx",r->name);
3228 for (i = 0 ; i < pic16_nRegs ;i++) {
3229 if (options.useXstack) {
3230 pic16_emitcode("inc","%s",r->name);
3231 //pic16_emitcode("mov","a,(%s+%d)",
3232 // regspic16[i].base,8*bank+regspic16[i].offset);
3233 pic16_emitcode("movx","@%s,a",r->name);
3235 pic16_emitcode("push","");// "(%s+%d)",
3236 //regspic16[i].base,8*bank+regspic16[i].offset);
3240 if (options.useXstack) {
3241 pic16_emitcode("mov","a,psw");
3242 pic16_emitcode("movx","@%s,a",r->name);
3243 pic16_emitcode("inc","%s",r->name);
3244 pic16_emitcode("mov","_spx,%s",r->name);
3245 pic16_freeAsmop (NULL,aop,ic,TRUE);
3248 pic16_emitcode("push","psw");
3250 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3258 static int wparamCmp(void *p1, void *p2)
3260 return (!strcmp((char *)p1, (char *)p2));
3263 int inWparamList(char *s)
3265 return isinSetWith(wparamList, s, wparamCmp);
3269 /*-----------------------------------------------------------------*/
3270 /* genCall - generates a call statement */
3271 /*-----------------------------------------------------------------*/
3272 static void genCall (iCode *ic)
3282 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3283 /* if caller saves & we have not saved then */
3284 // if (!ic->regsSaved)
3285 // saveRegisters(ic);
3287 /* initialise stackParms for IPUSH pushes */
3288 // stackParms = psuedoStkPtr;
3289 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3290 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3291 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3294 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3297 /* if send set is not empty the assign */
3300 int psuedoStkPtr=-1;
3301 int firstTimeThruLoop = 1;
3304 /* reverse sendSet if function is not reentrant */
3305 if(!IFFUNC_ISREENT(ftype))
3306 _G.sendSet = reverseSet(_G.sendSet);
3308 /* First figure how many parameters are getting passed */
3312 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3316 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3317 size = AOP_SIZE(IC_LEFT(sic));
3321 /* pass the last byte through WREG */
3325 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3326 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3327 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3329 if(!firstTimeThruLoop) {
3330 /* If this is not the first time we've been through the loop
3331 * then we need to save the parameter in a temporary
3332 * register. The last byte of the last parameter is
3336 // --psuedoStkPtr; // sanity check
3340 firstTimeThruLoop=0;
3342 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3347 /* all arguments are passed via stack */
3351 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3352 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3353 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3355 // pushaop(AOP(IC_LEFT(sic)), size);
3356 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3363 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3367 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3368 pushw(); /* save last parameter to stack if functions has varargs */
3372 } else use_wreg = 0;
3374 _G.stackRegSet = _G.sendSet;
3379 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3383 /* if we need to assign a result value */
3384 if ((IS_ITEMP(IC_RESULT(ic))
3385 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3386 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3387 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3390 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3393 assignResultValue(IC_RESULT(ic), 1);
3395 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3396 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3398 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3401 if(!stackParms && ic->parmBytes) {
3402 stackParms = ic->parmBytes;
3405 stackParms -= use_wreg;
3408 if(stackParms == 1) {
3409 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3411 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3412 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3414 if(STACK_MODEL_LARGE) {
3416 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3421 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3424 /* adjust the stack for parameters if required */
3425 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3428 /* if register bank was saved then pop them */
3430 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3432 /* if we hade saved some registers then unsave them */
3433 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3434 unsaveRegisters (ic);
3440 /*-----------------------------------------------------------------*/
3441 /* genPcall - generates a call by pointer statement */
3442 /* new version, created from genCall - HJD */
3443 /*-----------------------------------------------------------------*/
3444 static void genPcall (iCode *ic)
3448 symbol *retlbl = newiTempLabel(NULL);
3449 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3453 fntype = operandType( IC_LEFT(ic) )->next;
3455 /* if send set is not empty the assign */
3458 int psuedoStkPtr=-1;
3460 /* reverse sendSet if function is not reentrant */
3461 if(!IFFUNC_ISREENT(fntype))
3462 _G.sendSet = reverseSet(_G.sendSet);
3466 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3469 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3470 size = AOP_SIZE(IC_LEFT(sic));
3473 /* all parameters are passed via stack, since WREG is clobbered
3474 * by the calling sequence */
3476 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3477 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3478 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3480 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3484 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3487 _G.stackRegSet = _G.sendSet;
3491 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3493 // push return address
3494 // push $ on return stack, then replace with retlbl
3496 /* Thanks to Thorsten Klose for pointing out that the following
3497 * snippet should be interrupt safe */
3498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3499 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3501 pic16_emitpcodeNULLop(POC_PUSH);
3503 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3504 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3505 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3506 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3507 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3508 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3511 /* restore interrupt control register */
3512 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3513 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3515 /* make the call by writing the pointer into pc */
3516 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3517 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3519 // note: MOVFF to PCL not allowed
3520 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3521 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3524 /* return address is here: (X) */
3525 pic16_emitpLabelFORCE(retlbl->key);
3527 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3530 /* if we need assign a result value */
3531 if ((IS_ITEMP(IC_RESULT(ic))
3532 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3533 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3534 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3537 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3540 assignResultValue(IC_RESULT(ic), 1);
3542 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3543 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3545 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3548 // stackParms -= use_wreg;
3551 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3552 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3553 if(STACK_MODEL_LARGE) {
3555 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3560 /*-----------------------------------------------------------------*/
3561 /* resultRemat - result is rematerializable */
3562 /*-----------------------------------------------------------------*/
3563 static int resultRemat (iCode *ic)
3565 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3566 if (SKIP_IC(ic) || ic->op == IFX)
3569 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3570 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3571 if (sym->remat && !POINTER_SET(ic))
3578 #if defined(__BORLANDC__) || defined(_MSC_VER)
3579 #define STRCASECMP stricmp
3581 #define STRCASECMP strcasecmp
3585 /*-----------------------------------------------------------------*/
3586 /* inExcludeList - return 1 if the string is in exclude Reg list */
3587 /*-----------------------------------------------------------------*/
3588 static bool inExcludeList(char *s)
3590 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3594 if (options.excludeRegs[i] &&
3595 STRCASECMP(options.excludeRegs[i],"none") == 0)
3598 for ( i = 0 ; options.excludeRegs[i]; i++) {
3599 if (options.excludeRegs[i] &&
3600 STRCASECMP(s,options.excludeRegs[i]) == 0)
3607 /*-----------------------------------------------------------------*/
3608 /* genFunction - generated code for function entry */
3609 /*-----------------------------------------------------------------*/
3610 static void genFunction (iCode *ic)
3616 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3618 pic16_labelOffset += (max_key+4);
3623 ftype = operandType(IC_LEFT(ic));
3624 sym = OP_SYMBOL(IC_LEFT(ic));
3626 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3627 /* create an absolute section at the interrupt vector:
3628 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3633 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3635 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3636 sprintf(asymname, "ivec_%s", sym->name);
3638 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3640 /* when an interrupt is declared as naked, do not emit the special
3641 * wrapper segment at vector address. The user should take care for
3642 * this instead. -- VR */
3644 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3645 asym = newSymbol(asymname, 0);
3646 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3647 pic16_addpBlock( apb );
3649 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3650 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3651 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3652 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3653 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3655 /* mark the end of this tiny function */
3656 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3658 sprintf(asymname, "%s", sym->rname);
3664 abSym = Safe_calloc(1, sizeof(absSym));
3665 strcpy(abSym->name, asymname);
3667 switch( FUNC_INTNO(sym->type) ) {
3668 case 0: abSym->address = 0x000000; break;
3669 case 1: abSym->address = 0x000008; break;
3670 case 2: abSym->address = 0x000018; break;
3673 // fprintf(stderr, "no interrupt number is given\n");
3674 abSym->address = -1; break;
3677 /* relocate interrupt vectors if needed */
3678 if(abSym->address != -1)
3679 abSym->address += pic16_options.ivt_loc;
3681 addSet(&absSymSet, abSym);
3685 /* create the function header */
3686 pic16_emitcode(";","-----------------------------------------");
3687 pic16_emitcode(";"," function %s",sym->name);
3688 pic16_emitcode(";","-----------------------------------------");
3690 pic16_emitcode("","%s:",sym->rname);
3691 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3696 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3697 if(!strcmp(ab->name, sym->rname)) {
3698 pic16_pBlockConvert2Absolute(pb);
3704 if(IFFUNC_ISNAKED(ftype)) {
3705 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3709 /* if critical function then turn interrupts off */
3710 if (IFFUNC_ISCRITICAL(ftype)) {
3711 //pic16_emitcode("clr","ea");
3714 currFunc = sym; /* update the currFunc symbol */
3715 _G.fregsUsed = sym->regsUsed;
3716 _G.sregsAlloc = newBitVect(128);
3719 /* if this is an interrupt service routine then
3720 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3721 if (IFFUNC_ISISR(sym->type)) {
3722 _G.usefastretfie = 1; /* use shadow registers by default */
3724 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3725 if(!FUNC_ISSHADOWREGS(sym->type)) {
3726 /* do not save WREG,STATUS,BSR for high priority interrupts
3727 * because they are stored in the hardware shadow registers already */
3728 _G.usefastretfie = 0;
3729 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3730 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3731 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3734 /* these should really be optimized somehow, because not all
3735 * interrupt handlers modify them */
3736 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3737 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3738 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3739 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3741 // pic16_pBlockConvert2ISR(pb);
3744 /* emit code to setup stack frame if user enabled,
3745 * and function is not main() */
3747 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3748 if(strcmp(sym->name, "main")) {
3750 || !options.ommitFramePtr
3752 || IFFUNC_ARGS(sym->type)
3753 || FUNC_HASSTACKPARM(sym->etype)
3755 /* setup the stack frame */
3756 if(STACK_MODEL_LARGE)
3757 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3758 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3760 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3761 if(STACK_MODEL_LARGE)
3762 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3766 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3769 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3771 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3772 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3774 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3777 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3778 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3785 /* if callee-save to be used for this function
3786 * then save the registers being used in this function */
3787 // if (IFFUNC_CALLEESAVES(sym->type))
3788 if(strcmp(sym->name, "main")) {
3791 /* if any registers used */
3792 if (sym->regsUsed) {
3793 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3796 /* save the registers used */
3797 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3798 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3799 if (bitVectBitValue(sym->regsUsed,i)) {
3801 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3803 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3806 if(!pic16_regWithIdx(i)->wasUsed) {
3807 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3808 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3809 pic16_regWithIdx(i)->wasUsed = 1;
3816 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3817 for(i=0;i<sym->regsUsed->size;i++) {
3818 if(bitVectBitValue(sym->regsUsed, i)) {
3823 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3826 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3831 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3832 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3835 /*-----------------------------------------------------------------*/
3836 /* genEndFunction - generates epilogue for functions */
3837 /*-----------------------------------------------------------------*/
3838 static void genEndFunction (iCode *ic)
3840 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3844 if(IFFUNC_ISNAKED(sym->type)) {
3845 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3851 /* add code for ISCRITICAL */
3852 if(IFFUNC_ISCRITICAL(sym->type)) {
3853 /* if critical function, turn on interrupts */
3855 /* TODO: add code here -- VR */
3858 // sym->regsUsed = _G.fregsUsed;
3860 /* now we need to restore the registers */
3861 /* if any registers used */
3863 /* first restore registers that might be used for stack access */
3864 if(_G.sregsAllocSet) {
3867 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3868 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3869 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3873 if (strcmp(sym->name, "main") && sym->regsUsed) {
3876 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3877 /* restore registers used */
3878 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3879 for ( i = sym->regsUsed->size; i >= 0; i--) {
3880 if (bitVectBitValue(sym->regsUsed,i)) {
3881 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3885 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3890 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3892 if (sym->stack == 1) {
3893 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3894 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896 // we have to add more than one...
3897 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3898 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3899 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3901 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3902 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3903 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3907 if(strcmp(sym->name, "main")) {
3909 || !options.ommitFramePtr
3911 || IFFUNC_ARGS(sym->type)
3912 || FUNC_HASSTACKPARM(sym->etype)
3914 /* restore stack frame */
3915 if(STACK_MODEL_LARGE)
3916 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3917 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3923 if (IFFUNC_ISISR(sym->type)) {
3924 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3925 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3926 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3929 if(!FUNC_ISSHADOWREGS(sym->type)) {
3930 /* do not restore interrupt vector for WREG,STATUS,BSR
3931 * for high priority interrupt, see genFunction */
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3933 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3934 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3936 // _G.interruptvector = 0; /* sanity check */
3939 /* if debug then send end of function */
3940 /* if (options.debug && currFunc) */
3942 debugFile->writeEndFunction (currFunc, ic, 1);
3945 if(_G.usefastretfie)
3946 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3948 pic16_emitpcodeNULLop(POC_RETFIE);
3950 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3952 _G.usefastretfie = 0;
3956 if (IFFUNC_ISCRITICAL(sym->type)) {
3957 pic16_emitcode("setb","ea");
3960 /* if debug then send end of function */
3962 debugFile->writeEndFunction (currFunc, ic, 1);
3965 /* insert code to restore stack frame, if user enabled it
3966 * and function is not main() */
3969 pic16_emitpcodeNULLop(POC_RETURN);
3971 /* Mark the end of a function */
3972 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3976 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3978 unsigned long lit=1;
3983 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3984 if(AOP_TYPE(op) == AOP_LIT) {
3985 if(!IS_FLOAT(operandType( op ))) {
3986 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3989 unsigned long lit_int;
3993 /* take care if literal is a float */
3994 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4000 pic16_movLit2f(dest, lit);
4002 if(dest->type == PO_WREG && (offset == 0)) {
4003 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4010 /*-----------------------------------------------------------------*/
4011 /* genRet - generate code for return statement */
4012 /*-----------------------------------------------------------------*/
4013 static void genRet (iCode *ic)
4019 /* if we have no return value then
4020 * just generate the "ret" */
4025 /* we have something to return then
4026 * move the return value into place */
4027 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4028 size = AOP_SIZE(IC_LEFT(ic));
4032 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4035 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4038 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4040 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4043 /* >32-bits, setup stack and FSR0 */
4045 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4046 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4048 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4050 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4055 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4056 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4058 if(STACK_MODEL_LARGE) {
4059 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4060 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4062 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4067 /* old code, left here for reference -- VR */
4071 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4073 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4074 pic16_emitpcomment("push %s",l);
4077 DEBUGpic16_emitcode(";", "%d", __LINE__);
4078 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4079 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4081 if (strcmp(fReturn[offset],l)) {
4082 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4083 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4084 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4086 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4090 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4100 if (strcmp(fReturn[pushed],"a"))
4101 pic16_emitcode("pop",fReturn[pushed]);
4103 pic16_emitcode("pop","acc");
4109 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4112 /* generate a jump to the return label
4113 * if the next is not the return statement */
4114 if (!(ic->next && ic->next->op == LABEL
4115 && IC_LABEL(ic->next) == returnLabel)) {
4117 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4118 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4122 /*-----------------------------------------------------------------*/
4123 /* genLabel - generates a label */
4124 /*-----------------------------------------------------------------*/
4125 static void genLabel (iCode *ic)
4129 /* special case never generate */
4130 if (IC_LABEL(ic) == entryLabel)
4133 pic16_emitpLabel(IC_LABEL(ic)->key);
4134 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4137 /*-----------------------------------------------------------------*/
4138 /* genGoto - generates a goto */
4139 /*-----------------------------------------------------------------*/
4141 static void genGoto (iCode *ic)
4144 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4145 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4149 /*-----------------------------------------------------------------*/
4150 /* genMultbits :- multiplication of bits */
4151 /*-----------------------------------------------------------------*/
4152 static void genMultbits (operand *left,
4158 if(!pic16_sameRegs(AOP(result),AOP(right)))
4159 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4161 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4162 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4163 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4168 /*-----------------------------------------------------------------*/
4169 /* genMultOneByte : 8 bit multiplication & division */
4170 /*-----------------------------------------------------------------*/
4171 static void genMultOneByte (operand *left,
4177 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4178 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4180 /* (if two literals, the value is computed before) */
4181 /* if one literal, literal on the right */
4182 if (AOP_TYPE(left) == AOP_LIT){
4188 /* size is already checked in genMult == 1 */
4189 // size = AOP_SIZE(result);
4191 if (AOP_TYPE(right) == AOP_LIT){
4192 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4193 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4194 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4195 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4197 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4198 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4199 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4200 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4203 pic16_genMult8X8_8 (left, right,result);
4206 /*-----------------------------------------------------------------*/
4207 /* genMultOneWord : 16 bit multiplication */
4208 /*-----------------------------------------------------------------*/
4209 static void genMultOneWord (operand *left,
4214 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4217 /* (if two literals, the value is computed before)
4218 * if one literal, literal on the right */
4219 if (AOP_TYPE(left) == AOP_LIT){
4225 /* size is checked already == 2 */
4226 // size = AOP_SIZE(result);
4228 if (AOP_TYPE(right) == AOP_LIT) {
4229 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4230 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4231 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4232 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4234 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4235 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4236 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4237 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4240 pic16_genMult16X16_16(left, right,result);
4243 /*-----------------------------------------------------------------*/
4244 /* genMultOneLong : 32 bit multiplication */
4245 /*-----------------------------------------------------------------*/
4246 static void genMultOneLong (operand *left,
4251 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4252 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4254 /* (if two literals, the value is computed before)
4255 * if one literal, literal on the right */
4256 if (AOP_TYPE(left) == AOP_LIT){
4262 /* size is checked already == 4 */
4263 // size = AOP_SIZE(result);
4265 if (AOP_TYPE(right) == AOP_LIT) {
4266 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4267 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4268 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4269 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4271 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4272 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4273 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4274 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4277 pic16_genMult32X32_32(left, right,result);
4282 /*-----------------------------------------------------------------*/
4283 /* genMult - generates code for multiplication */
4284 /*-----------------------------------------------------------------*/
4285 static void genMult (iCode *ic)
4287 operand *left = IC_LEFT(ic);
4288 operand *right = IC_RIGHT(ic);
4289 operand *result= IC_RESULT(ic);
4292 /* assign the amsops */
4293 pic16_aopOp (left,ic,FALSE);
4294 pic16_aopOp (right,ic,FALSE);
4295 pic16_aopOp (result,ic,TRUE);
4297 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4299 /* special cases first *
4301 if (AOP_TYPE(left) == AOP_CRY
4302 && AOP_TYPE(right)== AOP_CRY) {
4303 genMultbits(left,right,result);
4307 /* if both are of size == 1 */
4308 if(AOP_SIZE(left) == 1
4309 && AOP_SIZE(right) == 1) {
4310 genMultOneByte(left,right,result);
4314 /* if both are of size == 2 */
4315 if(AOP_SIZE(left) == 2
4316 && AOP_SIZE(right) == 2) {
4317 genMultOneWord(left, right, result);
4321 /* if both are of size == 4 */
4322 if(AOP_SIZE(left) == 4
4323 && AOP_SIZE(right) == 4) {
4324 genMultOneLong(left, right, result);
4328 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4331 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4332 /* should have been converted to function call */
4336 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4337 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4338 pic16_freeAsmop(result,NULL,ic,TRUE);
4341 /*-----------------------------------------------------------------*/
4342 /* genDivbits :- division of bits */
4343 /*-----------------------------------------------------------------*/
4344 static void genDivbits (operand *left,
4351 /* the result must be bit */
4352 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4353 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4357 pic16_emitcode("div","ab");
4358 pic16_emitcode("rrc","a");
4359 pic16_aopPut(AOP(result),"c",0);
4362 /*-----------------------------------------------------------------*/
4363 /* genDivOneByte : 8 bit division */
4364 /*-----------------------------------------------------------------*/
4365 static void genDivOneByte (operand *left,
4369 sym_link *opetype = operandType(result);
4374 /* result = divident / divisor
4375 * - divident may be a register or a literal,
4376 * - divisor may be a register or a literal,
4377 * so there are 3 cases (literal / literal is optimized
4378 * by the front-end) to handle.
4379 * In addition we must handle signed and unsigned, which
4380 * result in 6 final different cases -- VR */
4384 size = AOP_SIZE(result) - 1;
4386 /* signed or unsigned */
4387 if (SPEC_USIGN(opetype)) {
4388 pCodeOp *pct1, /* count */
4391 symbol *label1, *label2, *label3;;
4394 /* unsigned is easy */
4396 pct1 = pic16_popGetTempReg(1);
4397 pct2 = pic16_popGetTempReg(1);
4398 pct3 = pic16_popGetTempReg(1);
4400 label1 = newiTempLabel(NULL);
4401 label2 = newiTempLabel(NULL);
4402 label3 = newiTempLabel(NULL);
4404 /* the following algorithm is extracted from divuint.c */
4406 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4407 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4409 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4411 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4413 pic16_emitpLabel(label1->key);
4416 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4420 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4424 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4426 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4427 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4429 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4430 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4431 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4433 pic16_emitpLabel( label3->key );
4434 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4435 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4439 pic16_emitpLabel(label2->key);
4440 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4441 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4442 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4444 /* result is in wreg */
4445 if(AOP_TYPE(result) != AOP_ACC)
4446 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4448 pic16_popReleaseTempReg( pct3, 1);
4449 pic16_popReleaseTempReg( pct2, 1);
4450 pic16_popReleaseTempReg( pct1, 1);
4455 /* signed is a little bit more difficult */
4457 /* save the signs of the operands */
4458 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4460 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4461 pic16_emitcode("push","acc"); /* save it on the stack */
4463 /* now sign adjust for both left & right */
4464 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4466 lbl = newiTempLabel(NULL);
4467 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4468 pic16_emitcode("cpl","a");
4469 pic16_emitcode("inc","a");
4470 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4471 pic16_emitcode("mov","b,a");
4473 /* sign adjust left side */
4474 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4477 lbl = newiTempLabel(NULL);
4478 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4479 pic16_emitcode("cpl","a");
4480 pic16_emitcode("inc","a");
4481 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4483 /* now the division */
4484 pic16_emitcode("div","ab");
4485 /* we are interested in the lower order
4487 pic16_emitcode("mov","b,a");
4488 lbl = newiTempLabel(NULL);
4489 pic16_emitcode("pop","acc");
4490 /* if there was an over flow we don't
4491 adjust the sign of the result */
4492 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4493 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4495 pic16_emitcode("clr","a");
4496 pic16_emitcode("subb","a,b");
4497 pic16_emitcode("mov","b,a");
4498 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4500 /* now we are done */
4501 pic16_aopPut(AOP(result),"b",0);
4503 pic16_emitcode("mov","c,b.7");
4504 pic16_emitcode("subb","a,acc");
4507 pic16_aopPut(AOP(result),"a",offset++);
4511 /*-----------------------------------------------------------------*/
4512 /* genDiv - generates code for division */
4513 /*-----------------------------------------------------------------*/
4514 static void genDiv (iCode *ic)
4516 operand *left = IC_LEFT(ic);
4517 operand *right = IC_RIGHT(ic);
4518 operand *result= IC_RESULT(ic);
4521 /* Division is a very lengthy algorithm, so it is better
4522 * to call support routines than inlining algorithm.
4523 * Division functions written here just in case someone
4524 * wants to inline and not use the support libraries -- VR */
4528 /* assign the amsops */
4529 pic16_aopOp (left,ic,FALSE);
4530 pic16_aopOp (right,ic,FALSE);
4531 pic16_aopOp (result,ic,TRUE);
4533 /* special cases first */
4535 if (AOP_TYPE(left) == AOP_CRY &&
4536 AOP_TYPE(right)== AOP_CRY) {
4537 genDivbits(left,right,result);
4541 /* if both are of size == 1 */
4542 if (AOP_SIZE(left) == 1 &&
4543 AOP_SIZE(right) == 1 ) {
4544 genDivOneByte(left,right,result);
4548 /* should have been converted to function call */
4551 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4552 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4553 pic16_freeAsmop(result,NULL,ic,TRUE);
4556 /*-----------------------------------------------------------------*/
4557 /* genModbits :- modulus of bits */
4558 /*-----------------------------------------------------------------*/
4559 static void genModbits (operand *left,
4567 werror(W_POSSBUG2, __FILE__, __LINE__);
4568 /* the result must be bit */
4569 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4570 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4574 pic16_emitcode("div","ab");
4575 pic16_emitcode("mov","a,b");
4576 pic16_emitcode("rrc","a");
4577 pic16_aopPut(AOP(result),"c",0);
4580 /*-----------------------------------------------------------------*/
4581 /* genModOneByte : 8 bit modulus */
4582 /*-----------------------------------------------------------------*/
4583 static void genModOneByte (operand *left,
4587 sym_link *opetype = operandType(result);
4592 werror(W_POSSBUG2, __FILE__, __LINE__);
4594 /* signed or unsigned */
4595 if (SPEC_USIGN(opetype)) {
4596 /* unsigned is easy */
4597 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4598 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4600 pic16_emitcode("div","ab");
4601 pic16_aopPut(AOP(result),"b",0);
4605 /* signed is a little bit more difficult */
4607 /* save the signs of the operands */
4608 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4611 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4612 pic16_emitcode("push","acc"); /* save it on the stack */
4614 /* now sign adjust for both left & right */
4615 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4618 lbl = newiTempLabel(NULL);
4619 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4620 pic16_emitcode("cpl","a");
4621 pic16_emitcode("inc","a");
4622 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4623 pic16_emitcode("mov","b,a");
4625 /* sign adjust left side */
4626 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4629 lbl = newiTempLabel(NULL);
4630 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4631 pic16_emitcode("cpl","a");
4632 pic16_emitcode("inc","a");
4633 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4635 /* now the multiplication */
4636 pic16_emitcode("div","ab");
4637 /* we are interested in the lower order
4639 lbl = newiTempLabel(NULL);
4640 pic16_emitcode("pop","acc");
4641 /* if there was an over flow we don't
4642 adjust the sign of the result */
4643 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4644 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4646 pic16_emitcode("clr","a");
4647 pic16_emitcode("subb","a,b");
4648 pic16_emitcode("mov","b,a");
4649 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4651 /* now we are done */
4652 pic16_aopPut(AOP(result),"b",0);
4656 /*-----------------------------------------------------------------*/
4657 /* genMod - generates code for division */
4658 /*-----------------------------------------------------------------*/
4659 static void genMod (iCode *ic)
4661 operand *left = IC_LEFT(ic);
4662 operand *right = IC_RIGHT(ic);
4663 operand *result= IC_RESULT(ic);
4667 /* assign the amsops */
4668 pic16_aopOp (left,ic,FALSE);
4669 pic16_aopOp (right,ic,FALSE);
4670 pic16_aopOp (result,ic,TRUE);
4672 /* special cases first */
4674 if (AOP_TYPE(left) == AOP_CRY &&
4675 AOP_TYPE(right)== AOP_CRY) {
4676 genModbits(left,right,result);
4680 /* if both are of size == 1 */
4681 if (AOP_SIZE(left) == 1 &&
4682 AOP_SIZE(right) == 1 ) {
4683 genModOneByte(left,right,result);
4687 /* should have been converted to function call */
4691 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4692 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4693 pic16_freeAsmop(result,NULL,ic,TRUE);
4696 /*-----------------------------------------------------------------*/
4697 /* genIfxJump :- will create a jump depending on the ifx */
4698 /*-----------------------------------------------------------------*/
4700 note: May need to add parameter to indicate when a variable is in bit space.
4702 static void genIfxJump (iCode *ic, char *jval)
4706 /* if true label then we jump if condition
4708 if ( IC_TRUE(ic) ) {
4710 if(strcmp(jval,"a") == 0)
4712 else if (strcmp(jval,"c") == 0)
4715 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4716 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4719 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4720 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4724 /* false label is present */
4725 if(strcmp(jval,"a") == 0)
4727 else if (strcmp(jval,"c") == 0)
4730 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4731 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4734 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4735 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4740 /* mark the icode as generated */
4744 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4748 /* if true label then we jump if condition
4750 if ( IC_TRUE(ic) ) {
4751 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4752 pic16_emitpcode(POC_BTFSC, jop);
4754 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4755 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4758 /* false label is present */
4759 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4760 pic16_emitpcode(POC_BTFSS, jop);
4762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4763 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4767 /* mark the icode as generated */
4774 /*-----------------------------------------------------------------*/
4776 /*-----------------------------------------------------------------*/
4777 static void genSkip(iCode *ifx,int status_bit)
4779 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4783 if ( IC_TRUE(ifx) ) {
4784 switch(status_bit) {
4799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4800 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4804 switch(status_bit) {
4818 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4819 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4826 /*-----------------------------------------------------------------*/
4828 /*-----------------------------------------------------------------*/
4829 static void genSkipc(resolvedIfx *rifx)
4831 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4841 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4842 rifx->generated = 1;
4845 #if !(USE_SIMPLE_GENCMP)
4846 /*-----------------------------------------------------------------*/
4848 /*-----------------------------------------------------------------*/
4849 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4851 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4856 if( (rifx->condition ^ invert_condition) & 1)
4861 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4862 rifx->generated = 1;
4867 /*-----------------------------------------------------------------*/
4869 /*-----------------------------------------------------------------*/
4870 static void genSkipz(iCode *ifx, int condition)
4881 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4883 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4886 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4888 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4893 #if !(USE_SIMPLE_GENCMP)
4894 /*-----------------------------------------------------------------*/
4896 /*-----------------------------------------------------------------*/
4897 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4903 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4905 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4909 rifx->generated = 1;
4914 /*-----------------------------------------------------------------*/
4915 /* genChkZeroes :- greater or less than comparison */
4916 /* For each byte in a literal that is zero, inclusive or the */
4917 /* the corresponding byte in the operand with W */
4918 /* returns true if any of the bytes are zero */
4919 /*-----------------------------------------------------------------*/
4920 static int genChkZeroes(operand *op, int lit, int size)
4927 i = (lit >> (size*8)) & 0xff;
4931 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4933 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4943 /*-----------------------------------------------------------------*/
4944 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4945 /* aop (if it's NOT a literal) or from lit (if */
4946 /* aop is a literal) */
4947 /*-----------------------------------------------------------------*/
4948 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4949 if (aop->type == AOP_LIT) {
4950 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4952 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4956 /*-----------------------------------------------------------------*/
4957 /* genCmp :- greater or less than comparison */
4958 /*-----------------------------------------------------------------*/
4960 #if USE_SIMPLE_GENCMP /* { */
4962 /* genCmp performs a left < right comparison, stores
4963 * the outcome in result (if != NULL) and generates
4964 * control flow code for the ifx (if != NULL).
4966 * This version leaves in sequences like
4967 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4968 * which should be optmized by the peephole
4969 * optimizer - RN 2005-01-01 */
4970 static void genCmp (operand *left,operand *right,
4971 operand *result, iCode *ifx, int sign)
4984 assert (left && right);
4985 assert (AOP_SIZE(left) == AOP_SIZE(right));
4987 size = AOP_SIZE(right) - 1;
4988 mask = (0x100UL << (size*8)) - 1;
4989 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4994 resolveIfx (&rIfx, ifx);
4996 /* handle for special cases */
4997 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5000 /**********************************************************************
5001 * handle bits - bit compares are promoted to int compares seemingly! *
5002 **********************************************************************/
5004 // THIS IS COMPLETELY UNTESTED!
5005 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5006 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5007 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5008 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5011 // 1 < {0,1} is false --> clear C by skipping the next instruction
5012 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5013 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5014 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5015 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5016 emitCLRC; // only skipped for left=0 && right=1
5018 goto correct_result_in_carry;
5022 /*************************************************
5023 * make sure that left is register (or the like) *
5024 *************************************************/
5025 if (!isAOP_REGlike(left)) {
5026 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5027 assert (isAOP_LIT(left));
5028 assert (isAOP_REGlike(right));
5029 // swap left and right
5030 // left < right <==> right > left <==> (right >= left + 1)
5031 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5033 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5034 // MAXVALUE < right? always false
5035 if (performedLt) emitCLRC; else emitSETC;
5036 goto correct_result_in_carry;
5039 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5040 // that's why we handled it above.
5047 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5048 } else if (isAOP_LIT(right)) {
5049 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5052 assert (isAOP_REGlike(left)); // left must be register or the like
5053 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5055 /*************************************************
5056 * special cases go here *
5057 *************************************************/
5059 if (isAOP_LIT(right)) {
5061 // unsigned comparison to a literal
5062 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5064 // unsigned left < 0? always false
5065 if (performedLt) emitCLRC; else emitSETC;
5066 goto correct_result_in_carry;
5069 // signed comparison to a literal
5070 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5071 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5072 // signed left < 0x80000000? always false
5073 if (performedLt) emitCLRC; else emitSETC;
5074 goto correct_result_in_carry;
5075 } else if (lit == 0) {
5076 // compare left < 0; set CARRY if SIGNBIT(left) is set
5077 if (performedLt) emitSETC; else emitCLRC;
5078 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5079 if (performedLt) emitCLRC; else emitSETC;
5080 goto correct_result_in_carry;
5083 } // right is literal
5085 /*************************************************
5086 * perform a general case comparison *
5087 * make sure we get CARRY==1 <==> left >= right *
5088 *************************************************/
5089 // compare most significant bytes
5090 //DEBUGpc ("comparing bytes at offset %d", size);
5092 // unsigned comparison
5093 mov2w_regOrLit (AOP(right), lit, size);
5094 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5096 // signed comparison
5097 // (add 2^n to both operands then perform an unsigned comparison)
5098 if (isAOP_LIT(right)) {
5099 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5100 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5102 if (litbyte == 0x80) {
5103 // left >= 0x80 -- always true, but more bytes to come
5104 pic16_mov2w (AOP(left), size);
5105 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5108 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5109 pic16_mov2w (AOP(left), size);
5110 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5111 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5114 /* using PRODL as a temporary register here */
5115 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5116 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5117 pic16_mov2w (AOP(left), size);
5118 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5119 pic16_emitpcode (POC_MOVWF, pctemp);
5120 pic16_mov2w (AOP(right), size);
5121 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5122 pic16_emitpcode (POC_SUBFW, pctemp);
5123 //pic16_popReleaseTempReg(pctemp, 1);
5127 // compare remaining bytes (treat as unsigned case from above)
5128 templbl = newiTempLabel ( NULL );
5131 //DEBUGpc ("comparing bytes at offset %d", offs);
5132 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5133 mov2w_regOrLit (AOP(right), lit, offs);
5134 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5136 pic16_emitpLabel (templbl->key);
5137 goto result_in_carry;
5141 /****************************************************
5142 * now CARRY contains the result of the comparison: *
5143 * SUBWF sets CARRY iff *
5144 * F-W >= 0 <==> F >= W <==> !(F < W) *
5145 * (F=left, W=right) *
5146 ****************************************************/
5149 if (result && AOP_TYPE(result) != AOP_CRY) {
5150 // value will be stored
5153 // value wil only be used in the following genSkipc()
5154 rIfx.condition ^= 1;
5158 correct_result_in_carry:
5160 // assign result to variable (if neccessary)
5161 if (result && AOP_TYPE(result) != AOP_CRY) {
5162 //DEBUGpc ("assign result");
5163 size = AOP_SIZE(result);
5165 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5167 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5170 // perform conditional jump
5172 //DEBUGpc ("generate control flow");
5181 static void genCmp (operand *left,operand *right,
5182 operand *result, iCode *ifx, int sign)
5184 int size; //, offset = 0 ;
5185 unsigned long lit = 0L,i = 0;
5186 resolvedIfx rFalseIfx;
5187 // resolvedIfx rTrueIfx;
5189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5192 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5193 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5199 resolveIfx(&rFalseIfx,ifx);
5200 truelbl = newiTempLabel(NULL);
5201 size = max(AOP_SIZE(left),AOP_SIZE(right));
5203 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5207 /* if literal is on the right then swap with left */
5208 if ((AOP_TYPE(right) == AOP_LIT)) {
5209 operand *tmp = right ;
5210 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5211 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5214 lit = (lit - 1) & mask;
5217 rFalseIfx.condition ^= 1;
5220 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5221 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5225 //if(IC_TRUE(ifx) == NULL)
5226 /* if left & right are bit variables */
5227 if (AOP_TYPE(left) == AOP_CRY &&
5228 AOP_TYPE(right) == AOP_CRY ) {
5229 assert (0 && "bit variables used in genCmp");
5230 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5231 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5233 /* subtract right from left if at the
5234 end the carry flag is set then we know that
5235 left is greater than right */
5237 symbol *lbl = newiTempLabel(NULL);
5240 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5241 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5245 if(AOP_TYPE(right) == AOP_LIT) {
5247 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5249 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5256 genSkipCond(&rFalseIfx,left,size-1,7);
5258 /* no need to compare to 0...*/
5259 /* NOTE: this is a de-generate compare that most certainly
5260 * creates some dead code. */
5261 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5263 if(ifx) ifx->generated = 1;
5270 //i = (lit >> (size*8)) & 0xff;
5271 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5273 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5275 i = ((0-lit) & 0xff);
5278 /* lit is 0x7f, all signed chars are less than
5279 * this except for 0x7f itself */
5280 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5281 genSkipz2(&rFalseIfx,0);
5283 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5284 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5285 genSkipc(&rFalseIfx);
5290 genSkipz2(&rFalseIfx,1);
5292 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5293 genSkipc(&rFalseIfx);
5297 if(ifx) ifx->generated = 1;
5301 /* chars are out of the way. now do ints and longs */
5304 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5311 genSkipCond(&rFalseIfx,left,size,7);
5312 if(ifx) ifx->generated = 1;
5317 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5319 //rFalseIfx.condition ^= 1;
5320 //genSkipCond(&rFalseIfx,left,size,7);
5321 //rFalseIfx.condition ^= 1;
5323 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5324 if(rFalseIfx.condition)
5325 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5327 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5329 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5330 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5331 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5334 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5336 if(rFalseIfx.condition) {
5338 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5344 genSkipc(&rFalseIfx);
5345 pic16_emitpLabel(truelbl->key);
5346 if(ifx) ifx->generated = 1;
5353 if( (lit & 0xff) == 0) {
5354 /* lower byte is zero */
5355 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5356 i = ((lit >> 8) & 0xff) ^0x80;
5357 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5358 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5359 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5360 genSkipc(&rFalseIfx);
5363 if(ifx) ifx->generated = 1;
5368 /* Special cases for signed longs */
5369 if( (lit & 0xffffff) == 0) {
5370 /* lower byte is zero */
5371 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372 i = ((lit >> 8*3) & 0xff) ^0x80;
5373 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376 genSkipc(&rFalseIfx);
5379 if(ifx) ifx->generated = 1;
5387 if(lit & (0x80 << (size*8))) {
5388 /* lit is negative */
5389 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5391 //genSkipCond(&rFalseIfx,left,size,7);
5393 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5395 if(rFalseIfx.condition)
5396 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5398 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5402 /* lit is positive */
5403 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5404 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5405 if(rFalseIfx.condition)
5406 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5413 This works, but is only good for ints.
5414 It also requires a "known zero" register.
5415 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5416 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5417 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5418 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5419 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5420 genSkipc(&rFalseIfx);
5422 pic16_emitpLabel(truelbl->key);
5423 if(ifx) ifx->generated = 1;
5427 /* There are no more special cases, so perform a general compare */
5429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5430 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5434 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5436 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5438 //rFalseIfx.condition ^= 1;
5439 genSkipc(&rFalseIfx);
5441 pic16_emitpLabel(truelbl->key);
5443 if(ifx) ifx->generated = 1;
5450 /* sign is out of the way. So now do an unsigned compare */
5451 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5454 /* General case - compare to an unsigned literal on the right.*/
5456 i = (lit >> (size*8)) & 0xff;
5457 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5458 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5460 i = (lit >> (size*8)) & 0xff;
5463 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5465 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5467 /* this byte of the lit is zero,
5468 *if it's not the last then OR in the variable */
5470 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5475 pic16_emitpLabel(lbl->key);
5476 // pic16_emitpLabel(truelbl->key);
5477 //if(emitFinalCheck)
5478 genSkipc(&rFalseIfx);
5480 pic16_emitpLabel(truelbl->key);
5482 if(ifx) ifx->generated = 1;
5489 if(AOP_TYPE(left) == AOP_LIT) {
5490 //symbol *lbl = newiTempLabel(NULL);
5492 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5495 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5498 if((lit == 0) && (sign == 0)){
5501 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5503 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5505 genSkipz2(&rFalseIfx,0);
5506 if(ifx) ifx->generated = 1;
5513 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5514 /* degenerate compare can never be true */
5515 if(rFalseIfx.condition == 0)
5516 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5518 if(ifx) ifx->generated = 1;
5523 /* signed comparisons to a literal byte */
5525 int lp1 = (lit+1) & 0xff;
5527 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5530 rFalseIfx.condition ^= 1;
5531 genSkipCond(&rFalseIfx,right,0,7);
5534 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5535 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5536 genSkipz2(&rFalseIfx,1);
5539 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5540 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5541 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5542 rFalseIfx.condition ^= 1;
5543 genSkipc(&rFalseIfx);
5547 /* unsigned comparisons to a literal byte */
5549 switch(lit & 0xff ) {
5551 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552 genSkipz2(&rFalseIfx,0);
5555 rFalseIfx.condition ^= 1;
5556 genSkipCond(&rFalseIfx,right,0,7);
5560 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5561 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5563 rFalseIfx.condition ^= 1;
5564 if (AOP_TYPE(result) == AOP_CRY)
5565 genSkipc(&rFalseIfx);
5567 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5568 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5574 if(ifx) ifx->generated = 1;
5575 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5581 /* Size is greater than 1 */
5589 /* this means lit = 0xffffffff, or -1 */
5592 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5593 rFalseIfx.condition ^= 1;
5594 genSkipCond(&rFalseIfx,right,size,7);
5595 if(ifx) ifx->generated = 1;
5597 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5606 if(rFalseIfx.condition) {
5607 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5608 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5611 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5613 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5617 if(rFalseIfx.condition) {
5618 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5619 pic16_emitpLabel(truelbl->key);
5621 rFalseIfx.condition ^= 1;
5622 genSkipCond(&rFalseIfx,right,s,7);
5625 if(ifx) ifx->generated = 1;
5627 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5633 if((size == 1) && (0 == (lp1&0xff))) {
5634 /* lower byte of signed word is zero */
5635 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5636 i = ((lp1 >> 8) & 0xff) ^0x80;
5637 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5638 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5639 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5641 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5643 if(ifx) ifx->generated = 1;
5646 rFalseIfx.condition ^= 1;
5647 genSkipc(&rFalseIfx);
5648 if(ifx) ifx->generated = 1;
5654 if(lit & (0x80 << (size*8))) {
5655 /* Lit is less than zero */
5656 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5657 //rFalseIfx.condition ^= 1;
5658 //genSkipCond(&rFalseIfx,left,size,7);
5659 //rFalseIfx.condition ^= 1;
5660 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5661 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5663 if(rFalseIfx.condition)
5664 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5666 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5670 /* Lit is greater than or equal to zero */
5671 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5672 //rFalseIfx.condition ^= 1;
5673 //genSkipCond(&rFalseIfx,right,size,7);
5674 //rFalseIfx.condition ^= 1;
5676 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5677 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5679 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5680 if(rFalseIfx.condition)
5681 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5683 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5687 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5688 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5692 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5694 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5696 rFalseIfx.condition ^= 1;
5697 //rFalseIfx.condition = 1;
5698 genSkipc(&rFalseIfx);
5700 pic16_emitpLabel(truelbl->key);
5702 if(ifx) ifx->generated = 1;
5705 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5712 /* compare word or long to an unsigned literal on the right.*/
5717 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5720 break; /* handled above */
5723 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5725 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5726 genSkipz2(&rFalseIfx,0);
5730 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5732 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5735 if(rFalseIfx.condition)
5736 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5738 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5741 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5742 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5744 rFalseIfx.condition ^= 1;
5745 genSkipc(&rFalseIfx);
5748 pic16_emitpLabel(truelbl->key);
5750 if(ifx) ifx->generated = 1;
5752 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5760 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5761 i = (lit >> (size*8)) & 0xff;
5763 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5764 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5767 i = (lit >> (size*8)) & 0xff;
5770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5772 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5774 /* this byte of the lit is zero,
5775 * if it's not the last then OR in the variable */
5777 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5782 pic16_emitpLabel(lbl->key);
5784 rFalseIfx.condition ^= 1;
5786 genSkipc(&rFalseIfx);
5790 pic16_emitpLabel(truelbl->key);
5791 if(ifx) ifx->generated = 1;
5793 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5799 /* Compare two variables */
5801 DEBUGpic16_emitcode(";sign","%d",sign);
5805 /* Sigh. thus sucks... */
5809 pctemp = pic16_popGetTempReg(1);
5810 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5811 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5812 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5813 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5814 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5815 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5816 pic16_popReleaseTempReg(pctemp, 1);
5818 /* Signed char comparison */
5819 /* Special thanks to Nikolai Golovchenko for this snippet */
5820 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5821 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5822 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5823 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5824 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5825 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5827 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5828 genSkipc(&rFalseIfx);
5830 if(ifx) ifx->generated = 1;
5832 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5840 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5841 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5845 /* The rest of the bytes of a multi-byte compare */
5849 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5852 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5858 pic16_emitpLabel(lbl->key);
5860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5861 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5862 (AOP_TYPE(result) == AOP_REG)) {
5863 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5864 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5866 genSkipc(&rFalseIfx);
5868 //genSkipc(&rFalseIfx);
5869 if(ifx) ifx->generated = 1;
5872 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5880 if ((AOP_TYPE(result) != AOP_CRY)
5881 && AOP_SIZE(result)) {
5882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5884 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5886 pic16_outBitC(result);
5888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5889 /* if the result is used in the next
5890 ifx conditional branch then generate
5891 code a little differently */
5893 genIfxJump (ifx,"c");
5895 pic16_outBitC(result);
5896 /* leave the result in acc */
5901 #elif 0 /* VR version of genCmp() */ /* } else { */
5903 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5904 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5905 operand *result, int offset, int invert_op)
5909 /* check condition, > or < ?? */
5910 if(rIfx->condition != 0)invert_op ^= 1;
5912 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5914 if(!ifx)invert_op ^= 1;
5916 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5917 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5920 if(!invert_op)return POC_CPFSGT;
5921 else return POC_CPFSLT;
5924 static int compareAopfirstpass=1;
5926 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5927 operand *oper, int offset, operand *result,
5928 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5934 /* invert if there is a result to be loaded, in order to fit,
5935 * SETC/CLRC sequence */
5936 if(AOP_SIZE(result))invert_op ^= 1;
5938 // if(sign && !offset)invert_op ^= 1;
5940 // if(sign)invert_op ^= 1;
5942 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5944 if(AOP_SIZE(result) && compareAopfirstpass) {
5947 pic16_emitpcode(POC_SETF, pcop2);
5952 pic16_emitpcode(POC_CLRF, pcop2);
5958 compareAopfirstpass = 0;
5960 /* there is a bug when comparing operands with size > 1,
5961 * because higher bytes can be equal and test should be performed
5962 * to the next lower byte, current algorithm, considers operands
5963 * inequal in these cases! -- VR 20041107 */
5967 pic16_emitpcode(op, pcop);
5969 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5972 if((!sign || !offset) && AOP_SIZE(result)) {
5975 pic16_emitpcode(POC_CLRF, pcop2);
5980 pic16_emitpcode(POC_SETF, pcop2);
5985 /* don't emit final branch (offset == 0) */
5989 pic16_emitpcode(POC_RRCF, pcop2);
5991 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5994 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5995 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5996 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5998 truelbl = newiTempLabel( NULL );
5999 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6000 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6001 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6003 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6004 pic16_emitpLabel(truelbl->key);
6006 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6011 static void genCmp (operand *left, operand *right,
6012 operand *result, iCode *ifx, int sign)
6016 resolvedIfx rFalseIfx;
6017 symbol *falselbl, *tlbl;
6021 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6023 resolveIfx(&rFalseIfx, ifx);
6024 size = max(AOP_SIZE(left), AOP_SIZE(right));
6026 /* if left & right are bit variables */
6027 if(AOP_TYPE(left) == AOP_CRY
6028 && AOP_TYPE(right) == AOP_CRY ) {
6030 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6031 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6033 werror(W_POSSBUG2, __FILE__, __LINE__);
6037 /* if literal is on the right then swap with left */
6038 if((AOP_TYPE(right) == AOP_LIT)) {
6039 operand *tmp = right ;
6040 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6042 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6044 // lit = (lit - 1) & mask;
6047 rFalseIfx.condition ^= 1; /* reverse compare */
6049 if ((AOP_TYPE(left) == AOP_LIT)) {
6050 /* float compares are handled by support functions */
6051 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6054 /* actual comparing algorithm */
6055 // size = AOP_SIZE( right );
6057 falselbl = newiTempLabel( NULL );
6058 if(AOP_TYPE(left) == AOP_LIT) {
6059 /* compare to literal */
6060 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6063 pCodeOp *pct, *pct2;
6066 /* signed compare */
6067 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6069 /* using PRODL:PRODH as a temporary register here */
6070 pct = pic16_popCopyReg(&pic16_pc_prodl);
6071 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6072 tlbl = newiTempLabel( NULL );
6074 /* first compare signs:
6075 * a. if both are positive, compare just like unsigned
6076 * b. if both are negative, invert cmpop, compare just like unsigned
6077 * c. if different signs, determine the result directly */
6083 tlbl1 = newiTempLabel( NULL );
6084 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6088 /* literal is zero or positive:
6089 * a. if carry is zero, too, continue compare,
6090 * b. if carry is set, then continue depending on cmpop ^ condition:
6091 * 1. '<' return false (literal < variable),
6092 * 2. '>' return true (literal > variable) */
6093 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6094 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6097 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6098 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6102 /* literal is negative:
6103 * a. if carry is set, too, continue compare,
6104 * b. if carry is zero, then continue depending on cmpop ^ condition:
6105 * 1. '<' return true (literal < variable),
6106 * 2. '>' return false (literal > variable) */
6107 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6108 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6110 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6111 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6116 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6118 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6119 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6124 pic16_emitpLabel( tlbl1->key );
6127 compareAopfirstpass=1;
6128 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6129 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6130 // pic16_emitpcode(POC_MOVWF, pct);
6132 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6133 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6134 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6135 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6139 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6140 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6141 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6142 // pic16_emitpcode(POC_MOVWF, pct);
6144 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6145 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6146 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6147 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6148 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6151 if(ifx)ifx->generated = 1;
6153 if(AOP_SIZE(result)) {
6154 pic16_emitpLabel(tlbl->key);
6155 pic16_emitpLabel(falselbl->key);
6156 pic16_outBitOp( result, pct2 );
6158 pic16_emitpLabel(tlbl->key);
6162 /* unsigned compare */
6163 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6165 compareAopfirstpass=1;
6168 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6169 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6172 if(ifx)ifx->generated = 1;
6174 if(AOP_SIZE(result)) {
6175 pic16_emitpLabel(falselbl->key);
6176 pic16_outBitC( result );
6181 /* compare registers */
6182 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6186 pCodeOp *pct, *pct2;
6188 /* signed compare */
6189 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6191 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6192 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6193 tlbl = newiTempLabel( NULL );
6195 compareAopfirstpass=1;
6198 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6199 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6200 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6201 pic16_emitpcode(POC_MOVWF, pct);
6203 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6204 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6207 /* WREG already holds left + 0x80 */
6208 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6211 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6212 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6213 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214 pic16_emitpcode(POC_MOVWF, pct);
6216 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6217 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6220 /* WREG already holds left + 0x80 */
6221 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6222 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6225 if(ifx)ifx->generated = 1;
6227 if(AOP_SIZE(result)) {
6228 pic16_emitpLabel(tlbl->key);
6229 pic16_emitpLabel(falselbl->key);
6230 pic16_outBitOp( result, pct2 );
6232 pic16_emitpLabel(tlbl->key);
6236 /* unsigned compare */
6237 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6239 compareAopfirstpass=1;
6242 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6243 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6247 if(ifx)ifx->generated = 1;
6248 if(AOP_SIZE(result)) {
6250 pic16_emitpLabel(falselbl->key);
6251 pic16_outBitC( result );
6262 /*-----------------------------------------------------------------*/
6263 /* genCmpGt :- greater than comparison */
6264 /*-----------------------------------------------------------------*/
6265 static void genCmpGt (iCode *ic, iCode *ifx)
6267 operand *left, *right, *result;
6268 sym_link *letype , *retype;
6274 right= IC_RIGHT(ic);
6275 result = IC_RESULT(ic);
6277 letype = getSpec(operandType(left));
6278 retype =getSpec(operandType(right));
6279 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6280 /* assign the amsops */
6281 pic16_aopOp (left,ic,FALSE);
6282 pic16_aopOp (right,ic,FALSE);
6283 pic16_aopOp (result,ic,TRUE);
6285 genCmp(right, left, result, ifx, sign);
6287 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6288 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6289 pic16_freeAsmop(result,NULL,ic,TRUE);
6292 /*-----------------------------------------------------------------*/
6293 /* genCmpLt - less than comparisons */
6294 /*-----------------------------------------------------------------*/
6295 static void genCmpLt (iCode *ic, iCode *ifx)
6297 operand *left, *right, *result;
6298 sym_link *letype , *retype;
6304 right= IC_RIGHT(ic);
6305 result = IC_RESULT(ic);
6307 letype = getSpec(operandType(left));
6308 retype =getSpec(operandType(right));
6309 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6311 /* assign the amsops */
6312 pic16_aopOp (left,ic,FALSE);
6313 pic16_aopOp (right,ic,FALSE);
6314 pic16_aopOp (result,ic,TRUE);
6316 genCmp(left, right, result, ifx, sign);
6318 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6319 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6320 pic16_freeAsmop(result,NULL,ic,TRUE);
6325 // FIXME reenable literal optimisation when the pic16 port is stable
6327 /*-----------------------------------------------------------------*/
6328 /* genc16bit2lit - compare a 16 bit value to a literal */
6329 /*-----------------------------------------------------------------*/
6330 static void genc16bit2lit(operand *op, int lit, int offset)
6334 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6335 if( (lit&0xff) == 0)
6340 switch( BYTEofLONG(lit,i)) {
6342 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6345 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6348 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6351 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6352 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6357 switch( BYTEofLONG(lit,i)) {
6359 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6363 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6367 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6370 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6372 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6381 /*-----------------------------------------------------------------*/
6382 /* gencjneshort - compare and jump if not equal */
6383 /*-----------------------------------------------------------------*/
6384 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6386 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6388 int res_offset = 0; /* the result may be a different size then left or right */
6389 int res_size = AOP_SIZE(result);
6391 symbol *lbl, *lbl_done;
6393 unsigned long lit = 0L;
6394 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6396 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6397 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6399 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6400 resolveIfx(&rIfx,ifx);
6401 lbl = newiTempLabel(NULL);
6402 lbl_done = newiTempLabel(NULL);
6405 /* if the left side is a literal or
6406 if the right is in a pointer register and left
6408 if ((AOP_TYPE(left) == AOP_LIT) ||
6409 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6414 if(AOP_TYPE(right) == AOP_LIT)
6415 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6417 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6418 preserve_result = 1;
6420 if(result && !preserve_result)
6423 for(i = 0; i < AOP_SIZE(result); i++)
6424 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6428 /* if the right side is a literal then anything goes */
6429 if (AOP_TYPE(right) == AOP_LIT &&
6430 AOP_TYPE(left) != AOP_DIR ) {
6433 genc16bit2lit(left, lit, 0);
6435 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6441 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6442 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6444 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6448 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6450 if(res_offset < res_size-1)
6458 /* if the right side is in a register or in direct space or
6459 if the left is a pointer register & right is not */
6460 else if (AOP_TYPE(right) == AOP_REG ||
6461 AOP_TYPE(right) == AOP_DIR ||
6462 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6463 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6464 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6465 int lbl_key = lbl->key;
6468 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6469 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6471 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6472 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6473 __FUNCTION__,__LINE__);
6477 /* switch(size) { */
6479 /* genc16bit2lit(left, lit, 0); */
6481 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6486 if((AOP_TYPE(left) == AOP_DIR) &&
6487 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6489 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6490 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6492 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6494 switch (lit & 0xff) {
6496 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6499 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6500 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6501 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6505 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6506 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6507 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6508 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6512 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6518 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6521 if(AOP_TYPE(result) == AOP_CRY) {
6522 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6527 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6529 /* fix me. probably need to check result size too */
6530 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6535 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6536 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6543 if(res_offset < res_size-1)
6548 } else if(AOP_TYPE(right) == AOP_REG &&
6549 AOP_TYPE(left) != AOP_DIR){
6552 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6553 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6554 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6559 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6561 if(res_offset < res_size-1)
6566 /* right is a pointer reg need both a & b */
6568 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6570 pic16_emitcode("mov","b,%s",l);
6571 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6572 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6577 if(result && preserve_result)
6580 for(i = 0; i < AOP_SIZE(result); i++)
6581 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6584 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6586 if(result && preserve_result)
6587 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6590 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6592 pic16_emitpLabel(lbl->key);
6594 if(result && preserve_result)
6597 for(i = 0; i < AOP_SIZE(result); i++)
6598 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6600 pic16_emitpLabel(lbl_done->key);
6603 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6611 /*-----------------------------------------------------------------*/
6612 /* gencjne - compare and jump if not equal */
6613 /*-----------------------------------------------------------------*/
6614 static void gencjne(operand *left, operand *right, iCode *ifx)
6616 symbol *tlbl = newiTempLabel(NULL);
6618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6619 gencjneshort(left, right, lbl);
6621 pic16_emitcode("mov","a,%s",one);
6622 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6623 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6624 pic16_emitcode("clr","a");
6625 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6627 pic16_emitpLabel(lbl->key);
6628 pic16_emitpLabel(tlbl->key);
6634 /*-----------------------------------------------------------------*/
6635 /* is_LitOp - check if operand has to be treated as literal */
6636 /*-----------------------------------------------------------------*/
6637 static bool is_LitOp(operand *op)
6639 return ((AOP_TYPE(op) == AOP_LIT)
6640 || ( (AOP_TYPE(op) == AOP_PCODE)
6641 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6642 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6645 /*-----------------------------------------------------------------*/
6646 /* is_LitAOp - check if operand has to be treated as literal */
6647 /*-----------------------------------------------------------------*/
6648 static bool is_LitAOp(asmop *aop)
6650 return ((aop->type == AOP_LIT)
6651 || ( (aop->type == AOP_PCODE)
6652 && ( (aop->aopu.pcop->type == PO_LITERAL)
6653 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6658 /*-----------------------------------------------------------------*/
6659 /* genCmpEq - generates code for equal to */
6660 /*-----------------------------------------------------------------*/
6661 static void genCmpEq (iCode *ic, iCode *ifx)
6663 operand *left, *right, *result;
6664 symbol *falselbl = newiTempLabel(NULL);
6665 symbol *donelbl = newiTempLabel(NULL);
6667 int preserve_result = 0;
6668 int generate_result = 0;
6670 unsigned long lit = -1;
6674 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6675 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6676 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6678 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6680 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6682 werror(W_POSSBUG2, __FILE__, __LINE__);
6683 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6684 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6688 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6690 operand *tmp = right ;
6695 if (AOP_TYPE(right) == AOP_LIT) {
6696 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6699 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6700 preserve_result = 1;
6702 if(result && AOP_SIZE(result))
6703 generate_result = 1;
6705 if(generate_result && !preserve_result)
6707 for(i = 0; i < AOP_SIZE(result); i++)
6708 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6711 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6712 for(i=0; i < AOP_SIZE(left); i++)
6714 if(AOP_TYPE(left) != AOP_ACC)
6717 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6719 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6721 if(is_LitOp(right)) {
6722 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6723 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6726 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6728 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6733 if(generate_result && preserve_result)
6735 for(i = 0; i < AOP_SIZE(result); i++)
6736 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6740 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6742 if(generate_result && preserve_result)
6743 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6745 if(ifx && IC_TRUE(ifx))
6746 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6748 if(ifx && IC_FALSE(ifx))
6749 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6751 pic16_emitpLabel(falselbl->key);
6755 if(ifx && IC_FALSE(ifx))
6756 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6758 if(generate_result && preserve_result)
6760 for(i = 0; i < AOP_SIZE(result); i++)
6761 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6764 pic16_emitpLabel(donelbl->key);
6770 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6771 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6772 pic16_freeAsmop(result,NULL,ic,TRUE);
6778 // old version kept for reference
6780 /*-----------------------------------------------------------------*/
6781 /* genCmpEq - generates code for equal to */
6782 /*-----------------------------------------------------------------*/
6783 static void genCmpEq (iCode *ic, iCode *ifx)
6785 operand *left, *right, *result;
6786 unsigned long lit = 0L;
6788 symbol *falselbl = newiTempLabel(NULL);
6791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6794 DEBUGpic16_emitcode ("; ifx is non-null","");
6796 DEBUGpic16_emitcode ("; ifx is null","");
6798 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6799 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6800 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6802 size = max(AOP_SIZE(left),AOP_SIZE(right));
6804 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6806 /* if literal, literal on the right or
6807 if the right is in a pointer register and left
6809 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6810 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6811 operand *tmp = right ;
6817 if(ifx && !AOP_SIZE(result)){
6819 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6820 /* if they are both bit variables */
6821 if (AOP_TYPE(left) == AOP_CRY &&
6822 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6823 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6824 if(AOP_TYPE(right) == AOP_LIT){
6825 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6827 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6828 pic16_emitcode("cpl","c");
6829 } else if(lit == 1L) {
6830 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832 pic16_emitcode("clr","c");
6834 /* AOP_TYPE(right) == AOP_CRY */
6836 symbol *lbl = newiTempLabel(NULL);
6837 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6839 pic16_emitcode("cpl","c");
6840 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6842 /* if true label then we jump if condition
6844 tlbl = newiTempLabel(NULL);
6845 if ( IC_TRUE(ifx) ) {
6846 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6847 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6849 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6850 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6852 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6855 /* left and right are both bit variables, result is carry */
6858 resolveIfx(&rIfx,ifx);
6860 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6861 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6862 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6863 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6868 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6870 /* They're not both bit variables. Is the right a literal? */
6871 if(AOP_TYPE(right) == AOP_LIT) {
6872 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6877 switch(lit & 0xff) {
6879 if ( IC_TRUE(ifx) ) {
6880 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6882 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6884 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6885 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6889 if ( IC_TRUE(ifx) ) {
6890 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6892 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6894 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6899 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6906 /* end of size == 1 */
6910 genc16bit2lit(left,lit,offset);
6913 /* end of size == 2 */
6918 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6919 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6920 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6921 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6924 /* search for patterns that can be optimized */
6926 genc16bit2lit(left,lit,0);
6930 emitSKPZ; // if hi word unequal
6932 emitSKPNZ; // if hi word equal
6934 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6935 genc16bit2lit(left,lit,2);
6938 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6939 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6943 pic16_emitpLabel(falselbl->key);
6952 } else if(AOP_TYPE(right) == AOP_CRY ) {
6953 /* we know the left is not a bit, but that the right is */
6954 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6955 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6956 pic16_popGet(AOP(right),offset));
6957 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6959 /* if the two are equal, then W will be 0 and the Z bit is set
6960 * we could test Z now, or go ahead and check the high order bytes if
6961 * the variable we're comparing is larger than a byte. */
6964 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6966 if ( IC_TRUE(ifx) ) {
6968 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6969 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6972 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6973 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6977 /* They're both variables that are larger than bits */
6980 tlbl = newiTempLabel(NULL);
6983 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6984 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6986 if ( IC_TRUE(ifx) ) {
6990 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6992 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6993 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6997 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7001 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7006 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7009 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7013 if(s>1 && IC_TRUE(ifx)) {
7014 pic16_emitpLabel(tlbl->key);
7015 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7019 /* mark the icode as generated */
7024 /* if they are both bit variables */
7025 if (AOP_TYPE(left) == AOP_CRY &&
7026 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7027 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7028 if(AOP_TYPE(right) == AOP_LIT){
7029 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7031 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7032 pic16_emitcode("cpl","c");
7033 } else if(lit == 1L) {
7034 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036 pic16_emitcode("clr","c");
7038 /* AOP_TYPE(right) == AOP_CRY */
7040 symbol *lbl = newiTempLabel(NULL);
7041 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7043 pic16_emitcode("cpl","c");
7044 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7047 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7048 pic16_outBitC(result);
7052 genIfxJump (ifx,"c");
7055 /* if the result is used in an arithmetic operation
7056 then put the result in place */
7057 pic16_outBitC(result);
7060 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7061 gencjne(left,right,result,ifx);
7064 gencjne(left,right,newiTempLabel(NULL));
7066 if(IC_TRUE(ifx)->key)
7067 gencjne(left,right,IC_TRUE(ifx)->key);
7069 gencjne(left,right,IC_FALSE(ifx)->key);
7073 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7074 pic16_aopPut(AOP(result),"a",0);
7079 genIfxJump (ifx,"a");
7083 /* if the result is used in an arithmetic operation
7084 then put the result in place */
7086 if (AOP_TYPE(result) != AOP_CRY)
7087 pic16_outAcc(result);
7089 /* leave the result in acc */
7093 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7094 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7095 pic16_freeAsmop(result,NULL,ic,TRUE);
7099 /*-----------------------------------------------------------------*/
7100 /* ifxForOp - returns the icode containing the ifx for operand */
7101 /*-----------------------------------------------------------------*/
7102 static iCode *ifxForOp ( operand *op, iCode *ic )
7106 /* if true symbol then needs to be assigned */
7107 if (IS_TRUE_SYMOP(op))
7110 /* if this has register type condition and
7111 the next instruction is ifx with the same operand
7112 and live to of the operand is upto the ifx only then */
7114 && ic->next->op == IFX
7115 && IC_COND(ic->next)->key == op->key
7116 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7118 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7124 ic->next->op == IFX &&
7125 IC_COND(ic->next)->key == op->key) {
7126 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7131 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7133 ic->next->op == IFX)
7134 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7137 ic->next->op == IFX &&
7138 IC_COND(ic->next)->key == op->key) {
7139 DEBUGpic16_emitcode ("; "," key is okay");
7140 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7141 OP_SYMBOL(op)->liveTo,
7146 /* the code below is completely untested
7147 * it just allows ulong2fs.c compile -- VR */
7150 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7151 __FILE__, __FUNCTION__, __LINE__);
7153 /* if this has register type condition and
7154 the next instruction is ifx with the same operand
7155 and live to of the operand is upto the ifx only then */
7157 ic->next->op == IFX &&
7158 IC_COND(ic->next)->key == op->key &&
7159 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7163 ic->next->op == IFX &&
7164 IC_COND(ic->next)->key == op->key) {
7165 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7169 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7170 __FILE__, __FUNCTION__, __LINE__);
7172 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7177 /*-----------------------------------------------------------------*/
7178 /* genAndOp - for && operation */
7179 /*-----------------------------------------------------------------*/
7180 static void genAndOp (iCode *ic)
7182 operand *left,*right, *result;
7187 /* note here that && operations that are in an
7188 if statement are taken away by backPatchLabels
7189 only those used in arthmetic operations remain */
7190 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7191 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7192 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7194 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7196 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7197 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7198 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7200 /* if both are bit variables */
7201 /* if (AOP_TYPE(left) == AOP_CRY && */
7202 /* AOP_TYPE(right) == AOP_CRY ) { */
7203 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7204 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7205 /* pic16_outBitC(result); */
7207 /* tlbl = newiTempLabel(NULL); */
7208 /* pic16_toBoolean(left); */
7209 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7210 /* pic16_toBoolean(right); */
7211 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7212 /* pic16_outBitAcc(result); */
7215 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7216 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7217 pic16_freeAsmop(result,NULL,ic,TRUE);
7221 /*-----------------------------------------------------------------*/
7222 /* genOrOp - for || operation */
7223 /*-----------------------------------------------------------------*/
7226 modified this code, but it doesn't appear to ever get called
7229 static void genOrOp (iCode *ic)
7231 operand *left,*right, *result;
7236 /* note here that || operations that are in an
7237 if statement are taken away by backPatchLabels
7238 only those used in arthmetic operations remain */
7239 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7240 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7241 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7243 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7245 /* if both are bit variables */
7246 if (AOP_TYPE(left) == AOP_CRY &&
7247 AOP_TYPE(right) == AOP_CRY ) {
7248 pic16_emitcode("clrc","");
7249 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7250 AOP(left)->aopu.aop_dir,
7251 AOP(left)->aopu.aop_dir);
7252 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7253 AOP(right)->aopu.aop_dir,
7254 AOP(right)->aopu.aop_dir);
7255 pic16_emitcode("setc","");
7258 tlbl = newiTempLabel(NULL);
7259 pic16_toBoolean(left);
7261 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7262 pic16_toBoolean(right);
7263 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7265 pic16_outBitAcc(result);
7268 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7269 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7270 pic16_freeAsmop(result,NULL,ic,TRUE);
7273 /*-----------------------------------------------------------------*/
7274 /* isLiteralBit - test if lit == 2^n */
7275 /*-----------------------------------------------------------------*/
7276 static int isLiteralBit(unsigned long lit)
7278 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7279 0x100L,0x200L,0x400L,0x800L,
7280 0x1000L,0x2000L,0x4000L,0x8000L,
7281 0x10000L,0x20000L,0x40000L,0x80000L,
7282 0x100000L,0x200000L,0x400000L,0x800000L,
7283 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7284 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7287 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7288 for(idx = 0; idx < 32; idx++)
7294 /*-----------------------------------------------------------------*/
7295 /* continueIfTrue - */
7296 /*-----------------------------------------------------------------*/
7297 static void continueIfTrue (iCode *ic)
7301 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7305 /*-----------------------------------------------------------------*/
7307 /*-----------------------------------------------------------------*/
7308 static void jumpIfTrue (iCode *ic)
7312 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7316 /*-----------------------------------------------------------------*/
7317 /* jmpTrueOrFalse - */
7318 /*-----------------------------------------------------------------*/
7319 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7321 // ugly but optimized by peephole
7324 symbol *nlbl = newiTempLabel(NULL);
7325 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7326 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7327 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7328 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7330 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7331 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7336 /*-----------------------------------------------------------------*/
7337 /* genAnd - code for and */
7338 /*-----------------------------------------------------------------*/
7339 static void genAnd (iCode *ic, iCode *ifx)
7341 operand *left, *right, *result;
7343 unsigned long lit = 0L;
7349 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7350 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7351 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7353 resolveIfx(&rIfx,ifx);
7355 /* if left is a literal & right is not then exchange them */
7356 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7357 AOP_NEEDSACC(left)) {
7358 operand *tmp = right ;
7363 /* if result = right then exchange them */
7364 if(pic16_sameRegs(AOP(result),AOP(right))){
7365 operand *tmp = right ;
7370 /* if right is bit then exchange them */
7371 if (AOP_TYPE(right) == AOP_CRY &&
7372 AOP_TYPE(left) != AOP_CRY){
7373 operand *tmp = right ;
7377 if(AOP_TYPE(right) == AOP_LIT)
7378 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7380 size = AOP_SIZE(result);
7382 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7385 // result = bit & yy;
7386 if (AOP_TYPE(left) == AOP_CRY){
7387 // c = bit & literal;
7388 if(AOP_TYPE(right) == AOP_LIT){
7390 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7393 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7396 if(size && (AOP_TYPE(result) == AOP_CRY)){
7397 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7400 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7404 pic16_emitcode("clr","c");
7407 if (AOP_TYPE(right) == AOP_CRY){
7409 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7410 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7413 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7415 pic16_emitcode("rrc","a");
7416 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7422 pic16_outBitC(result);
7424 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7425 genIfxJump(ifx, "c");
7429 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7430 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7431 if((AOP_TYPE(right) == AOP_LIT) &&
7432 (AOP_TYPE(result) == AOP_CRY) &&
7433 (AOP_TYPE(left) != AOP_CRY)){
7434 int posbit = isLiteralBit(lit);
7438 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7441 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7447 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7448 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7450 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7451 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7454 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7455 size = AOP_SIZE(left);
7458 int bp = posbit, ofs=0;
7465 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7466 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7470 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7471 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7473 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7480 symbol *tlbl = newiTempLabel(NULL);
7481 int sizel = AOP_SIZE(left);
7487 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7489 /* patch provided by Aaron Colwell */
7490 if((posbit = isLiteralBit(bytelit)) != 0) {
7491 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7492 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7493 (posbit-1),0, PO_GPR_REGISTER));
7495 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7496 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7498 if (bytelit == 0xff) {
7499 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7500 * a peephole could optimize it out -- VR */
7501 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7503 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7504 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7507 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7508 pic16_popGetLabel(tlbl->key));
7512 /* old code, left here for reference -- VR 09/2004 */
7513 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7515 if((posbit = isLiteralBit(bytelit)) != 0)
7516 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7518 if(bytelit != 0x0FFL)
7519 pic16_emitcode("anl","a,%s",
7520 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7521 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7527 // bit = left & literal
7530 pic16_emitpLabel(tlbl->key);
7532 // if(left & literal)
7535 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7538 pic16_emitpLabel(tlbl->key);
7543 pic16_outBitC(result);
7547 /* if left is same as result */
7548 if(pic16_sameRegs(AOP(result),AOP(left))){
7550 for(;size--; offset++,lit>>=8) {
7551 if(AOP_TYPE(right) == AOP_LIT){
7552 switch(lit & 0xff) {
7554 /* and'ing with 0 has clears the result */
7555 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7556 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7559 /* and'ing with 0xff is a nop when the result and left are the same */
7564 int p = pic16_my_powof2( (~lit) & 0xff );
7566 /* only one bit is set in the literal, so use a bcf instruction */
7567 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7568 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7571 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7572 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7573 if(know_W != (lit&0xff))
7574 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7576 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7581 if (AOP_TYPE(left) == AOP_ACC) {
7582 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7584 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7585 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7592 // left & result in different registers
7593 if(AOP_TYPE(result) == AOP_CRY){
7595 // if(size), result in bit
7596 // if(!size && ifx), conditional oper: if(left & right)
7597 symbol *tlbl = newiTempLabel(NULL);
7598 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7600 pic16_emitcode("setb","c");
7602 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7603 pic16_emitcode("anl","a,%s",
7604 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7605 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7610 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7611 pic16_outBitC(result);
7613 jmpTrueOrFalse(ifx, tlbl);
7615 for(;(size--);offset++) {
7617 // result = left & right
7618 if(AOP_TYPE(right) == AOP_LIT){
7619 int t = (lit >> (offset*8)) & 0x0FFL;
7622 pic16_emitcode("clrf","%s",
7623 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7624 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7627 pic16_emitcode("movf","%s,w",
7628 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7629 pic16_emitcode("movwf","%s",
7630 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7631 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7632 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7635 pic16_emitcode("movlw","0x%x",t);
7636 pic16_emitcode("andwf","%s,w",
7637 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7638 pic16_emitcode("movwf","%s",
7639 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7641 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7642 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7643 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7648 if (AOP_TYPE(left) == AOP_ACC) {
7649 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7650 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7652 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7653 pic16_emitcode("andwf","%s,w",
7654 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7655 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7656 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7658 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7659 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7665 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7666 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7667 pic16_freeAsmop(result,NULL,ic,TRUE);
7670 /*-----------------------------------------------------------------*/
7671 /* genOr - code for or */
7672 /*-----------------------------------------------------------------*/
7673 static void genOr (iCode *ic, iCode *ifx)
7675 operand *left, *right, *result;
7677 unsigned long lit = 0L;
7679 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7681 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7682 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7683 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7685 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7687 /* if left is a literal & right is not then exchange them */
7688 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7689 AOP_NEEDSACC(left)) {
7690 operand *tmp = right ;
7695 /* if result = right then exchange them */
7696 if(pic16_sameRegs(AOP(result),AOP(right))){
7697 operand *tmp = right ;
7702 /* if right is bit then exchange them */
7703 if (AOP_TYPE(right) == AOP_CRY &&
7704 AOP_TYPE(left) != AOP_CRY){
7705 operand *tmp = right ;
7710 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7712 if(AOP_TYPE(right) == AOP_LIT)
7713 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7715 size = AOP_SIZE(result);
7719 if (AOP_TYPE(left) == AOP_CRY){
7720 if(AOP_TYPE(right) == AOP_LIT){
7721 // c = bit & literal;
7723 // lit != 0 => result = 1
7724 if(AOP_TYPE(result) == AOP_CRY){
7726 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7727 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7728 // AOP(result)->aopu.aop_dir,
7729 // AOP(result)->aopu.aop_dir);
7731 continueIfTrue(ifx);
7735 // lit == 0 => result = left
7736 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7738 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7741 if (AOP_TYPE(right) == AOP_CRY){
7742 if(pic16_sameRegs(AOP(result),AOP(left))){
7744 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7745 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7746 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7748 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7749 AOP(result)->aopu.aop_dir,
7750 AOP(result)->aopu.aop_dir);
7751 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7752 AOP(right)->aopu.aop_dir,
7753 AOP(right)->aopu.aop_dir);
7754 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7755 AOP(result)->aopu.aop_dir,
7756 AOP(result)->aopu.aop_dir);
7758 if( AOP_TYPE(result) == AOP_ACC) {
7759 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7760 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7761 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7762 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7766 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7767 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7768 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7769 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7771 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7772 AOP(result)->aopu.aop_dir,
7773 AOP(result)->aopu.aop_dir);
7774 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7775 AOP(right)->aopu.aop_dir,
7776 AOP(right)->aopu.aop_dir);
7777 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7778 AOP(left)->aopu.aop_dir,
7779 AOP(left)->aopu.aop_dir);
7780 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7781 AOP(result)->aopu.aop_dir,
7782 AOP(result)->aopu.aop_dir);
7787 symbol *tlbl = newiTempLabel(NULL);
7788 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7791 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7792 if( AOP_TYPE(right) == AOP_ACC) {
7793 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7795 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7796 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7801 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7802 pic16_emitcode(";XXX setb","c");
7803 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7804 AOP(left)->aopu.aop_dir,tlbl->key+100);
7805 pic16_toBoolean(right);
7806 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7807 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7808 jmpTrueOrFalse(ifx, tlbl);
7812 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7819 pic16_outBitC(result);
7821 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7822 genIfxJump(ifx, "c");
7826 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7827 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7828 if((AOP_TYPE(right) == AOP_LIT) &&
7829 (AOP_TYPE(result) == AOP_CRY) &&
7830 (AOP_TYPE(left) != AOP_CRY)){
7832 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7835 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7837 continueIfTrue(ifx);
7840 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7841 // lit = 0, result = boolean(left)
7843 pic16_emitcode(";XXX setb","c");
7844 pic16_toBoolean(right);
7846 symbol *tlbl = newiTempLabel(NULL);
7847 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7849 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7851 genIfxJump (ifx,"a");
7855 pic16_outBitC(result);
7859 /* if left is same as result */
7860 if(pic16_sameRegs(AOP(result),AOP(left))){
7862 for(;size--; offset++,lit>>=8) {
7863 if(AOP_TYPE(right) == AOP_LIT){
7864 if((lit & 0xff) == 0)
7865 /* or'ing with 0 has no effect */
7868 int p = pic16_my_powof2(lit & 0xff);
7870 /* only one bit is set in the literal, so use a bsf instruction */
7871 pic16_emitpcode(POC_BSF,
7872 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7874 if(know_W != (lit & 0xff))
7875 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7876 know_W = lit & 0xff;
7877 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7882 if (AOP_TYPE(left) == AOP_ACC) {
7883 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7884 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7886 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7887 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7889 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7890 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7896 // left & result in different registers
7897 if(AOP_TYPE(result) == AOP_CRY){
7899 // if(size), result in bit
7900 // if(!size && ifx), conditional oper: if(left | right)
7901 symbol *tlbl = newiTempLabel(NULL);
7902 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7903 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7907 pic16_emitcode(";XXX setb","c");
7909 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910 pic16_emitcode(";XXX orl","a,%s",
7911 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7912 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7917 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7918 pic16_outBitC(result);
7920 jmpTrueOrFalse(ifx, tlbl);
7921 } else for(;(size--);offset++){
7923 // result = left & right
7924 if(AOP_TYPE(right) == AOP_LIT){
7925 int t = (lit >> (offset*8)) & 0x0FFL;
7928 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7931 // pic16_emitcode("movf","%s,w",
7932 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7933 // pic16_emitcode("movwf","%s",
7934 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7937 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7938 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7941 // pic16_emitcode("movlw","0x%x",t);
7942 // pic16_emitcode("iorwf","%s,w",
7943 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7944 // pic16_emitcode("movwf","%s",
7945 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7951 // faster than result <- left, anl result,right
7952 // and better if result is SFR
7953 if (AOP_TYPE(left) == AOP_ACC) {
7954 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7955 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7957 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7958 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7960 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7961 // pic16_emitcode("iorwf","%s,w",
7962 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7965 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7970 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7971 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7972 pic16_freeAsmop(result,NULL,ic,TRUE);
7975 /*-----------------------------------------------------------------*/
7976 /* genXor - code for xclusive or */
7977 /*-----------------------------------------------------------------*/
7978 static void genXor (iCode *ic, iCode *ifx)
7980 operand *left, *right, *result;
7982 unsigned long lit = 0L;
7984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7986 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7987 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7988 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7990 /* if left is a literal & right is not ||
7991 if left needs acc & right does not */
7992 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7993 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7994 operand *tmp = right ;
7999 /* if result = right then exchange them */
8000 if(pic16_sameRegs(AOP(result),AOP(right))){
8001 operand *tmp = right ;
8006 /* if right is bit then exchange them */
8007 if (AOP_TYPE(right) == AOP_CRY &&
8008 AOP_TYPE(left) != AOP_CRY){
8009 operand *tmp = right ;
8013 if(AOP_TYPE(right) == AOP_LIT)
8014 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8016 size = AOP_SIZE(result);
8020 if (AOP_TYPE(left) == AOP_CRY){
8021 if(AOP_TYPE(right) == AOP_LIT){
8022 // c = bit & literal;
8024 // lit>>1 != 0 => result = 1
8025 if(AOP_TYPE(result) == AOP_CRY){
8027 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8028 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8030 continueIfTrue(ifx);
8033 pic16_emitcode("setb","c");
8037 // lit == 0, result = left
8038 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8040 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8042 // lit == 1, result = not(left)
8043 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8044 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8045 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8046 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8049 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8050 pic16_emitcode("cpl","c");
8057 symbol *tlbl = newiTempLabel(NULL);
8058 if (AOP_TYPE(right) == AOP_CRY){
8060 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8063 int sizer = AOP_SIZE(right);
8065 // if val>>1 != 0, result = 1
8066 pic16_emitcode("setb","c");
8068 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8070 // test the msb of the lsb
8071 pic16_emitcode("anl","a,#0xfe");
8072 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8076 pic16_emitcode("rrc","a");
8078 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8079 pic16_emitcode("cpl","c");
8080 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8085 pic16_outBitC(result);
8087 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8088 genIfxJump(ifx, "c");
8092 if(pic16_sameRegs(AOP(result),AOP(left))){
8093 /* if left is same as result */
8094 for(;size--; offset++) {
8095 if(AOP_TYPE(right) == AOP_LIT){
8096 int t = (lit >> (offset*8)) & 0x0FFL;
8100 if (IS_AOP_PREG(left)) {
8101 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8102 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8103 pic16_aopPut(AOP(result),"a",offset);
8105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8106 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8107 pic16_emitcode("xrl","%s,%s",
8108 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8109 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112 if (AOP_TYPE(left) == AOP_ACC)
8113 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8115 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8116 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8118 if (IS_AOP_PREG(left)) {
8119 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8120 pic16_aopPut(AOP(result),"a",offset);
8122 pic16_emitcode("xrl","%s,a",
8123 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8129 // left & result in different registers
8130 if(AOP_TYPE(result) == AOP_CRY){
8132 // if(size), result in bit
8133 // if(!size && ifx), conditional oper: if(left ^ right)
8134 symbol *tlbl = newiTempLabel(NULL);
8135 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8137 pic16_emitcode("setb","c");
8139 if((AOP_TYPE(right) == AOP_LIT) &&
8140 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8141 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8143 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8144 pic16_emitcode("xrl","a,%s",
8145 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8147 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8152 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8153 pic16_outBitC(result);
8155 jmpTrueOrFalse(ifx, tlbl);
8156 } else for(;(size--);offset++){
8158 // result = left & right
8159 if(AOP_TYPE(right) == AOP_LIT){
8160 int t = (lit >> (offset*8)) & 0x0FFL;
8163 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8165 pic16_emitcode("movf","%s,w",
8166 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8167 pic16_emitcode("movwf","%s",
8168 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8171 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8173 pic16_emitcode("comf","%s,w",
8174 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8175 pic16_emitcode("movwf","%s",
8176 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8179 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8180 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8181 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8182 pic16_emitcode("movlw","0x%x",t);
8183 pic16_emitcode("xorwf","%s,w",
8184 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185 pic16_emitcode("movwf","%s",
8186 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8192 // faster than result <- left, anl result,right
8193 // and better if result is SFR
8194 if (AOP_TYPE(left) == AOP_ACC) {
8195 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8196 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8198 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8199 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8200 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8201 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8203 if ( AOP_TYPE(result) != AOP_ACC){
8204 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8205 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8211 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8212 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8213 pic16_freeAsmop(result,NULL,ic,TRUE);
8216 /*-----------------------------------------------------------------*/
8217 /* genInline - write the inline code out */
8218 /*-----------------------------------------------------------------*/
8219 static void genInline (iCode *ic)
8221 char *buffer, *bp, *bp1;
8223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8225 _G.inLine += (!options.asmpeep);
8227 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8228 strcpy(buffer,IC_INLINE(ic));
8230 while((bp1=strstr(bp, "\\n"))) {
8238 /* This is an experimental code for #pragma inline
8239 and is temporarily disabled for 2.5.0 release */
8247 cbuf = Safe_strdup(buffer);
8248 cblen = strlen(buffer)+1;
8249 memset(cbuf, 0, cblen);
8254 if(*bp != '%')*bp1++ = *bp++;
8260 if(i>elementsInSet(asmInlineMap))break;
8263 s = indexSet(asmInlineMap, i);
8264 DEBUGpc("searching symbol s = `%s'", s);
8265 sym = findSym(SymbolTab, NULL, s);
8268 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8270 strcat(bp1, sym->rname);
8276 if(strlen(bp1) > cblen - 16) {
8277 int i = strlen(cbuf);
8279 cbuf = realloc(cbuf, cblen);
8280 memset(cbuf+i, 0, 50);
8286 buffer = Safe_strdup( cbuf );
8293 /* emit each line as a code */
8299 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8307 /* print label, use this special format with NULL directive
8308 * to denote that the argument should not be indented with tab */
8309 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8312 /* advance to end of line (prevent splitting of comments at ':' */
8313 while (*bp && *bp != '\n') {
8321 if ((bp1 != bp) && *bp1)
8322 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8327 _G.inLine -= (!options.asmpeep);
8330 /*-----------------------------------------------------------------*/
8331 /* genRRC - rotate right with carry */
8332 /*-----------------------------------------------------------------*/
8333 static void genRRC (iCode *ic)
8335 operand *left , *result ;
8336 int size, offset = 0, same;
8338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8340 /* rotate right with carry */
8342 result=IC_RESULT(ic);
8343 pic16_aopOp (left,ic,FALSE);
8344 pic16_aopOp (result,ic,TRUE);
8346 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8348 same = pic16_sameRegs(AOP(result),AOP(left));
8350 size = AOP_SIZE(result);
8352 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8354 /* get the lsb and put it into the carry */
8355 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8362 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8364 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8365 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8371 pic16_freeAsmop(left,NULL,ic,TRUE);
8372 pic16_freeAsmop(result,NULL,ic,TRUE);
8375 /*-----------------------------------------------------------------*/
8376 /* genRLC - generate code for rotate left with carry */
8377 /*-----------------------------------------------------------------*/
8378 static void genRLC (iCode *ic)
8380 operand *left , *result ;
8381 int size, offset = 0;
8384 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8385 /* rotate right with carry */
8387 result=IC_RESULT(ic);
8388 pic16_aopOp (left,ic,FALSE);
8389 pic16_aopOp (result,ic,TRUE);
8391 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8393 same = pic16_sameRegs(AOP(result),AOP(left));
8395 /* move it to the result */
8396 size = AOP_SIZE(result);
8398 /* get the msb and put it into the carry */
8399 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8406 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8408 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8409 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8416 pic16_freeAsmop(left,NULL,ic,TRUE);
8417 pic16_freeAsmop(result,NULL,ic,TRUE);
8421 /* gpasm can get the highest order bit with HIGH/UPPER
8422 * so the following probably is not needed -- VR */
8424 /*-----------------------------------------------------------------*/
8425 /* genGetHbit - generates code get highest order bit */
8426 /*-----------------------------------------------------------------*/
8427 static void genGetHbit (iCode *ic)
8429 operand *left, *result;
8431 result=IC_RESULT(ic);
8432 pic16_aopOp (left,ic,FALSE);
8433 pic16_aopOp (result,ic,FALSE);
8435 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8436 /* get the highest order byte into a */
8437 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8438 if(AOP_TYPE(result) == AOP_CRY){
8439 pic16_emitcode("rlc","a");
8440 pic16_outBitC(result);
8443 pic16_emitcode("rl","a");
8444 pic16_emitcode("anl","a,#0x01");
8445 pic16_outAcc(result);
8449 pic16_freeAsmop(left,NULL,ic,TRUE);
8450 pic16_freeAsmop(result,NULL,ic,TRUE);
8454 /*-----------------------------------------------------------------*/
8455 /* AccRol - rotate left accumulator by known count */
8456 /*-----------------------------------------------------------------*/
8457 static void AccRol (int shCount)
8459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8460 shCount &= 0x0007; // shCount : 0..7
8465 pic16_emitcode("rl","a");
8468 pic16_emitcode("rl","a");
8469 pic16_emitcode("rl","a");
8472 pic16_emitcode("swap","a");
8473 pic16_emitcode("rr","a");
8476 pic16_emitcode("swap","a");
8479 pic16_emitcode("swap","a");
8480 pic16_emitcode("rl","a");
8483 pic16_emitcode("rr","a");
8484 pic16_emitcode("rr","a");
8487 pic16_emitcode("rr","a");
8493 /*-----------------------------------------------------------------*/
8494 /* AccLsh - left shift accumulator by known count */
8495 /*-----------------------------------------------------------------*/
8496 static void AccLsh (int shCount, int doMask)
8498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8504 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8507 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8511 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8515 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8518 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8526 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8530 /* no masking is required in genPackBits */
8531 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8535 /*-----------------------------------------------------------------*/
8536 /* AccRsh - right shift accumulator by known count */
8537 /*-----------------------------------------------------------------*/
8538 static void AccRsh (int shCount, int andmask)
8540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8545 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8548 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8553 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8572 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8574 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8578 /*-----------------------------------------------------------------*/
8579 /* AccSRsh - signed right shift accumulator by known count */
8580 /*-----------------------------------------------------------------*/
8581 static void AccSRsh (int shCount)
8584 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8587 pic16_emitcode("mov","c,acc.7");
8588 pic16_emitcode("rrc","a");
8589 } else if(shCount == 2){
8590 pic16_emitcode("mov","c,acc.7");
8591 pic16_emitcode("rrc","a");
8592 pic16_emitcode("mov","c,acc.7");
8593 pic16_emitcode("rrc","a");
8595 tlbl = newiTempLabel(NULL);
8596 /* rotate right accumulator */
8597 AccRol(8 - shCount);
8598 /* and kill the higher order bits */
8599 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8600 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8601 pic16_emitcode("orl","a,#0x%02x",
8602 (unsigned char)~SRMask[shCount]);
8603 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8609 /*-----------------------------------------------------------------*/
8610 /* shiftR1Left2Result - shift right one byte from left to result */
8611 /*-----------------------------------------------------------------*/
8612 static void shiftR1Left2ResultSigned (operand *left, int offl,
8613 operand *result, int offr,
8618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8620 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8624 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8626 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8628 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8635 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8637 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8639 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8640 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8643 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8649 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8652 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8655 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8656 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8657 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8659 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8660 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8662 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8666 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8667 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8668 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8669 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8670 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8674 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8676 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8681 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8682 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8683 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8688 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8689 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8690 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8692 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8697 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8699 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8705 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8706 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8711 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8712 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8720 /*-----------------------------------------------------------------*/
8721 /* shiftR1Left2Result - shift right one byte from left to result */
8722 /*-----------------------------------------------------------------*/
8723 static void shiftR1Left2Result (operand *left, int offl,
8724 operand *result, int offr,
8725 int shCount, int sign)
8729 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8731 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8733 /* Copy the msb into the carry if signed. */
8735 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8745 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8747 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8748 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8754 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8756 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8760 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8765 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8771 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8772 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8774 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8779 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8784 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8785 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8793 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8794 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8795 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8796 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8797 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8802 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8803 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8813 /*-----------------------------------------------------------------*/
8814 /* shiftL1Left2Result - shift left one byte from left to result */
8815 /*-----------------------------------------------------------------*/
8816 static void shiftL1Left2Result (operand *left, int offl,
8817 operand *result, int offr, int shCount)
8822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8824 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8825 DEBUGpic16_emitcode ("; ***","same = %d",same);
8826 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8828 /* shift left accumulator */
8829 //AccLsh(shCount, 1); // don't comment out just yet...
8830 // pic16_aopPut(AOP(result),"a",offr);
8834 /* Shift left 1 bit position */
8835 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8837 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8839 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8844 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8845 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8846 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8851 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8852 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8853 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8863 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8864 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8869 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8870 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8876 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8881 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8886 /*-----------------------------------------------------------------*/
8887 /* movLeft2Result - move byte from left to result */
8888 /*-----------------------------------------------------------------*/
8889 static void movLeft2Result (operand *left, int offl,
8890 operand *result, int offr)
8893 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8894 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8895 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8897 if (*l == '@' && (IS_AOP_PREG(result))) {
8898 pic16_emitcode("mov","a,%s",l);
8899 pic16_aopPut(AOP(result),"a",offr);
8901 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8907 /*-----------------------------------------------------------------*/
8908 /* shiftL2Left2Result - shift left two bytes from left to result */
8909 /*-----------------------------------------------------------------*/
8910 static void shiftL2Left2Result (operand *left, int offl,
8911 operand *result, int offr, int shCount)
8913 int same = pic16_sameRegs(AOP(result), AOP(left));
8916 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8918 if (same && (offl != offr)) { // shift bytes
8921 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8922 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8924 } else { // just treat as different later on
8937 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8943 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8951 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8952 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8958 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8963 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8968 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8969 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8976 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8989 /* note, use a mov/add for the shift since the mov has a
8990 chance of getting optimized out */
8991 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8999 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9000 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9006 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9007 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9009 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9010 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9011 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9012 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9017 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9023 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9025 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9028 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9030 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9031 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9037 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9038 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9039 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9046 /*-----------------------------------------------------------------*/
9047 /* shiftR2Left2Result - shift right two bytes from left to result */
9048 /*-----------------------------------------------------------------*/
9049 static void shiftR2Left2Result (operand *left, int offl,
9050 operand *result, int offr,
9051 int shCount, int sign)
9053 int same = pic16_sameRegs(AOP(result), AOP(left));
9055 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9057 if (same && (offl != offr)) { // shift right bytes
9060 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9061 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9063 } else { // just treat as different later on
9075 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9081 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9083 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9084 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9085 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9086 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9091 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9094 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9095 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9102 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9103 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9104 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9107 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9108 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9109 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9112 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9113 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9116 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9117 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9118 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9119 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9123 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9124 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9129 pic16_emitpcode(POC_BTFSC,
9130 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9131 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9139 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9144 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9145 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9147 pic16_emitpcode(POC_BTFSC,
9148 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9149 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9151 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9152 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9156 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9157 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9159 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9160 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9162 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9163 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9165 pic16_emitpcode(POC_BTFSC,
9166 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9167 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9169 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9170 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9177 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9178 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9179 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9183 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9185 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9190 /*-----------------------------------------------------------------*/
9191 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9192 /*-----------------------------------------------------------------*/
9193 static void shiftLLeftOrResult (operand *left, int offl,
9194 operand *result, int offr, int shCount)
9196 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9198 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9199 /* shift left accumulator */
9201 /* or with result */
9202 /* back to result */
9203 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9206 /*-----------------------------------------------------------------*/
9207 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9208 /*-----------------------------------------------------------------*/
9209 static void shiftRLeftOrResult (operand *left, int offl,
9210 operand *result, int offr, int shCount)
9212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9214 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9215 /* shift right accumulator */
9217 /* or with result */
9218 /* back to result */
9219 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9222 /*-----------------------------------------------------------------*/
9223 /* genlshOne - left shift a one byte quantity by known count */
9224 /*-----------------------------------------------------------------*/
9225 static void genlshOne (operand *result, operand *left, int shCount)
9227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9228 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9231 /*-----------------------------------------------------------------*/
9232 /* genlshTwo - left shift two bytes by known amount != 0 */
9233 /*-----------------------------------------------------------------*/
9234 static void genlshTwo (operand *result,operand *left, int shCount)
9238 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9239 size = pic16_getDataSize(result);
9241 /* if shCount >= 8 */
9247 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9249 movLeft2Result(left, LSB, result, MSB16);
9251 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9254 /* 1 <= shCount <= 7 */
9257 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9259 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9263 /*-----------------------------------------------------------------*/
9264 /* shiftLLong - shift left one long from left to result */
9265 /* offr = LSB or MSB16 */
9266 /*-----------------------------------------------------------------*/
9267 static void shiftLLong (operand *left, operand *result, int offr )
9269 int size = AOP_SIZE(result);
9270 int same = pic16_sameRegs(AOP(left),AOP(result));
9273 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9275 if (same && (offr == MSB16)) { //shift one byte
9276 for(i=size-1;i>=MSB16;i--) {
9277 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9278 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9281 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9284 if (size > LSB+offr ){
9286 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9288 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9289 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9293 if(size > MSB16+offr){
9295 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9297 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9298 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9302 if(size > MSB24+offr){
9304 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9306 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9307 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9311 if(size > MSB32+offr){
9313 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9315 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9316 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9320 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9324 /*-----------------------------------------------------------------*/
9325 /* genlshFour - shift four byte by a known amount != 0 */
9326 /*-----------------------------------------------------------------*/
9327 static void genlshFour (operand *result, operand *left, int shCount)
9331 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9332 size = AOP_SIZE(result);
9334 /* if shifting more that 3 bytes */
9335 if (shCount >= 24 ) {
9338 /* lowest order of left goes to the highest
9339 order of the destination */
9340 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9342 movLeft2Result(left, LSB, result, MSB32);
9344 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9345 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9346 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9351 /* more than two bytes */
9352 else if ( shCount >= 16 ) {
9353 /* lower order two bytes goes to higher order two bytes */
9355 /* if some more remaining */
9357 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9359 movLeft2Result(left, MSB16, result, MSB32);
9360 movLeft2Result(left, LSB, result, MSB24);
9362 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9363 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9367 /* if more than 1 byte */
9368 else if ( shCount >= 8 ) {
9369 /* lower order three bytes goes to higher order three bytes */
9373 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9375 movLeft2Result(left, LSB, result, MSB16);
9377 else{ /* size = 4 */
9379 movLeft2Result(left, MSB24, result, MSB32);
9380 movLeft2Result(left, MSB16, result, MSB24);
9381 movLeft2Result(left, LSB, result, MSB16);
9382 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9384 else if(shCount == 1)
9385 shiftLLong(left, result, MSB16);
9387 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9388 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9389 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9390 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9395 /* 1 <= shCount <= 7 */
9396 else if(shCount <= 3)
9398 shiftLLong(left, result, LSB);
9399 while(--shCount >= 1)
9400 shiftLLong(result, result, LSB);
9402 /* 3 <= shCount <= 7, optimize */
9404 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9405 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9406 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9410 /*-----------------------------------------------------------------*/
9411 /* genLeftShiftLiteral - left shifting by known count */
9412 /*-----------------------------------------------------------------*/
9413 void pic16_genLeftShiftLiteral (operand *left,
9418 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9422 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9423 pic16_freeAsmop(right,NULL,ic,TRUE);
9425 pic16_aopOp(left,ic,FALSE);
9426 pic16_aopOp(result,ic,TRUE);
9428 size = getSize(operandType(result));
9431 pic16_emitcode("; shift left ","result %d, left %d",size,
9435 /* I suppose that the left size >= result size */
9438 movLeft2Result(left, size, result, size);
9442 else if(shCount >= (size * 8))
9444 pic16_aopPut(AOP(result),zero,size);
9448 genlshOne (result,left,shCount);
9453 genlshTwo (result,left,shCount);
9457 genlshFour (result,left,shCount);
9461 pic16_freeAsmop(left,NULL,ic,TRUE);
9462 pic16_freeAsmop(result,NULL,ic,TRUE);
9465 /*-----------------------------------------------------------------*
9466 * genMultiAsm - repeat assembly instruction for size of register.
9467 * if endian == 1, then the high byte (i.e base address + size of
9468 * register) is used first else the low byte is used first;
9469 *-----------------------------------------------------------------*/
9470 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9488 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9494 #if !(USE_GENERIC_SIGNED_SHIFT)
9495 /*-----------------------------------------------------------------*/
9496 /* genLeftShift - generates code for left shifting */
9497 /*-----------------------------------------------------------------*/
9498 static void genLeftShift (iCode *ic)
9500 operand *left,*right, *result;
9503 symbol *tlbl , *tlbl1;
9506 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9508 right = IC_RIGHT(ic);
9510 result = IC_RESULT(ic);
9512 pic16_aopOp(right,ic,FALSE);
9514 /* if the shift count is known then do it
9515 as efficiently as possible */
9516 if (AOP_TYPE(right) == AOP_LIT) {
9517 pic16_genLeftShiftLiteral (left,right,result,ic);
9521 /* shift count is unknown then we have to form
9522 * a loop. Get the loop count in WREG : Note: we take
9523 * only the lower order byte since shifting
9524 * more than 32 bits make no sense anyway, ( the
9525 * largest size of an object can be only 32 bits ) */
9527 pic16_aopOp(left,ic,FALSE);
9528 pic16_aopOp(result,ic,FALSE);
9530 /* now move the left to the result if they are not the
9531 * same, and if size > 1,
9532 * and if right is not same to result (!!!) -- VR */
9533 if (!pic16_sameRegs(AOP(left),AOP(result))
9534 && (AOP_SIZE(result) > 1)) {
9536 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9538 size = AOP_SIZE(result);
9543 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9544 if (*l == '@' && (IS_AOP_PREG(result))) {
9546 pic16_emitcode("mov","a,%s",l);
9547 pic16_aopPut(AOP(result),"a",offset);
9551 /* we don't know if left is a literal or a register, take care -- VR */
9552 pic16_mov2f(AOP(result), AOP(left), offset);
9558 size = AOP_SIZE(result);
9560 /* if it is only one byte then */
9562 if(optimized_for_speed) {
9563 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9564 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9565 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9566 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9568 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9569 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9570 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9571 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9572 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9573 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9574 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9579 tlbl = newiTempLabel(NULL);
9582 /* this is already done, why change it? */
9583 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9584 pic16_mov2f(AOP(result), AOP(left), 0);
9588 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9589 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9590 pic16_emitpLabel(tlbl->key);
9591 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9592 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9599 if (pic16_sameRegs(AOP(left),AOP(result))) {
9601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9603 tlbl = newiTempLabel(NULL);
9604 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9605 genMultiAsm(POC_RRCF, result, size,1);
9606 pic16_emitpLabel(tlbl->key);
9607 genMultiAsm(POC_RLCF, result, size,0);
9608 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9610 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9614 //tlbl = newiTempLabel(NULL);
9616 //tlbl1 = newiTempLabel(NULL);
9618 //reAdjustPreg(AOP(result));
9620 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9621 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9622 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9624 //pic16_emitcode("add","a,acc");
9625 //pic16_aopPut(AOP(result),"a",offset++);
9627 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9629 // pic16_emitcode("rlc","a");
9630 // pic16_aopPut(AOP(result),"a",offset++);
9632 //reAdjustPreg(AOP(result));
9634 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9635 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9638 tlbl = newiTempLabel(NULL);
9639 tlbl1= newiTempLabel(NULL);
9641 size = AOP_SIZE(result);
9644 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9646 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9648 /* offset should be 0, 1 or 3 */
9650 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9652 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9654 pic16_emitpcode(POC_MOVWF, pctemp);
9657 pic16_emitpLabel(tlbl->key);
9660 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9662 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9664 pic16_emitpcode(POC_DECFSZ, pctemp);
9665 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9666 pic16_emitpLabel(tlbl1->key);
9668 pic16_popReleaseTempReg(pctemp,1);
9672 pic16_freeAsmop (right,NULL,ic,TRUE);
9673 pic16_freeAsmop(left,NULL,ic,TRUE);
9674 pic16_freeAsmop(result,NULL,ic,TRUE);
9680 #error old code (left here for reference)
9681 /*-----------------------------------------------------------------*/
9682 /* genLeftShift - generates code for left shifting */
9683 /*-----------------------------------------------------------------*/
9684 static void genLeftShift (iCode *ic)
9686 operand *left,*right, *result;
9689 symbol *tlbl , *tlbl1;
9692 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9694 right = IC_RIGHT(ic);
9696 result = IC_RESULT(ic);
9698 pic16_aopOp(right,ic,FALSE);
9700 /* if the shift count is known then do it
9701 as efficiently as possible */
9702 if (AOP_TYPE(right) == AOP_LIT) {
9703 pic16_genLeftShiftLiteral (left,right,result,ic);
9707 /* shift count is unknown then we have to form
9708 a loop get the loop count in B : Note: we take
9709 only the lower order byte since shifting
9710 more that 32 bits make no sense anyway, ( the
9711 largest size of an object can be only 32 bits ) */
9714 pic16_aopOp(left,ic,FALSE);
9715 pic16_aopOp(result,ic,FALSE);
9717 /* now move the left to the result if they are not the
9719 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9720 AOP_SIZE(result) > 1) {
9722 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9724 size = AOP_SIZE(result);
9727 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9728 if (*l == '@' && (IS_AOP_PREG(result))) {
9730 pic16_emitcode("mov","a,%s",l);
9731 pic16_aopPut(AOP(result),"a",offset);
9734 /* we don't know if left is a literal or a register, take care -- VR */
9735 pic16_mov2f(AOP(result), AOP(left), offset);
9741 size = AOP_SIZE(result);
9743 /* if it is only one byte then */
9745 if(optimized_for_speed) {
9746 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9747 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9748 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9749 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9750 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9751 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9752 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9753 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9754 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9755 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9756 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9757 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9762 tlbl = newiTempLabel(NULL);
9763 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9764 pic16_mov2f(AOP(result), AOP(left), 0);
9766 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9767 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9770 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9771 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9772 pic16_emitpLabel(tlbl->key);
9773 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9774 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9776 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9781 if (pic16_sameRegs(AOP(left),AOP(result))) {
9783 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9785 tlbl = newiTempLabel(NULL);
9786 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9787 genMultiAsm(POC_RRCF, result, size,1);
9788 pic16_emitpLabel(tlbl->key);
9789 genMultiAsm(POC_RLCF, result, size,0);
9790 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9792 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9796 //tlbl = newiTempLabel(NULL);
9798 //tlbl1 = newiTempLabel(NULL);
9800 //reAdjustPreg(AOP(result));
9802 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9803 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9804 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9806 //pic16_emitcode("add","a,acc");
9807 //pic16_aopPut(AOP(result),"a",offset++);
9809 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9811 // pic16_emitcode("rlc","a");
9812 // pic16_aopPut(AOP(result),"a",offset++);
9814 //reAdjustPreg(AOP(result));
9816 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9817 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9820 tlbl = newiTempLabel(NULL);
9821 tlbl1= newiTempLabel(NULL);
9823 size = AOP_SIZE(result);
9826 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9828 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9830 /* offset should be 0, 1 or 3 */
9832 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9834 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9836 pic16_emitpcode(POC_MOVWF, pctemp);
9839 pic16_emitpLabel(tlbl->key);
9842 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9844 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9846 pic16_emitpcode(POC_DECFSZ, pctemp);
9847 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9848 pic16_emitpLabel(tlbl1->key);
9850 pic16_popReleaseTempReg(pctemp,1);
9854 pic16_freeAsmop (right,NULL,ic,TRUE);
9855 pic16_freeAsmop(left,NULL,ic,TRUE);
9856 pic16_freeAsmop(result,NULL,ic,TRUE);
9860 /*-----------------------------------------------------------------*/
9861 /* genrshOne - right shift a one byte quantity by known count */
9862 /*-----------------------------------------------------------------*/
9863 static void genrshOne (operand *result, operand *left,
9864 int shCount, int sign)
9866 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9867 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9870 /*-----------------------------------------------------------------*/
9871 /* genrshTwo - right shift two bytes by known amount != 0 */
9872 /*-----------------------------------------------------------------*/
9873 static void genrshTwo (operand *result,operand *left,
9874 int shCount, int sign)
9876 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9877 /* if shCount >= 8 */
9881 shiftR1Left2Result(left, MSB16, result, LSB,
9884 movLeft2Result(left, MSB16, result, LSB);
9886 pic16_addSign (result, 1, sign);
9889 /* 1 <= shCount <= 7 */
9891 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9894 /*-----------------------------------------------------------------*/
9895 /* shiftRLong - shift right one long from left to result */
9896 /* offl = LSB or MSB16 */
9897 /*-----------------------------------------------------------------*/
9898 static void shiftRLong (operand *left, int offl,
9899 operand *result, int sign)
9901 int size = AOP_SIZE(result);
9902 int same = pic16_sameRegs(AOP(left),AOP(result));
9904 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9906 if (same && (offl == MSB16)) { //shift one byte right
9907 for(i=MSB16;i<size;i++) {
9908 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9909 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9914 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9920 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9922 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9927 /* add sign of "a" */
9928 pic16_addSign(result, MSB32, sign);
9932 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9934 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9955 /*-----------------------------------------------------------------*/
9956 /* genrshFour - shift four byte by a known amount != 0 */
9957 /*-----------------------------------------------------------------*/
9958 static void genrshFour (operand *result, operand *left,
9959 int shCount, int sign)
9961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9962 /* if shifting more that 3 bytes */
9963 if(shCount >= 24 ) {
9966 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9968 movLeft2Result(left, MSB32, result, LSB);
9970 pic16_addSign(result, MSB16, sign);
9972 else if(shCount >= 16){
9975 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9977 movLeft2Result(left, MSB24, result, LSB);
9978 movLeft2Result(left, MSB32, result, MSB16);
9980 pic16_addSign(result, MSB24, sign);
9982 else if(shCount >= 8){
9985 shiftRLong(left, MSB16, result, sign);
9986 else if(shCount == 0){
9987 movLeft2Result(left, MSB16, result, LSB);
9988 movLeft2Result(left, MSB24, result, MSB16);
9989 movLeft2Result(left, MSB32, result, MSB24);
9990 pic16_addSign(result, MSB32, sign);
9992 else{ //shcount >= 2
9993 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9994 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9995 /* the last shift is signed */
9996 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9997 pic16_addSign(result, MSB32, sign);
10000 else{ /* 1 <= shCount <= 7 */
10002 shiftRLong(left, LSB, result, sign);
10004 shiftRLong(result, LSB, result, sign);
10007 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10008 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10009 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10014 /*-----------------------------------------------------------------*/
10015 /* genRightShiftLiteral - right shifting by known count */
10016 /*-----------------------------------------------------------------*/
10017 static void genRightShiftLiteral (operand *left,
10023 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10024 int lsize,res_size;
10026 pic16_freeAsmop(right,NULL,ic,TRUE);
10028 pic16_aopOp(left,ic,FALSE);
10029 pic16_aopOp(result,ic,TRUE);
10031 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10034 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10038 lsize = pic16_getDataSize(left);
10039 res_size = pic16_getDataSize(result);
10040 /* test the LEFT size !!! */
10042 /* I suppose that the left size >= result size */
10044 assert (res_size <= lsize);
10045 while (res_size--) {
10046 pic16_mov2f (AOP(result), AOP(left), res_size);
10050 else if(shCount >= (lsize * 8)){
10052 if(res_size == 1) {
10053 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10055 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10056 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10062 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10070 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10075 switch (res_size) {
10077 genrshOne (result,left,shCount,sign);
10081 genrshTwo (result,left,shCount,sign);
10085 genrshFour (result,left,shCount,sign);
10093 pic16_freeAsmop(left,NULL,ic,TRUE);
10094 pic16_freeAsmop(result,NULL,ic,TRUE);
10097 #if !(USE_GENERIC_SIGNED_SHIFT)
10098 /*-----------------------------------------------------------------*/
10099 /* genSignedRightShift - right shift of signed number */
10100 /*-----------------------------------------------------------------*/
10101 static void genSignedRightShift (iCode *ic)
10103 operand *right, *left, *result;
10106 symbol *tlbl, *tlbl1 ;
10109 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10111 /* we do it the hard way put the shift count in b
10112 and loop thru preserving the sign */
10113 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10115 right = IC_RIGHT(ic);
10116 left = IC_LEFT(ic);
10117 result = IC_RESULT(ic);
10119 pic16_aopOp(right,ic,FALSE);
10120 pic16_aopOp(left,ic,FALSE);
10121 pic16_aopOp(result,ic,FALSE);
10124 if ( AOP_TYPE(right) == AOP_LIT) {
10125 genRightShiftLiteral (left,right,result,ic,1);
10128 /* shift count is unknown then we have to form
10129 a loop get the loop count in B : Note: we take
10130 only the lower order byte since shifting
10131 more that 32 bits make no sense anyway, ( the
10132 largest size of an object can be only 32 bits ) */
10134 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10135 //pic16_emitcode("inc","b");
10136 //pic16_freeAsmop (right,NULL,ic,TRUE);
10137 //pic16_aopOp(left,ic,FALSE);
10138 //pic16_aopOp(result,ic,FALSE);
10140 /* now move the left to the result if they are not the
10142 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10143 AOP_SIZE(result) > 1) {
10145 size = AOP_SIZE(result);
10149 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10150 if (*l == '@' && IS_AOP_PREG(result)) {
10152 pic16_emitcode("mov","a,%s",l);
10153 pic16_aopPut(AOP(result),"a",offset);
10155 pic16_aopPut(AOP(result),l,offset);
10157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10158 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10164 /* mov the highest order bit to OVR */
10165 tlbl = newiTempLabel(NULL);
10166 tlbl1= newiTempLabel(NULL);
10168 size = AOP_SIZE(result);
10171 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10173 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10175 /* offset should be 0, 1 or 3 */
10176 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10178 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10180 pic16_emitpcode(POC_MOVWF, pctemp);
10183 pic16_emitpLabel(tlbl->key);
10185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10186 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10189 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10192 pic16_emitpcode(POC_DECFSZ, pctemp);
10193 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10194 pic16_emitpLabel(tlbl1->key);
10196 pic16_popReleaseTempReg(pctemp,1);
10198 size = AOP_SIZE(result);
10200 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10201 pic16_emitcode("rlc","a");
10202 pic16_emitcode("mov","ov,c");
10203 /* if it is only one byte then */
10205 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10207 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10208 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10209 pic16_emitcode("mov","c,ov");
10210 pic16_emitcode("rrc","a");
10211 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10212 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10213 pic16_aopPut(AOP(result),"a",0);
10217 reAdjustPreg(AOP(result));
10218 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10219 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10220 pic16_emitcode("mov","c,ov");
10222 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10224 pic16_emitcode("rrc","a");
10225 pic16_aopPut(AOP(result),"a",offset--);
10227 reAdjustPreg(AOP(result));
10228 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10229 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10234 pic16_freeAsmop(left,NULL,ic,TRUE);
10235 pic16_freeAsmop(result,NULL,ic,TRUE);
10236 pic16_freeAsmop(right,NULL,ic,TRUE);
10240 #if !(USE_GENERIC_SIGNED_SHIFT)
10241 #warning This implementation of genRightShift() is incomplete!
10242 /*-----------------------------------------------------------------*/
10243 /* genRightShift - generate code for right shifting */
10244 /*-----------------------------------------------------------------*/
10245 static void genRightShift (iCode *ic)
10247 operand *right, *left, *result;
10251 symbol *tlbl, *tlbl1 ;
10253 /* if signed then we do it the hard way preserve the
10254 sign bit moving it inwards */
10255 letype = getSpec(operandType(IC_LEFT(ic)));
10256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10258 if (!SPEC_USIGN(letype)) {
10259 genSignedRightShift (ic);
10263 /* signed & unsigned types are treated the same : i.e. the
10264 signed is NOT propagated inwards : quoting from the
10265 ANSI - standard : "for E1 >> E2, is equivalent to division
10266 by 2**E2 if unsigned or if it has a non-negative value,
10267 otherwise the result is implementation defined ", MY definition
10268 is that the sign does not get propagated */
10270 right = IC_RIGHT(ic);
10271 left = IC_LEFT(ic);
10272 result = IC_RESULT(ic);
10274 pic16_aopOp(right,ic,FALSE);
10276 /* if the shift count is known then do it
10277 as efficiently as possible */
10278 if (AOP_TYPE(right) == AOP_LIT) {
10279 genRightShiftLiteral (left,right,result,ic, 0);
10283 /* shift count is unknown then we have to form
10284 a loop get the loop count in B : Note: we take
10285 only the lower order byte since shifting
10286 more that 32 bits make no sense anyway, ( the
10287 largest size of an object can be only 32 bits ) */
10289 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10290 pic16_emitcode("inc","b");
10291 pic16_aopOp(left,ic,FALSE);
10292 pic16_aopOp(result,ic,FALSE);
10294 /* now move the left to the result if they are not the
10296 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10297 AOP_SIZE(result) > 1) {
10299 size = AOP_SIZE(result);
10302 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10303 if (*l == '@' && IS_AOP_PREG(result)) {
10305 pic16_emitcode("mov","a,%s",l);
10306 pic16_aopPut(AOP(result),"a",offset);
10308 pic16_aopPut(AOP(result),l,offset);
10313 tlbl = newiTempLabel(NULL);
10314 tlbl1= newiTempLabel(NULL);
10315 size = AOP_SIZE(result);
10318 /* if it is only one byte then */
10321 tlbl = newiTempLabel(NULL);
10322 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10323 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10327 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10328 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10329 pic16_emitpLabel(tlbl->key);
10330 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10331 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10333 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10338 reAdjustPreg(AOP(result));
10339 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10340 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10343 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10345 pic16_emitcode("rrc","a");
10346 pic16_aopPut(AOP(result),"a",offset--);
10348 reAdjustPreg(AOP(result));
10350 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10351 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10354 pic16_freeAsmop(left,NULL,ic,TRUE);
10355 pic16_freeAsmop (right,NULL,ic,TRUE);
10356 pic16_freeAsmop(result,NULL,ic,TRUE);
10360 #if (USE_GENERIC_SIGNED_SHIFT)
10361 /*-----------------------------------------------------------------*/
10362 /* genGenericShift - generates code for left or right shifting */
10363 /*-----------------------------------------------------------------*/
10364 static void genGenericShift (iCode *ic, int isShiftLeft) {
10365 operand *left,*right, *result;
10367 int sign, signedCount;
10368 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10369 PIC_OPCODE pos_shift, neg_shift;
10373 right = IC_RIGHT(ic);
10374 left = IC_LEFT(ic);
10375 result = IC_RESULT(ic);
10377 pic16_aopOp(right,ic,FALSE);
10378 pic16_aopOp(left,ic,FALSE);
10379 pic16_aopOp(result,ic,TRUE);
10381 sign = !SPEC_USIGN(operandType (left));
10382 signedCount = !SPEC_USIGN(operandType (right));
10384 /* if the shift count is known then do it
10385 as efficiently as possible */
10386 if (AOP_TYPE(right) == AOP_LIT) {
10387 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10388 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10389 // we should modify right->aopu.aop_lit here!
10390 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10391 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10393 pic16_genLeftShiftLiteral (left,right,result,ic);
10395 genRightShiftLiteral (left,right,result,ic, sign);
10398 } // if (right is literal)
10400 /* shift count is unknown then we have to form a loop.
10401 * Note: we take only the lower order byte since shifting
10402 * more than 32 bits make no sense anyway, ( the
10403 * largest size of an object can be only 32 bits )
10404 * Note: we perform arithmetic shifts if the left operand is
10405 * signed and we do an (effective) right shift, i. e. we
10406 * shift in the sign bit from the left. */
10408 label_complete = newiTempLabel ( NULL );
10409 label_loop_pos = newiTempLabel ( NULL );
10410 label_loop_neg = NULL;
10411 label_negative = NULL;
10412 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10413 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10416 // additional labels needed
10417 label_loop_neg = newiTempLabel ( NULL );
10418 label_negative = newiTempLabel ( NULL );
10421 // copy source to result -- this will effectively truncate the left operand to the size of result!
10422 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10423 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10424 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10425 pic16_mov2f (AOP(result),AOP(left), offset);
10428 // if result is longer than left, fill with zeros (or sign)
10429 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10430 if (sign && AOP_SIZE(left) > 0) {
10431 // shift signed operand -- fill with sign
10432 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10433 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10434 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10435 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10436 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10439 // shift unsigned operand -- fill result with zeros
10440 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10441 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10444 } // if (size mismatch)
10446 pic16_mov2w (AOP(right), 0);
10447 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10448 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10451 // perform a shift by one (shift count is positive)
10452 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10453 // 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])
10454 pic16_emitpLabel (label_loop_pos->key);
10456 if (sign && (pos_shift == POC_RRCF)) {
10457 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10460 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10461 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10462 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10464 // perform a shift by one (shift count is positive)
10465 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10466 // 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])
10467 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10468 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10470 pic16_emitpLabel (label_loop_pos->key);
10471 if (sign && (pos_shift == POC_RRCF)) {
10472 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10475 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10476 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10477 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10478 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10482 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10484 pic16_emitpLabel (label_negative->key);
10485 // perform a shift by -1 (shift count is negative)
10486 // 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)
10488 pic16_emitpLabel (label_loop_neg->key);
10489 if (sign && (neg_shift == POC_RRCF)) {
10490 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10493 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10494 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10497 } // if (signedCount)
10499 pic16_emitpLabel (label_complete->key);
10502 pic16_freeAsmop (right,NULL,ic,TRUE);
10503 pic16_freeAsmop(left,NULL,ic,TRUE);
10504 pic16_freeAsmop(result,NULL,ic,TRUE);
10507 static void genLeftShift (iCode *ic) {
10508 genGenericShift (ic, 1);
10511 static void genRightShift (iCode *ic) {
10512 genGenericShift (ic, 0);
10517 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10518 void pic16_loadFSR0(operand *op, int lit)
10520 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10521 if (AOP_TYPE(op) == AOP_LIT) {
10522 /* handle 12 bit integers correctly */
10523 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10524 if ((val & 0x0fff) != val) {
10525 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10526 val, (val & 0x0fff) );
10529 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10531 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10534 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10535 // set up FSR0 with address of result
10536 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10537 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10541 /*----------------------------------------------------------------*/
10542 /* pic16_derefPtr - move one byte from the location ptr points to */
10543 /* to WREG (doWrite == 0) or one byte from WREG */
10544 /* to the location ptr points to (doWrite != 0) */
10545 /*----------------------------------------------------------------*/
10546 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10548 if (!IS_PTR(operandType(ptr)))
10550 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10551 else pic16_mov2w (AOP(ptr), 0);
10555 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10556 /* We might determine pointer type right here: */
10557 p_type = DCL_TYPE(operandType(ptr));
10562 if (!fsr0_setup || !*fsr0_setup)
10564 pic16_loadFSR0( ptr, 0 );
10565 if (fsr0_setup) *fsr0_setup = 1;
10568 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10570 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10574 if (AOP(ptr)->aopu.aop_reg[2]) {
10575 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10576 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10577 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10578 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10579 pic16_mov2w(AOP(ptr), 2);
10580 pic16_callGenericPointerRW(doWrite, 1);
10582 // data pointer (just 2 byte given)
10583 if (!fsr0_setup || !*fsr0_setup)
10585 pic16_loadFSR0( ptr, 0 );
10586 if (fsr0_setup) *fsr0_setup = 1;
10589 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10591 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10596 assert (0 && "invalid pointer type specified");
10601 /*-----------------------------------------------------------------*/
10602 /* genUnpackBits - generates code for unpacking bits */
10603 /*-----------------------------------------------------------------*/
10604 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10607 sym_link *etype, *letype;
10608 int blen=0, bstr=0;
10613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10614 etype = getSpec(operandType(result));
10615 letype = getSpec(operandType(left));
10617 // if(IS_BITFIELD(etype)) {
10618 blen = SPEC_BLEN(etype);
10619 bstr = SPEC_BSTR(etype);
10622 lbstr = SPEC_BSTR( letype );
10624 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10625 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10628 if((blen == 1) && (bstr < 8)
10629 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10630 /* it is a single bit, so use the appropriate bit instructions */
10631 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10633 same = pic16_sameRegs(AOP(left),AOP(result));
10634 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10635 pic16_emitpcode(POC_CLRF, op);
10637 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10638 /* workaround to reduce the extra lfsr instruction */
10639 pic16_emitpcode(POC_BTFSC,
10640 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10642 assert (PIC_IS_DATA_PTR (operandType(left)));
10643 pic16_loadFSR0 (left, 0);
10644 pic16_emitpcode(POC_BTFSC,
10645 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10648 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10649 /* unsigned bitfields result in either 0 or 1 */
10650 pic16_emitpcode(POC_INCF, op);
10652 /* signed bitfields result in either 0 or -1 */
10653 pic16_emitpcode(POC_DECF, op);
10656 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10659 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10665 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10666 // access symbol directly
10667 pic16_mov2w (AOP(left), 0);
10669 pic16_derefPtr (left, ptype, 0, NULL);
10672 /* if we have bitdisplacement then it fits */
10673 /* into this byte completely or if length is */
10674 /* less than a byte */
10675 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10677 /* shift right acc */
10680 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10681 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10683 /* VR -- normally I would use the following, but since we use the hack,
10684 * to avoid the masking from AccRsh, why not mask it right now? */
10687 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10690 /* extend signed bitfields to 8 bits */
10691 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10693 assert (blen + bstr > 0);
10694 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10695 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10698 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10700 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10704 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10705 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10712 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10714 int size, offset = 0, leoffset=0 ;
10716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10717 pic16_aopOp(result, ic, TRUE);
10721 size = AOP_SIZE(result);
10722 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10726 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10727 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10728 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10733 if(AOP(left)->aopu.pcop->type == PO_DIR)
10734 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10736 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10739 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10741 // pic16_DumpOp("(result)",result);
10742 if(is_LitAOp(AOP(result))) {
10743 pic16_mov2w(AOP(left), offset); // patch 8
10744 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10746 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10747 pic16_popGet(AOP(left), offset), //patch 8
10748 pic16_popGet(AOP(result), offset)));
10756 pic16_freeAsmop(result,NULL,ic,TRUE);
10761 /*-----------------------------------------------------------------*/
10762 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10763 /*-----------------------------------------------------------------*/
10764 static void genNearPointerGet (operand *left,
10768 // asmop *aop = NULL;
10769 //regs *preg = NULL ;
10770 sym_link *rtype, *retype;
10771 sym_link *ltype, *letype;
10775 rtype = operandType(result);
10776 retype= getSpec(rtype);
10777 ltype = operandType(left);
10778 letype= getSpec(ltype);
10780 pic16_aopOp(left,ic,FALSE);
10782 // pic16_DumpOp("(left)",left);
10783 // pic16_DumpOp("(result)",result);
10785 /* if left is rematerialisable and
10786 * result is not bit variable type and
10787 * the left is pointer to data space i.e
10788 * lower 128 bytes of space */
10790 if (AOP_TYPE(left) == AOP_PCODE
10791 && !IS_BITFIELD(retype)
10792 && DCL_TYPE(ltype) == POINTER) {
10794 genDataPointerGet (left,result,ic);
10795 pic16_freeAsmop(left, NULL, ic, TRUE);
10799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10800 pic16_aopOp (result,ic,TRUE);
10802 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10805 if(IS_BITFIELD( retype )
10806 && (SPEC_BLEN(operandType(result))==1)
10810 int bitstrt, bytestrt;
10812 /* if this is bitfield of size 1, see if we are checking the value
10813 * of a single bit in an if-statement,
10814 * if yes, then don't generate usual code, but execute the
10815 * genIfx directly -- VR */
10819 /* CHECK: if next iCode is IFX
10820 * and current result operand is nextic's conditional operand
10821 * and current result operand live ranges ends at nextic's key number
10823 if((nextic->op == IFX)
10824 && (result == IC_COND(nextic))
10825 && (OP_LIVETO(result) == nextic->seq)
10826 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10828 /* everything is ok then */
10829 /* find a way to optimize the genIfx iCode */
10831 bytestrt = SPEC_BSTR(operandType(result))/8;
10832 bitstrt = SPEC_BSTR(operandType(result))%8;
10834 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10836 genIfxpCOpJump(nextic, jop);
10838 pic16_freeAsmop(left, NULL, ic, TRUE);
10839 pic16_freeAsmop(result, NULL, ic, TRUE);
10845 /* if bitfield then unpack the bits */
10846 if (IS_BITFIELD(letype))
10847 genUnpackBits (result, left, NULL, POINTER);
10849 /* we have can just get the values */
10850 int size = AOP_SIZE(result);
10853 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10855 pic16_loadFSR0( left, 0 );
10859 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10860 pic16_popGet(AOP(result), offset++)));
10862 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10863 pic16_popGet(AOP(result), offset++)));
10869 /* now some housekeeping stuff */
10871 /* we had to allocate for this iCode */
10872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10873 pic16_freeAsmop(NULL,aop,ic,TRUE);
10875 /* we did not allocate which means left
10876 * already in a pointer register, then
10877 * if size > 0 && this could be used again
10878 * we have to point it back to where it
10880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10881 if (AOP_SIZE(result) > 1
10882 && !OP_SYMBOL(left)->remat
10883 && ( OP_SYMBOL(left)->liveTo > ic->seq
10885 // int size = AOP_SIZE(result) - 1;
10887 // pic16_emitcode("dec","%s",rname);
10893 pic16_freeAsmop(left,NULL,ic,TRUE);
10894 pic16_freeAsmop(result,NULL,ic,TRUE);
10897 /*-----------------------------------------------------------------*/
10898 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10899 /*-----------------------------------------------------------------*/
10900 static void genPagedPointerGet (operand *left,
10905 regs *preg = NULL ;
10907 sym_link *rtype, *retype;
10909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10911 rtype = operandType(result);
10912 retype= getSpec(rtype);
10914 pic16_aopOp(left,ic,FALSE);
10916 /* if the value is already in a pointer register
10917 then don't need anything more */
10918 if (!AOP_INPREG(AOP(left))) {
10919 /* otherwise get a free pointer register */
10921 preg = getFreePtr(ic,&aop,FALSE);
10922 pic16_emitcode("mov","%s,%s",
10924 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10925 rname = preg->name ;
10927 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10929 pic16_freeAsmop(left,NULL,ic,TRUE);
10930 pic16_aopOp (result,ic,TRUE);
10932 /* if bitfield then unpack the bits */
10933 if (IS_BITFIELD(retype))
10934 genUnpackBits (result,left,rname,PPOINTER);
10936 /* we have can just get the values */
10937 int size = AOP_SIZE(result);
10942 pic16_emitcode("movx","a,@%s",rname);
10943 pic16_aopPut(AOP(result),"a",offset);
10948 pic16_emitcode("inc","%s",rname);
10952 /* now some housekeeping stuff */
10954 /* we had to allocate for this iCode */
10955 pic16_freeAsmop(NULL,aop,ic,TRUE);
10957 /* we did not allocate which means left
10958 already in a pointer register, then
10959 if size > 0 && this could be used again
10960 we have to point it back to where it
10962 if (AOP_SIZE(result) > 1 &&
10963 !OP_SYMBOL(left)->remat &&
10964 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10966 int size = AOP_SIZE(result) - 1;
10968 pic16_emitcode("dec","%s",rname);
10973 pic16_freeAsmop(result,NULL,ic,TRUE);
10979 /* This code is not adjusted to PIC16 and fails utterly.
10980 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10982 /*-----------------------------------------------------------------*/
10983 /* genFarPointerGet - gget value from far space */
10984 /*-----------------------------------------------------------------*/
10985 static void genFarPointerGet (operand *left,
10986 operand *result, iCode *ic)
10989 sym_link *retype = getSpec(operandType(result));
10991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10993 pic16_aopOp(left,ic,FALSE);
10995 /* if the operand is already in dptr
10996 then we do nothing else we move the value to dptr */
10997 if (AOP_TYPE(left) != AOP_STR) {
10998 /* if this is remateriazable */
10999 if (AOP_TYPE(left) == AOP_IMMD)
11000 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11001 else { /* we need to get it byte by byte */
11002 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11003 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11004 if (options.model == MODEL_FLAT24)
11006 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11010 /* so dptr know contains the address */
11011 pic16_freeAsmop(left,NULL,ic,TRUE);
11012 pic16_aopOp(result,ic,TRUE);
11014 /* if bit then unpack */
11015 if (IS_BITFIELD(retype))
11016 genUnpackBits(result,left,"dptr",FPOINTER);
11018 size = AOP_SIZE(result);
11022 pic16_emitcode("movx","a,@dptr");
11023 pic16_aopPut(AOP(result),"a",offset++);
11025 pic16_emitcode("inc","dptr");
11029 pic16_freeAsmop(result,NULL,ic,TRUE);
11034 /*-----------------------------------------------------------------*/
11035 /* genCodePointerGet - get value from code space */
11036 /*-----------------------------------------------------------------*/
11037 static void genCodePointerGet (operand *left,
11038 operand *result, iCode *ic)
11041 sym_link *retype = getSpec(operandType(result));
11043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11045 pic16_aopOp(left,ic,FALSE);
11047 /* if the operand is already in dptr
11048 then we do nothing else we move the value to dptr */
11049 if (AOP_TYPE(left) != AOP_STR) {
11050 /* if this is remateriazable */
11051 if (AOP_TYPE(left) == AOP_IMMD)
11052 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11053 else { /* we need to get it byte by byte */
11054 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11055 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11056 if (options.model == MODEL_FLAT24)
11058 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11062 /* so dptr know contains the address */
11063 pic16_freeAsmop(left,NULL,ic,TRUE);
11064 pic16_aopOp(result,ic,FALSE);
11066 /* if bit then unpack */
11067 if (IS_BITFIELD(retype))
11068 genUnpackBits(result,left,"dptr",CPOINTER);
11070 size = AOP_SIZE(result);
11074 pic16_emitcode("clr","a");
11075 pic16_emitcode("movc","a,@a+dptr");
11076 pic16_aopPut(AOP(result),"a",offset++);
11078 pic16_emitcode("inc","dptr");
11082 pic16_freeAsmop(result,NULL,ic,TRUE);
11087 /*-----------------------------------------------------------------*/
11088 /* genGenPointerGet - gget value from generic pointer space */
11089 /*-----------------------------------------------------------------*/
11090 static void genGenPointerGet (operand *left,
11091 operand *result, iCode *ic)
11093 int size, offset, lit;
11094 sym_link *retype = getSpec(operandType(result));
11096 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11097 pic16_aopOp(left,ic,FALSE);
11098 pic16_aopOp(result,ic,FALSE);
11099 size = AOP_SIZE(result);
11101 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11103 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11105 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11106 // load FSR0 from immediate
11107 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11109 // pic16_loadFSR0( left );
11114 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11116 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11123 else { /* we need to get it byte by byte */
11124 // set up FSR0 with address from left
11125 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11132 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11134 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11141 /* if bit then unpack */
11142 if (IS_BITFIELD(retype))
11143 genUnpackBits(result,left,"BAD",GPOINTER);
11146 pic16_freeAsmop(left,NULL,ic,TRUE);
11147 pic16_freeAsmop(result,NULL,ic,TRUE);
11153 /*-----------------------------------------------------------------*/
11154 /* genGenPointerGet - gget value from generic pointer space */
11155 /*-----------------------------------------------------------------*/
11156 static void genGenPointerGet (operand *left,
11157 operand *result, iCode *ic)
11159 int size, offset, lit;
11160 sym_link *letype = getSpec(operandType(left));
11162 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11163 pic16_aopOp(left,ic,FALSE);
11164 pic16_aopOp(result,ic,TRUE);
11165 size = AOP_SIZE(result);
11167 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11169 /* if bit then unpack */
11170 if (IS_BITFIELD(letype)) {
11171 genUnpackBits(result,left,"BAD",GPOINTER);
11175 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11177 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11178 // load FSR0 from immediate
11179 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11181 werror(W_POSSBUG2, __FILE__, __LINE__);
11186 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11188 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11195 } else { /* we need to get it byte by byte */
11197 /* set up WREG:PRODL:FSR0L with address from left */
11198 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11199 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11200 pic16_mov2w(AOP(left), 2);
11201 pic16_callGenericPointerRW(0, size);
11203 assignResultValue(result, 1);
11209 pic16_freeAsmop(left,NULL,ic,TRUE);
11210 pic16_freeAsmop(result,NULL,ic,TRUE);
11213 /*-----------------------------------------------------------------*/
11214 /* genConstPointerGet - get value from const generic pointer space */
11215 /*-----------------------------------------------------------------*/
11216 static void genConstPointerGet (operand *left,
11217 operand *result, iCode *ic)
11219 //sym_link *retype = getSpec(operandType(result));
11220 // symbol *albl = newiTempLabel(NULL); // patch 15
11221 // symbol *blbl = newiTempLabel(NULL); //
11222 // PIC_OPCODE poc; // patch 15
11226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11227 pic16_aopOp(left,ic,FALSE);
11228 pic16_aopOp(result,ic,TRUE);
11229 size = AOP_SIZE(result);
11231 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11233 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11235 // set up table pointer
11236 if( (AOP_TYPE(left) == AOP_PCODE)
11237 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11238 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11240 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11241 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11242 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11243 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11244 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11245 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11247 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11248 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11249 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11253 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11258 pic16_freeAsmop(left,NULL,ic,TRUE);
11259 pic16_freeAsmop(result,NULL,ic,TRUE);
11263 /*-----------------------------------------------------------------*/
11264 /* genPointerGet - generate code for pointer get */
11265 /*-----------------------------------------------------------------*/
11266 static void genPointerGet (iCode *ic)
11268 operand *left, *result ;
11269 sym_link *type, *etype;
11274 left = IC_LEFT(ic);
11275 result = IC_RESULT(ic) ;
11277 /* depending on the type of pointer we need to
11278 move it to the correct pointer register */
11279 type = operandType(left);
11280 etype = getSpec(type);
11283 if (IS_PTR_CONST(type))
11285 if (IS_CODEPTR(type))
11287 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11289 /* if left is of type of pointer then it is simple */
11290 if (IS_PTR(type) && !IS_FUNC(type->next))
11291 p_type = DCL_TYPE(type);
11293 /* we have to go by the storage class */
11294 p_type = PTR_TYPE(SPEC_OCLS(etype));
11296 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11298 if (SPEC_OCLS(etype)->codesp ) {
11299 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11300 //p_type = CPOINTER ;
11302 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11303 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11304 /*p_type = FPOINTER ;*/
11306 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11307 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11308 /* p_type = PPOINTER; */
11310 if (SPEC_OCLS(etype) == idata ) {
11311 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11312 /* p_type = IPOINTER; */
11314 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11315 /* p_type = POINTER ; */
11319 /* now that we have the pointer type we assign
11320 the pointer values */
11325 genNearPointerGet (left,result,ic);
11329 genPagedPointerGet(left,result,ic);
11333 /* PICs do not support FAR pointers... */
11334 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11336 genFarPointerGet (left,result,ic);
11341 genConstPointerGet (left,result,ic);
11342 //pic16_emitcodePointerGet (left,result,ic);
11347 if (IS_PTR_CONST(type))
11348 genConstPointerGet (left,result,ic);
11351 genGenPointerGet (left,result,ic);
11355 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11356 "genPointerGet: illegal pointer type");
11361 /*-----------------------------------------------------------------*/
11362 /* genPackBits - generates code for packed bit storage */
11363 /*-----------------------------------------------------------------*/
11364 static void genPackBits (sym_link *etype , operand *result,
11366 char *rname, int p_type)
11372 int shifted_and_masked = 0;
11373 unsigned long lit = (unsigned long)-1;
11376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11377 blen = SPEC_BLEN(etype);
11378 bstr = SPEC_BSTR(etype);
11380 retype = getSpec(operandType(right));
11382 if(AOP_TYPE(right) == AOP_LIT) {
11383 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11385 if((blen == 1) && (bstr < 8)) {
11386 /* it is a single bit, so use the appropriate bit instructions */
11388 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11390 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11391 /* workaround to reduce the extra lfsr instruction */
11393 pic16_emitpcode(POC_BSF,
11394 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11396 pic16_emitpcode(POC_BCF,
11397 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11400 if (PIC_IS_DATA_PTR(operandType(result))) {
11401 pic16_loadFSR0(result, 0);
11402 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11403 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11405 /* get old value */
11406 pic16_derefPtr (result, p_type, 0, NULL);
11407 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11408 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11409 /* write back new value */
11410 pic16_derefPtr (result, p_type, 1, NULL);
11416 /* IORLW below is more efficient */
11417 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11418 lit = (lit & ((1UL << blen) - 1)) << bstr;
11419 shifted_and_masked = 1;
11422 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11423 && IS_BITFIELD(retype)
11424 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11428 rblen = SPEC_BLEN( retype );
11429 rbstr = SPEC_BSTR( retype );
11431 if(IS_BITFIELD(etype)) {
11432 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11433 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11435 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11438 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11440 if(IS_BITFIELD(etype)) {
11441 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11443 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11446 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11450 /* move right to W */
11451 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11454 /* if the bit length is less than or */
11455 /* it exactly fits a byte then */
11456 if((shCnt=SPEC_BSTR(etype))
11457 || SPEC_BLEN(etype) <= 8 ) {
11458 int fsr0_setup = 0;
11460 if (blen != 8 || bstr != 0) {
11461 // we need to combine the value with the old value
11462 if(!shifted_and_masked)
11464 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11466 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11467 SPEC_BSTR(etype), SPEC_BLEN(etype));
11469 /* shift left acc, do NOT mask the result again */
11472 /* using PRODH as a temporary register here */
11473 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11476 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11477 || IS_DIRECT(result)) {
11478 /* access symbol directly */
11479 pic16_mov2w (AOP(result), 0);
11481 /* get old value */
11482 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11485 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11486 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11487 (unsigned char)(0xff >> (8-bstr))) ));
11488 if (!shifted_and_masked) {
11489 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11491 /* We have the shifted and masked (literal) right value in `lit' */
11493 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11495 } // if (blen != 8 || bstr != 0)
11497 /* write new value back */
11498 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11499 || IS_DIRECT(result)) {
11500 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11502 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11511 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11512 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11517 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11518 rLen = SPEC_BLEN(etype)-8;
11520 /* now generate for lengths greater than one byte */
11524 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11536 pic16_emitcode("movx","@dptr,a");
11541 DEBUGpic16_emitcode(";lcall","__gptrput");
11549 pic16_mov2w(AOP(right), offset++);
11552 /* last last was not complete */
11554 /* save the byte & read byte */
11557 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11558 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11563 pic16_emitcode ("mov","b,a");
11564 pic16_emitcode("movx","a,@dptr");
11568 pic16_emitcode ("push","b");
11569 pic16_emitcode ("push","acc");
11570 pic16_emitcode ("lcall","__gptrget");
11571 pic16_emitcode ("pop","b");
11577 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11578 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11579 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11580 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11581 // pic16_emitcode ("orl","a,b");
11584 // if (p_type == GPOINTER)
11585 // pic16_emitcode("pop","b");
11590 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11591 // pic16_emitcode("mov","@%s,a",rname);
11595 pic16_emitcode("movx","@dptr,a");
11599 DEBUGpic16_emitcode(";lcall","__gptrput");
11606 // pic16_freeAsmop(right, NULL, ic, TRUE);
11609 /*-----------------------------------------------------------------*/
11610 /* genDataPointerSet - remat pointer to data space */
11611 /*-----------------------------------------------------------------*/
11612 static void genDataPointerSet(operand *right,
11616 int size, offset = 0, resoffset=0 ;
11618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11619 pic16_aopOp(right,ic,FALSE);
11621 size = AOP_SIZE(right);
11623 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11626 if ( AOP_TYPE(result) == AOP_PCODE) {
11627 fprintf(stderr,"genDataPointerSet %s, %d\n",
11628 AOP(result)->aopu.pcop->name,
11629 (AOP(result)->aopu.pcop->type == PO_DIR)?
11630 PCOR(AOP(result)->aopu.pcop)->instance:
11631 PCOI(AOP(result)->aopu.pcop)->offset);
11635 if(AOP(result)->aopu.pcop->type == PO_DIR)
11636 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11639 if (AOP_TYPE(right) == AOP_LIT) {
11642 if(!IS_FLOAT(operandType( right )))
11643 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11646 unsigned long lit_int;
11650 /* take care if literal is a float */
11651 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11652 lit = info.lit_int;
11654 lit = lit >> (8*offset);
11655 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11657 pic16_mov2w(AOP(right), offset);
11658 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11664 pic16_freeAsmop(right,NULL,ic,TRUE);
11669 /*-----------------------------------------------------------------*/
11670 /* genNearPointerSet - pic16_emitcode for near pointer put */
11671 /*-----------------------------------------------------------------*/
11672 static void genNearPointerSet (operand *right,
11678 sym_link *ptype = operandType(result);
11679 sym_link *resetype;
11681 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11682 retype= getSpec(operandType(right));
11683 resetype = getSpec(operandType(result));
11685 pic16_aopOp(result,ic,FALSE);
11687 /* if the result is rematerializable &
11688 * in data space & not a bit variable */
11690 /* and result is not a bit variable */
11691 if (AOP_TYPE(result) == AOP_PCODE
11692 // && AOP_TYPE(result) == AOP_IMMD
11693 && DCL_TYPE(ptype) == POINTER
11694 && !IS_BITFIELD(retype)
11695 && !IS_BITFIELD(resetype)) {
11697 genDataPointerSet (right,result,ic);
11698 pic16_freeAsmop(result,NULL,ic,TRUE);
11702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11703 pic16_aopOp(right,ic,FALSE);
11704 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11706 /* if bitfield then unpack the bits */
11707 if (IS_BITFIELD(resetype)) {
11708 genPackBits (resetype, result, right, NULL, POINTER);
11710 /* we have can just get the values */
11711 int size = AOP_SIZE(right);
11714 pic16_loadFSR0(result, 0);
11716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11718 if (AOP_TYPE(right) == AOP_LIT) {
11719 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11721 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11723 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11725 } else { // no literal
11727 pic16_emitpcode(POC_MOVFF,
11728 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11729 pic16_popCopyReg(&pic16_pc_postinc0)));
11731 pic16_emitpcode(POC_MOVFF,
11732 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11733 pic16_popCopyReg(&pic16_pc_indf0)));
11741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11742 /* now some housekeeping stuff */
11744 /* we had to allocate for this iCode */
11745 pic16_freeAsmop(NULL,aop,ic,TRUE);
11747 /* we did not allocate which means left
11748 * already in a pointer register, then
11749 * if size > 0 && this could be used again
11750 * we have to point it back to where it
11752 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11753 if (AOP_SIZE(right) > 1
11754 && !OP_SYMBOL(result)->remat
11755 && ( OP_SYMBOL(result)->liveTo > ic->seq
11758 int size = AOP_SIZE(right) - 1;
11761 pic16_emitcode("decf","fsr0,f");
11762 //pic16_emitcode("dec","%s",rname);
11766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11769 pic16_freeAsmop(right,NULL,ic,TRUE);
11770 pic16_freeAsmop(result,NULL,ic,TRUE);
11773 /*-----------------------------------------------------------------*/
11774 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11775 /*-----------------------------------------------------------------*/
11776 static void genPagedPointerSet (operand *right,
11781 regs *preg = NULL ;
11785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11787 retype= getSpec(operandType(right));
11789 pic16_aopOp(result,ic,FALSE);
11791 /* if the value is already in a pointer register
11792 then don't need anything more */
11793 if (!AOP_INPREG(AOP(result))) {
11794 /* otherwise get a free pointer register */
11796 preg = getFreePtr(ic,&aop,FALSE);
11797 pic16_emitcode("mov","%s,%s",
11799 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11800 rname = preg->name ;
11802 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11804 pic16_freeAsmop(result,NULL,ic,TRUE);
11805 pic16_aopOp (right,ic,FALSE);
11807 /* if bitfield then unpack the bits */
11808 if (IS_BITFIELD(retype))
11809 genPackBits (retype,result,right,rname,PPOINTER);
11811 /* we have can just get the values */
11812 int size = AOP_SIZE(right);
11816 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11819 pic16_emitcode("movx","@%s,a",rname);
11822 pic16_emitcode("inc","%s",rname);
11828 /* now some housekeeping stuff */
11830 /* we had to allocate for this iCode */
11831 pic16_freeAsmop(NULL,aop,ic,TRUE);
11833 /* we did not allocate which means left
11834 already in a pointer register, then
11835 if size > 0 && this could be used again
11836 we have to point it back to where it
11838 if (AOP_SIZE(right) > 1 &&
11839 !OP_SYMBOL(result)->remat &&
11840 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11842 int size = AOP_SIZE(right) - 1;
11844 pic16_emitcode("dec","%s",rname);
11849 pic16_freeAsmop(right,NULL,ic,TRUE);
11855 /* This code is not adjusted to PIC16 and fails utterly...
11856 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11858 /*-----------------------------------------------------------------*/
11859 /* genFarPointerSet - set value from far space */
11860 /*-----------------------------------------------------------------*/
11861 static void genFarPointerSet (operand *right,
11862 operand *result, iCode *ic)
11865 sym_link *retype = getSpec(operandType(right));
11867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11868 pic16_aopOp(result,ic,FALSE);
11870 /* if the operand is already in dptr
11871 then we do nothing else we move the value to dptr */
11872 if (AOP_TYPE(result) != AOP_STR) {
11873 /* if this is remateriazable */
11874 if (AOP_TYPE(result) == AOP_IMMD)
11875 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11876 else { /* we need to get it byte by byte */
11877 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11878 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11879 if (options.model == MODEL_FLAT24)
11881 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11885 /* so dptr know contains the address */
11886 pic16_freeAsmop(result,NULL,ic,TRUE);
11887 pic16_aopOp(right,ic,FALSE);
11889 /* if bit then unpack */
11890 if (IS_BITFIELD(retype))
11891 genPackBits(retype,result,right,"dptr",FPOINTER);
11893 size = AOP_SIZE(right);
11897 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11899 pic16_emitcode("movx","@dptr,a");
11901 pic16_emitcode("inc","dptr");
11905 pic16_freeAsmop(right,NULL,ic,TRUE);
11909 /*-----------------------------------------------------------------*/
11910 /* genGenPointerSet - set value from generic pointer space */
11911 /*-----------------------------------------------------------------*/
11913 static void genGenPointerSet (operand *right,
11914 operand *result, iCode *ic)
11916 int i, size, offset, lit;
11917 sym_link *retype = getSpec(operandType(right));
11919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11921 pic16_aopOp(result,ic,FALSE);
11922 pic16_aopOp(right,ic,FALSE);
11923 size = AOP_SIZE(right);
11926 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11928 /* if the operand is already in dptr
11929 then we do nothing else we move the value to dptr */
11930 if (AOP_TYPE(result) != AOP_STR) {
11931 /* if this is remateriazable */
11932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11933 // WARNING: anythig until "else" is untested!
11934 if (AOP_TYPE(result) == AOP_IMMD) {
11935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11936 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11937 // load FSR0 from immediate
11938 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11942 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11944 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11950 else { /* we need to get it byte by byte */
11951 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11952 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11954 // set up FSR0 with address of result
11955 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11956 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11958 /* hack hack! see if this the FSR. If so don't load W */
11959 if(AOP_TYPE(right) != AOP_ACC) {
11961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11963 if(AOP_TYPE(right) == AOP_LIT)
11966 // note: pic16_popGet handles sign extension
11967 for(i=0;i<size;i++) {
11968 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11970 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11972 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11977 for(i=0;i<size;i++) {
11979 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11980 pic16_popCopyReg(&pic16_pc_postinc0)));
11982 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11983 pic16_popCopyReg(&pic16_pc_indf0)));
11989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11990 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11992 } // if (AOP_TYPE(result) != AOP_IMMD)
11994 } // if (AOP_TYPE(result) != AOP_STR)
11995 /* so dptr know contains the address */
11998 /* if bit then unpack */
11999 if (IS_BITFIELD(retype))
12000 genPackBits(retype,result,right,"dptr",GPOINTER);
12002 size = AOP_SIZE(right);
12005 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12007 // set up FSR0 with address of result
12008 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12009 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12012 if (AOP_TYPE(right) == AOP_LIT) {
12013 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12015 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12017 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12019 } else { // no literal
12021 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12031 pic16_freeAsmop(right,NULL,ic,TRUE);
12032 pic16_freeAsmop(result,NULL,ic,TRUE);
12036 static void genGenPointerSet (operand *right,
12037 operand *result, iCode *ic)
12040 sym_link *retype = getSpec(operandType(result));
12042 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12044 pic16_aopOp(result,ic,FALSE);
12045 pic16_aopOp(right,ic,FALSE);
12046 size = AOP_SIZE(right);
12048 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12051 /* if bit then unpack */
12052 if (IS_BITFIELD(retype)) {
12053 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12054 genPackBits(retype,result,right,"dptr",GPOINTER);
12058 size = AOP_SIZE(right);
12060 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12063 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12065 /* value of right+0 is placed on stack, which will be retrieved
12066 * by the support function thus restoring the stack. The important
12067 * thing is that there is no need to manually restore stack pointer
12069 pushaop(AOP(right), 0);
12070 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12071 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12072 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12073 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12075 /* load address to write to in WREG:FSR0H:FSR0L */
12076 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12077 pic16_popCopyReg(&pic16_pc_fsr0l)));
12078 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12079 pic16_popCopyReg(&pic16_pc_prodl)));
12080 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12082 pic16_callGenericPointerRW(1, size);
12085 pic16_freeAsmop(right,NULL,ic,TRUE);
12086 pic16_freeAsmop(result,NULL,ic,TRUE);
12089 /*-----------------------------------------------------------------*/
12090 /* genPointerSet - stores the value into a pointer location */
12091 /*-----------------------------------------------------------------*/
12092 static void genPointerSet (iCode *ic)
12094 operand *right, *result ;
12095 sym_link *type, *etype;
12100 right = IC_RIGHT(ic);
12101 result = IC_RESULT(ic) ;
12103 /* depending on the type of pointer we need to
12104 move it to the correct pointer register */
12105 type = operandType(result);
12106 etype = getSpec(type);
12108 /* if left is of type of pointer then it is simple */
12109 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12110 p_type = DCL_TYPE(type);
12113 /* we have to go by the storage class */
12114 p_type = PTR_TYPE(SPEC_OCLS(etype));
12116 /* if (SPEC_OCLS(etype)->codesp ) { */
12117 /* p_type = CPOINTER ; */
12120 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12121 /* p_type = FPOINTER ; */
12123 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12124 /* p_type = PPOINTER ; */
12126 /* if (SPEC_OCLS(etype) == idata ) */
12127 /* p_type = IPOINTER ; */
12129 /* p_type = POINTER ; */
12132 /* now that we have the pointer type we assign
12133 the pointer values */
12138 genNearPointerSet (right,result,ic);
12142 genPagedPointerSet (right,result,ic);
12146 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12148 genFarPointerSet (right,result,ic);
12153 genGenPointerSet (right,result,ic);
12157 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12158 "genPointerSet: illegal pointer type");
12162 /*-----------------------------------------------------------------*/
12163 /* genIfx - generate code for Ifx statement */
12164 /*-----------------------------------------------------------------*/
12165 static void genIfx (iCode *ic, iCode *popIc)
12167 operand *cond = IC_COND(ic);
12172 pic16_aopOp(cond,ic,FALSE);
12174 /* get the value into acc */
12175 if (AOP_TYPE(cond) != AOP_CRY)
12176 pic16_toBoolean(cond);
12179 /* the result is now in the accumulator */
12180 pic16_freeAsmop(cond,NULL,ic,TRUE);
12182 /* if there was something to be popped then do it */
12186 /* if the condition is a bit variable */
12187 if (isbit && IS_ITEMP(cond) &&
12189 genIfxJump(ic,"c");
12190 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12192 if (isbit && !IS_ITEMP(cond))
12193 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12195 genIfxJump(ic,"a");
12200 /*-----------------------------------------------------------------*/
12201 /* genAddrOf - generates code for address of */
12202 /*-----------------------------------------------------------------*/
12203 static void genAddrOf (iCode *ic)
12205 operand *result, *left;
12207 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12208 pCodeOp *pcop0, *pcop1, *pcop2;
12212 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12214 sym = OP_SYMBOL( IC_LEFT(ic) );
12217 /* get address of symbol on stack */
12218 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12220 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12221 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12224 // operands on stack are accessible via "FSR2 + index" with index
12225 // starting at 2 for arguments and growing from 0 downwards for
12226 // local variables (index == 0 is not assigned so we add one here)
12228 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12231 assert (soffs < 0);
12235 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12236 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12237 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12238 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12239 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12240 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12241 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12247 // if(pic16_debug_verbose) {
12248 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12249 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12252 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12253 size = AOP_SIZE(IC_RESULT(ic));
12255 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12256 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12257 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12260 pic16_emitpcode(POC_MOVLW, pcop0);
12261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12262 pic16_emitpcode(POC_MOVLW, pcop1);
12263 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12264 pic16_emitpcode(POC_MOVLW, pcop2);
12265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12268 pic16_emitpcode(POC_MOVLW, pcop0);
12269 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12270 pic16_emitpcode(POC_MOVLW, pcop1);
12271 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12273 pic16_emitpcode(POC_MOVLW, pcop0);
12274 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12277 pic16_freeAsmop(left, NULL, ic, FALSE);
12279 pic16_freeAsmop(result,NULL,ic,TRUE);
12284 /*-----------------------------------------------------------------*/
12285 /* genFarFarAssign - assignment when both are in far space */
12286 /*-----------------------------------------------------------------*/
12287 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12289 int size = AOP_SIZE(right);
12292 /* first push the right side on to the stack */
12294 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12296 pic16_emitcode ("push","acc");
12299 pic16_freeAsmop(right,NULL,ic,FALSE);
12300 /* now assign DPTR to result */
12301 pic16_aopOp(result,ic,FALSE);
12302 size = AOP_SIZE(result);
12304 pic16_emitcode ("pop","acc");
12305 pic16_aopPut(AOP(result),"a",--offset);
12307 pic16_freeAsmop(result,NULL,ic,FALSE);
12312 /*-----------------------------------------------------------------*/
12313 /* genAssign - generate code for assignment */
12314 /*-----------------------------------------------------------------*/
12315 static void genAssign (iCode *ic)
12317 operand *result, *right;
12318 sym_link *restype, *rtype;
12319 int size, offset,know_W;
12320 unsigned long lit = 0L;
12322 result = IC_RESULT(ic);
12323 right = IC_RIGHT(ic) ;
12327 /* if they are the same */
12328 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12331 /* reversed order operands are aopOp'ed so that result operand
12332 * is effective in case right is a stack symbol. This maneauver
12333 * allows to use the _G.resDirect flag later */
12334 pic16_aopOp(result,ic,TRUE);
12335 pic16_aopOp(right,ic,FALSE);
12337 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12339 /* if they are the same registers */
12340 if (pic16_sameRegs(AOP(right),AOP(result)))
12343 /* if the result is a bit */
12344 if (AOP_TYPE(result) == AOP_CRY) {
12345 /* if the right size is a literal then
12346 we know what the value is */
12347 if (AOP_TYPE(right) == AOP_LIT) {
12349 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12350 pic16_popGet(AOP(result),0));
12352 if (((int) operandLitValue(right)))
12353 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12354 AOP(result)->aopu.aop_dir,
12355 AOP(result)->aopu.aop_dir);
12357 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12358 AOP(result)->aopu.aop_dir,
12359 AOP(result)->aopu.aop_dir);
12364 /* the right is also a bit variable */
12365 if (AOP_TYPE(right) == AOP_CRY) {
12366 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12367 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12368 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12373 /* we need to or */
12374 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12375 pic16_toBoolean(right);
12377 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12378 //pic16_aopPut(AOP(result),"a",0);
12382 /* bit variables done */
12384 size = AOP_SIZE(result);
12387 /* bit variables done */
12389 size = AOP_SIZE(result);
12390 restype = operandType(result);
12391 rtype = operandType(right);
12394 if(AOP_TYPE(right) == AOP_LIT) {
12395 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12397 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12399 /* patch tag for literals that are cast to pointers */
12400 if (IS_CODEPTR(restype)) {
12401 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12402 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12404 if (IS_GENPTR(restype))
12406 if (IS_CODEPTR(rtype)) {
12407 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12408 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12409 } else if (PIC_IS_DATA_PTR(rtype)) {
12410 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12411 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12412 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12413 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12414 } else if (IS_PTR(rtype)) {
12415 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12416 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12422 unsigned long lit_int;
12427 if(IS_FIXED16X16(operandType(right))) {
12428 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12430 /* take care if literal is a float */
12431 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12432 lit = info.lit_int;
12437 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12438 // sizeof(unsigned long int), sizeof(float));
12441 if (AOP_TYPE(right) == AOP_REG) {
12442 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12444 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12449 /* when do we have to read the program memory?
12450 * - if right itself is a symbol in code space
12451 * (we don't care what it points to if it's a pointer)
12452 * - AND right is not a function (we would want its address)
12454 if(AOP_TYPE(right) != AOP_LIT
12455 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12456 && !IS_FUNC(OP_SYM_TYPE(right))
12457 && !IS_ITEMP(right)) {
12459 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12460 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12462 // set up table pointer
12463 if(is_LitOp(right)) {
12464 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12465 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12466 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12467 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12468 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12469 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12470 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12472 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12473 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12474 pic16_popCopyReg(&pic16_pc_tblptrl)));
12475 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12476 pic16_popCopyReg(&pic16_pc_tblptrh)));
12477 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12478 pic16_popCopyReg(&pic16_pc_tblptru)));
12481 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12482 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12484 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12485 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12486 pic16_popGet(AOP(result),offset)));
12490 /* FIXME: for pointers we need to extend differently (according
12491 * to pointer type DATA/CODE/EEPROM/... :*/
12492 size = getSize(OP_SYM_TYPE(right));
12493 if(AOP_SIZE(result) > size) {
12494 size = AOP_SIZE(result) - size;
12496 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12504 /* VR - What is this?! */
12505 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12506 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12508 if(aopIdx(AOP(result),0) == 4) {
12509 /* this is a workaround to save value of right into wreg too,
12510 * value of wreg is going to be used later */
12511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12512 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12513 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12517 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12523 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12524 if(AOP_TYPE(right) == AOP_LIT) {
12526 if(know_W != (lit&0xff))
12527 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12529 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12531 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12535 } else if (AOP_TYPE(right) == AOP_CRY) {
12536 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12538 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12539 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12540 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12542 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12543 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12544 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12548 if(!_G.resDirect) { /* use this aopForSym feature */
12549 if(AOP_TYPE(result) == AOP_ACC) {
12550 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12552 if(AOP_TYPE(right) == AOP_ACC) {
12553 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12555 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12564 pic16_freeAsmop (right,NULL,ic,FALSE);
12565 pic16_freeAsmop (result,NULL,ic,TRUE);
12568 /*-----------------------------------------------------------------*/
12569 /* genJumpTab - generates code for jump table */
12570 /*-----------------------------------------------------------------*/
12571 static void genJumpTab (iCode *ic)
12576 pCodeOp *jt_offs_hi;
12581 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12582 /* get the condition into accumulator */
12583 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12585 /* multiply by three */
12586 pic16_emitcode("add","a,acc");
12587 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12589 jtab = newiTempLabel(NULL);
12590 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12591 pic16_emitcode("jmp","@a+dptr");
12592 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12595 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12596 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12598 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12599 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12600 pic16_emitpLabel(jtab->key);
12604 jt_offs = pic16_popGetTempReg(0);
12605 jt_offs_hi = pic16_popGetTempReg(1);
12606 jt_label = pic16_popGetLabel (jtab->key);
12607 //fprintf (stderr, "Creating jump table...\n");
12609 // calculate offset into jump table (idx * sizeof (GOTO))
12610 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12611 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12612 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12613 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12614 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12615 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12616 pic16_emitpcode(POC_MOVWF , jt_offs);
12618 // prepare PCLATx (set to first entry in jump table)
12619 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12620 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12621 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12622 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12623 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12625 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12626 pic16_emitpcode(POC_ADDWF , jt_offs);
12627 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12628 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12630 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12632 // release temporaries and prepare jump into table (new PCL --> WREG)
12633 pic16_emitpcode(POC_MOVFW , jt_offs);
12634 pic16_popReleaseTempReg (jt_offs_hi, 1);
12635 pic16_popReleaseTempReg (jt_offs, 0);
12637 // jump into the table
12638 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12640 pic16_emitpLabelFORCE(jtab->key);
12643 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12644 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12646 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12647 /* now generate the jump labels */
12648 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12649 jtab = setNextItem(IC_JTLABELS(ic))) {
12650 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12651 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12654 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12658 /*-----------------------------------------------------------------*/
12659 /* genMixedOperation - gen code for operators between mixed types */
12660 /*-----------------------------------------------------------------*/
12662 TSD - Written for the PIC port - but this unfortunately is buggy.
12663 This routine is good in that it is able to efficiently promote
12664 types to different (larger) sizes. Unfortunately, the temporary
12665 variables that are optimized out by this routine are sometimes
12666 used in other places. So until I know how to really parse the
12667 iCode tree, I'm going to not be using this routine :(.
12669 static int genMixedOperation (iCode *ic)
12672 operand *result = IC_RESULT(ic);
12673 sym_link *ctype = operandType(IC_LEFT(ic));
12674 operand *right = IC_RIGHT(ic);
12680 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12682 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12688 nextright = IC_RIGHT(nextic);
12689 nextleft = IC_LEFT(nextic);
12690 nextresult = IC_RESULT(nextic);
12692 pic16_aopOp(right,ic,FALSE);
12693 pic16_aopOp(result,ic,FALSE);
12694 pic16_aopOp(nextright, nextic, FALSE);
12695 pic16_aopOp(nextleft, nextic, FALSE);
12696 pic16_aopOp(nextresult, nextic, FALSE);
12698 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12700 operand *t = right;
12704 pic16_emitcode(";remove right +","");
12706 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12708 operand *t = right;
12712 pic16_emitcode(";remove left +","");
12716 big = AOP_SIZE(nextleft);
12717 small = AOP_SIZE(nextright);
12719 switch(nextic->op) {
12722 pic16_emitcode(";optimize a +","");
12723 /* if unsigned or not an integral type */
12724 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12725 pic16_emitcode(";add a bit to something","");
12728 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12730 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12731 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12732 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12734 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12742 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12743 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12744 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12747 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12749 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12750 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12751 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12752 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12753 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12756 pic16_emitcode("rlf","known_zero,w");
12763 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12764 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12767 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12777 pic16_freeAsmop(right,NULL,ic,TRUE);
12778 pic16_freeAsmop(result,NULL,ic,TRUE);
12779 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12780 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12782 nextic->generated = 1;
12789 /*-----------------------------------------------------------------*/
12790 /* genCast - gen code for casting */
12791 /*-----------------------------------------------------------------*/
12792 static void genCast (iCode *ic)
12794 operand *result = IC_RESULT(ic);
12795 sym_link *ctype = operandType(IC_LEFT(ic));
12796 sym_link *rtype = operandType(IC_RIGHT(ic));
12797 sym_link *restype = operandType(IC_RESULT(ic));
12798 operand *right = IC_RIGHT(ic);
12804 /* if they are equivalent then do nothing */
12805 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12808 pic16_aopOp(result,ic,FALSE);
12809 pic16_aopOp(right,ic,FALSE) ;
12811 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12814 /* if the result is a bit */
12815 if (AOP_TYPE(result) == AOP_CRY) {
12817 /* if the right size is a literal then
12818 * we know what the value is */
12819 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12821 if (AOP_TYPE(right) == AOP_LIT) {
12822 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12823 pic16_popGet(AOP(result),0));
12825 if (((int) operandLitValue(right)))
12826 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12827 AOP(result)->aopu.aop_dir,
12828 AOP(result)->aopu.aop_dir);
12830 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12831 AOP(result)->aopu.aop_dir,
12832 AOP(result)->aopu.aop_dir);
12836 /* the right is also a bit variable */
12837 if (AOP_TYPE(right) == AOP_CRY) {
12839 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12841 pic16_emitcode("clrc","");
12842 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12843 AOP(right)->aopu.aop_dir,
12844 AOP(right)->aopu.aop_dir);
12845 pic16_aopPut(AOP(result),"c",0);
12849 /* we need to or */
12850 if (AOP_TYPE(right) == AOP_REG) {
12851 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12852 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12853 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12855 pic16_toBoolean(right);
12856 pic16_aopPut(AOP(result),"a",0);
12860 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12863 size = AOP_SIZE(result);
12865 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12867 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12868 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12869 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12872 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12877 if(IS_BITFIELD(getSpec(restype))
12878 && IS_BITFIELD(getSpec(rtype))) {
12879 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12882 /* port from pic14 to cope with generic pointers */
12883 if (PIC_IS_TAGGED(restype))
12885 operand *result = IC_RESULT(ic);
12886 //operand *left = IC_LEFT(ic);
12887 operand *right = IC_RIGHT(ic);
12890 /* copy common part */
12891 int max, size = AOP_SIZE(result);
12892 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12893 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12898 pic16_mov2w (AOP(right), size);
12899 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12902 /* upcast into generic pointer type? */
12903 if (IS_GENPTR(restype)
12904 && !PIC_IS_TAGGED(rtype)
12905 && (AOP_SIZE(result) > max))
12907 /* determine appropriate tag for right */
12908 if (PIC_IS_DATA_PTR(rtype))
12909 tag = GPTR_TAG_DATA;
12910 else if (IS_CODEPTR(rtype))
12911 tag = GPTR_TAG_CODE;
12912 else if (PIC_IS_DATA_PTR(ctype)) {
12913 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12914 tag = GPTR_TAG_DATA;
12915 } else if (IS_CODEPTR(ctype)) {
12916 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12917 tag = GPTR_TAG_CODE;
12918 } else if (IS_PTR(rtype)) {
12919 PERFORM_ONCE(weirdcast,
12920 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12922 tag = GPTR_TAG_DATA;
12924 PERFORM_ONCE(weirdcast,
12925 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12927 tag = GPTR_TAG_DATA;
12930 assert (AOP_SIZE(result) == 3);
12931 /* zero-extend address... */
12932 for (size = max; size < AOP_SIZE(result)-1; size++)
12933 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12934 /* ...and add tag */
12935 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12936 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12937 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12938 for (size = max; size < AOP_SIZE(result)-1; size++)
12939 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12940 /* add __code tag */
12941 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12942 } else if (AOP_SIZE(result) > max) {
12943 /* extend non-pointers */
12944 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12945 pic16_addSign(result, max, 0);
12950 /* if they are the same size : or less */
12951 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12953 /* if they are in the same place */
12954 if (pic16_sameRegs(AOP(right),AOP(result)))
12957 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12959 if (IS_PTR_CONST(rtype))
12961 if (IS_CODEPTR(rtype))
12963 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12966 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12968 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12970 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12973 if(AOP_TYPE(right) == AOP_IMMD) {
12974 pCodeOp *pcop0, *pcop1, *pcop2;
12975 symbol *sym = OP_SYMBOL( right );
12977 size = AOP_SIZE(result);
12979 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12981 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12983 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12986 pic16_emitpcode(POC_MOVLW, pcop0);
12987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12988 pic16_emitpcode(POC_MOVLW, pcop1);
12989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12990 pic16_emitpcode(POC_MOVLW, pcop2);
12991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12994 pic16_emitpcode(POC_MOVLW, pcop0);
12995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12996 pic16_emitpcode(POC_MOVLW, pcop1);
12997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12999 pic16_emitpcode(POC_MOVLW, pcop0);
13000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13004 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13005 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13007 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13009 if(AOP_SIZE(result) <2)
13010 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13012 /* if they in different places then copy */
13013 size = AOP_SIZE(result);
13016 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13024 /* if the result is of type pointer */
13025 if (IS_PTR(ctype)) {
13027 sym_link *type = operandType(right);
13028 sym_link *etype = getSpec(type);
13030 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13032 /* pointer to generic pointer */
13033 if (IS_GENPTR(ctype)) {
13037 p_type = DCL_TYPE(type);
13039 /* we have to go by the storage class */
13040 p_type = PTR_TYPE(SPEC_OCLS(etype));
13042 /* if (SPEC_OCLS(etype)->codesp ) */
13043 /* p_type = CPOINTER ; */
13045 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13046 /* p_type = FPOINTER ; */
13048 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13049 /* p_type = PPOINTER; */
13051 /* if (SPEC_OCLS(etype) == idata ) */
13052 /* p_type = IPOINTER ; */
13054 /* p_type = POINTER ; */
13057 /* the first two bytes are known */
13058 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13059 size = GPTRSIZE - 1;
13062 if(offset < AOP_SIZE(right)) {
13063 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13064 pic16_mov2f(AOP(result), AOP(right), offset);
13066 if ((AOP_TYPE(right) == AOP_PCODE) &&
13067 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13068 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13072 pic16_aopPut(AOP(result),
13073 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13078 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13081 /* the last byte depending on type */
13086 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13090 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13094 pic16_emitcode(";BUG!? ","%d",__LINE__);
13099 if (GPTRSIZE > AOP_SIZE(right)) {
13100 // assume __data pointer... THIS MIGHT BE WRONG!
13101 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13103 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13108 /* this should never happen */
13109 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13110 "got unknown pointer type");
13113 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13119 /* just copy the pointers */
13120 size = AOP_SIZE(result);
13123 pic16_aopPut(AOP(result),
13124 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13133 /* so we now know that the size of destination is greater
13134 than the size of the source.
13135 Now, if the next iCode is an operator then we might be
13136 able to optimize the operation without performing a cast.
13138 if(genMixedOperation(ic))
13141 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13143 /* we move to result for the size of source */
13144 size = AOP_SIZE(right);
13149 pic16_mov2f(AOP(result), AOP(right), offset);
13153 /* now depending on the sign of the destination */
13154 size = AOP_SIZE(result) - AOP_SIZE(right);
13155 /* if unsigned or not an integral type */
13156 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13158 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13160 /* we need to extend the sign :( */
13163 /* Save one instruction of casting char to int */
13164 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13165 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13166 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13168 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13171 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13173 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13175 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13178 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13183 pic16_freeAsmop(right,NULL,ic,TRUE);
13184 pic16_freeAsmop(result,NULL,ic,TRUE);
13188 /*-----------------------------------------------------------------*/
13189 /* genDjnz - generate decrement & jump if not zero instrucion */
13190 /*-----------------------------------------------------------------*/
13191 static int genDjnz (iCode *ic, iCode *ifx)
13193 symbol *lbl, *lbl1;
13194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13199 /* if the if condition has a false label
13200 then we cannot save */
13204 /* if the minus is not of the form
13206 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13207 !IS_OP_LITERAL(IC_RIGHT(ic)))
13210 if (operandLitValue(IC_RIGHT(ic)) != 1)
13213 /* if the size of this greater than one then no
13215 if (getSize(operandType(IC_RESULT(ic))) > 1)
13218 /* otherwise we can save BIG */
13219 lbl = newiTempLabel(NULL);
13220 lbl1= newiTempLabel(NULL);
13222 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13224 if (IS_AOP_PREG(IC_RESULT(ic))) {
13225 pic16_emitcode("dec","%s",
13226 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13227 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13228 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13232 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13233 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13235 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13236 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13240 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13241 ifx->generated = 1;
13245 /*-----------------------------------------------------------------*/
13246 /* genReceive - generate code for a receive iCode */
13247 /*-----------------------------------------------------------------*/
13248 static void genReceive (iCode *ic)
13254 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13255 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13257 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13259 if (isOperandInFarSpace(IC_RESULT(ic))
13260 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13261 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13263 int size = getSize(operandType(IC_RESULT(ic)));
13264 int offset = pic16_fReturnSizePic - size;
13268 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13269 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13273 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13275 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13276 size = AOP_SIZE(IC_RESULT(ic));
13279 pic16_emitcode ("pop","acc");
13280 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13283 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13285 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13288 /* set pseudo stack pointer to where it should be - dw*/
13289 GpsuedoStkPtr = ic->parmBytes;
13291 /* setting GpsuedoStkPtr has side effects here: */
13292 assignResultValue(IC_RESULT(ic), 0);
13295 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13298 /*-----------------------------------------------------------------*/
13299 /* genDummyRead - generate code for dummy read of volatiles */
13300 /*-----------------------------------------------------------------*/
13302 genDummyRead (iCode * ic)
13308 if (op && IS_SYMOP(op)) {
13309 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13310 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13313 pic16_aopOp (op, ic, FALSE);
13314 for (i=0; i < AOP_SIZE(op); i++) {
13315 // may need to protect this from the peepholer -- this is not nice but works...
13316 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13317 pic16_mov2w (AOP(op),i);
13318 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13320 pic16_freeAsmop (op, NULL, ic, TRUE);
13322 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13326 /*-----------------------------------------------------------------*/
13327 /* genpic16Code - generate code for pic16 based controllers */
13328 /*-----------------------------------------------------------------*/
13330 * At this point, ralloc.c has gone through the iCode and attempted
13331 * to optimize in a way suitable for a PIC. Now we've got to generate
13332 * PIC instructions that correspond to the iCode.
13334 * Once the instructions are generated, we'll pass through both the
13335 * peep hole optimizer and the pCode optimizer.
13336 *-----------------------------------------------------------------*/
13338 void genpic16Code (iCode *lic)
13343 lineHead = lineCurr = NULL;
13345 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13346 pic16_addpBlock(pb);
13349 /* if debug information required */
13350 if (options.debug && currFunc) {
13352 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13357 for (ic = lic ; ic ; ic = ic->next ) {
13359 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13360 if ( cln != ic->lineno ) {
13361 if ( options.debug ) {
13362 debugFile->writeCLine (ic);
13365 if(!options.noCcodeInAsm) {
13366 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13367 printCLine(ic->filename, ic->lineno)));
13373 if(options.iCodeInAsm) {
13376 /* insert here code to print iCode as comment */
13377 l = Safe_strdup(printILine(ic));
13378 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13381 /* if the result is marked as
13382 * spilt and rematerializable or code for
13383 * this has already been generated then
13385 if (resultRemat(ic) || ic->generated )
13388 /* depending on the operation */
13407 /* IPOP happens only when trying to restore a
13408 * spilt live range, if there is an ifx statement
13409 * following this pop then the if statement might
13410 * be using some of the registers being popped which
13411 * would destroy the contents of the register so
13412 * we need to check for this condition and handle it */
13414 && ic->next->op == IFX
13415 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13416 genIfx (ic->next,ic);
13434 genEndFunction (ic);
13450 pic16_genPlus (ic) ;
13454 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13455 pic16_genMinus (ic);
13471 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13475 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13481 /* note these two are xlated by algebraic equivalence
13482 * during parsing SDCC.y */
13483 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13484 "got '>=' or '<=' shouldn't have come here");
13488 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13500 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13504 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13508 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13532 genRightShift (ic);
13535 case GET_VALUE_AT_ADDRESS:
13540 if (POINTER_SET(ic))
13567 addSet(&_G.sendSet,ic);
13570 case DUMMY_READ_VOLATILE:
13580 /* now we are ready to call the
13581 peep hole optimizer */
13582 if (!options.nopeep)
13583 peepHole (&lineHead);
13585 /* now do the actual printing */
13586 printLine (lineHead, codeOutFile);
13589 DFPRINTF((stderr,"printing pBlock\n\n"));
13590 pic16_printpBlock(stdout,pb);