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 AT users.sourceforge.net> (2003-2006)
10 Bug Fixes - Raphael Neider <rneider AT 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 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
711 for(i=0;i<aop->size;i++) {
712 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
713 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
718 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
721 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
723 // we do not need to load the value if it is to be defined...
724 if (result) return aop;
727 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730 for(i=0;i<aop->size;i++) {
732 /* initialise for stack access via frame pointer */
733 // operands on stack are accessible via "{FRAME POINTER} + index" with index
734 // starting at 2 for arguments and growing from 0 downwards for
735 // local variables (index == 0 is not assigned so we add one here)
737 int soffs = sym->stack;
743 if(1 && ic->op == SEND) {
744 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
745 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
746 pic16_popCopyReg( pic16_frame_plusw ),
747 pic16_popCopyReg(pic16_stack_postdec )));
749 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
750 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
757 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
764 /* now assign the address of the variable to
765 the pointer register */
766 if (aop->type != AOP_STK) {
770 pic16_emitcode("push","acc");
772 pic16_emitcode("mov","a,_bp");
773 pic16_emitcode("add","a,#0x%02x",
775 ((char)(sym->stack - _G.nRegsSaved )) :
776 ((char)sym->stack)) & 0xff);
777 pic16_emitcode("mov","%s,a",
778 aop->aopu.aop_ptr->name);
781 pic16_emitcode("pop","acc");
783 pic16_emitcode("mov","%s,#%s",
784 aop->aopu.aop_ptr->name,
786 aop->paged = space->paged;
788 aop->aopu.aop_stk = sym->stack;
796 if (sym->onStack && options.stack10bit)
798 /* It's on the 10 bit stack, which is located in
802 //DEBUGpic16_emitcode(";","%d",__LINE__);
805 pic16_emitcode("push","acc");
807 pic16_emitcode("mov","a,_bp");
808 pic16_emitcode("add","a,#0x%02x",
810 ((char)(sym->stack - _G.nRegsSaved )) :
811 ((char)sym->stack)) & 0xff);
814 pic16_emitcode ("mov","dpx1,#0x40");
815 pic16_emitcode ("mov","dph1,#0x00");
816 pic16_emitcode ("mov","dpl1, a");
820 pic16_emitcode("pop","acc");
822 sym->aop = aop = newAsmop(AOP_DPTR2);
823 aop->size = getSize(sym->type);
829 /* special case for a function */
830 if (IS_FUNC(sym->type)) {
831 sym->aop = aop = newAsmop(AOP_PCODE);
832 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
833 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
834 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
835 PCOI(aop->aopu.pcop)->index = 0;
836 aop->size = FPTRSIZE;
837 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
844 //DEBUGpic16_emitcode(";","%d",__LINE__);
845 /* if in bit space */
846 if (IN_BITSPACE(space)) {
847 sym->aop = aop = newAsmop (AOP_CRY);
848 aop->aopu.aop_dir = sym->rname ;
849 aop->size = getSize(sym->type);
850 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853 /* if it is in direct space */
854 if (IN_DIRSPACE(space)) {
855 if(!strcmp(sym->rname, "_WREG")) {
856 sym->aop = aop = newAsmop (AOP_ACC);
857 aop->size = getSize(sym->type); /* should always be 1 */
858 assert(aop->size == 1);
859 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
862 sym->aop = aop = newAsmop (AOP_DIR);
863 aop->aopu.aop_dir = sym->rname ;
864 aop->size = getSize(sym->type);
865 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
866 pic16_allocDirReg( IC_LEFT(ic) );
871 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
872 sym->aop = aop = newAsmop (AOP_DIR);
873 aop->aopu.aop_dir = sym->rname ;
874 aop->size = getSize(sym->type);
875 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
876 pic16_allocDirReg( IC_LEFT(ic) );
881 /* only remaining is far space */
882 sym->aop = aop = newAsmop(AOP_PCODE);
884 /* change the next if to 1 to revert to good old immediate code */
885 if(IN_CODESPACE(space)) {
886 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
887 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
888 PCOI(aop->aopu.pcop)->index = 0;
890 /* try to allocate via direct register */
891 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
892 // aop->size = getSize( sym->type );
895 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
896 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
899 if(!pic16_allocDirReg (IC_LEFT(ic)))
903 if(IN_DIRSPACE( space ))
905 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
906 aop->size = FPTRSIZE;
907 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
908 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
909 else if(sym->onStack) {
912 if(SPEC_SCLS(sym->etype) == S_PDATA) {
913 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
914 aop->size = FPTRSIZE;
919 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
921 /* if it is in code space */
922 if (IN_CODESPACE(space))
928 /*-----------------------------------------------------------------*/
929 /* aopForRemat - rematerialzes an object */
930 /*-----------------------------------------------------------------*/
931 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
933 symbol *sym = OP_SYMBOL(op);
935 iCode *ic = NULL, *oldic;
936 asmop *aop = newAsmop(AOP_PCODE);
943 ic = sym->rematiCode;
945 if(IS_OP_POINTER(op)) {
946 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
949 // if(!result) /* fixme-vr */
953 // pic16_emitpcomment("ic: %s\n", printILine(ic));
956 val += (int) operandLitValue(IC_RIGHT(ic));
957 } else if (ic->op == '-') {
958 val -= (int) operandLitValue(IC_RIGHT(ic));
962 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
965 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
968 if(!op->isaddr)viaimmd++; else viaimmd=0;
970 /* set the following if to 1 to revert to good old immediate code */
971 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
974 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
976 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
979 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
981 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
984 PCOI(aop->aopu.pcop)->index = val;
986 aop->size = getSize( sym->type );
988 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
990 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
991 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
993 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
997 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
998 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1000 val, IS_PTR_CONST(operandType(op)));
1002 val, IS_CODEPTR(operandType(op)));
1005 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1007 pic16_allocDirReg (IC_LEFT(ic));
1009 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1016 static int aopIdx (asmop *aop, int offset)
1021 if(aop->type != AOP_REG)
1024 return aop->aopu.aop_reg[offset]->rIdx;
1029 /*-----------------------------------------------------------------*/
1030 /* regsInCommon - two operands have some registers in common */
1031 /*-----------------------------------------------------------------*/
1032 static bool regsInCommon (operand *op1, operand *op2)
1034 symbol *sym1, *sym2;
1037 /* if they have registers in common */
1038 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1041 sym1 = OP_SYMBOL(op1);
1042 sym2 = OP_SYMBOL(op2);
1044 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1047 for (i = 0 ; i < sym1->nRegs ; i++) {
1052 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1056 if (sym2->regs[j] == sym1->regs[i])
1064 /*-----------------------------------------------------------------*/
1065 /* operandsEqu - equivalent */
1066 /*-----------------------------------------------------------------*/
1067 static bool operandsEqu ( operand *op1, operand *op2)
1069 symbol *sym1, *sym2;
1071 /* if they not symbols */
1072 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1075 sym1 = OP_SYMBOL(op1);
1076 sym2 = OP_SYMBOL(op2);
1078 /* if both are itemps & one is spilt
1079 and the other is not then false */
1080 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1081 sym1->isspilt != sym2->isspilt )
1084 /* if they are the same */
1088 if (sym1->rname[0] && sym2->rname[0]
1089 && strcmp (sym1->rname, sym2->rname) == 0)
1093 /* if left is a tmp & right is not */
1094 if (IS_ITEMP(op1) &&
1097 (sym1->usl.spillLoc == sym2))
1100 if (IS_ITEMP(op2) &&
1104 (sym2->usl.spillLoc == sym1))
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_sameRegs - two asmops have the same registers */
1112 /*-----------------------------------------------------------------*/
1113 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1120 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1121 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1123 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1125 if (aop1->type != AOP_REG ||
1126 aop2->type != AOP_REG )
1129 /* This is a bit too restrictive if one is a subset of the other...
1130 if (aop1->size != aop2->size )
1134 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1135 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1137 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1138 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1145 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1147 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1148 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1150 if(aop1 == aop2)return TRUE;
1151 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1153 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1159 /*-----------------------------------------------------------------*/
1160 /* pic16_aopOp - allocates an asmop for an operand : */
1161 /*-----------------------------------------------------------------*/
1162 void pic16_aopOp (operand *op, iCode *ic, bool result)
1171 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1173 /* if this a literal */
1174 if (IS_OP_LITERAL(op)) {
1175 op->aop = aop = newAsmop(AOP_LIT);
1176 aop->aopu.aop_lit = op->operand.valOperand;
1177 aop->size = getSize(operandType(op));
1182 sym_link *type = operandType(op);
1184 if(IS_PTR_CONST(type))
1186 if(IS_CODEPTR(type))
1188 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1191 /* if already has a asmop then continue */
1195 /* if the underlying symbol has a aop */
1196 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1197 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1198 op->aop = OP_SYMBOL(op)->aop;
1202 /* if this is a true symbol */
1203 if (IS_TRUE_SYMOP(op)) {
1204 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1205 op->aop = aopForSym(ic, op, result);
1209 /* this is a temporary : this has
1215 e) can be a return use only */
1217 sym = OP_SYMBOL(op);
1219 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1220 /* if the type is a conditional */
1221 if (sym->regType == REG_CND) {
1222 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1227 /* if it is spilt then two situations
1229 b) has a spill location */
1230 if (sym->isspilt || sym->nRegs == 0) {
1232 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1233 DEBUGpic16_emitcode(";","%d",__LINE__);
1234 /* rematerialize it NOW */
1237 sym->aop = op->aop = aop = aopForRemat (op, result);
1238 // aop->size = getSize(sym->type);
1239 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1246 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1247 aop->size = getSize(sym->type);
1248 for ( i = 0 ; i < 1 ; i++ ) {
1249 aop->aopu.aop_str[i] = accUse[i];
1250 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1252 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1253 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1261 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1262 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1263 //pic16_allocDirReg (IC_LEFT(ic));
1264 aop->size = getSize(sym->type);
1269 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1270 aop->size = getSize(sym->type);
1271 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1272 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1274 DEBUGpic16_emitcode(";","%d",__LINE__);
1278 /* else spill location */
1279 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1280 /* force a new aop if sizes differ */
1281 sym->usl.spillLoc->aop = NULL;
1285 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1286 __FUNCTION__,__LINE__,
1287 sym->usl.spillLoc->rname,
1288 sym->rname, sym->usl.spillLoc->offset);
1291 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1292 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1293 /* Don't reuse the new aop */
1294 sym->usl.spillLoc->aop = NULL;
1296 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1297 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1298 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1300 sym->usl.spillLoc->offset, op);
1302 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1303 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1304 assert (getSize(sym->type) <= 1);
1305 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1307 aop->size = getSize(sym->type);
1313 sym_link *type = operandType(op);
1315 if(IS_PTR_CONST(type))
1317 if(IS_CODEPTR(type))
1319 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1322 /* must be in a register */
1323 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1324 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1325 aop->size = sym->nRegs;
1326 for ( i = 0 ; i < sym->nRegs ;i++)
1327 aop->aopu.aop_reg[i] = sym->regs[i];
1330 /*-----------------------------------------------------------------*/
1331 /* pic16_freeAsmop - free up the asmop given to an operand */
1332 /*----------------------------------------------------------------*/
1333 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1350 /* depending on the asmop type only three cases need work AOP_RO
1351 , AOP_R1 && AOP_STK */
1353 switch (aop->type) {
1355 if (_G.fsr0Pushed ) {
1357 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1358 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1359 // pic16_emitcode ("pop","ar0");
1363 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1367 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1373 pic16_emitcode ("pop","ar0");
1377 bitVectUnSetBit(ic->rUsed,R0_IDX);
1383 pic16_emitcode ("pop","ar1");
1387 bitVectUnSetBit(ic->rUsed,R1_IDX);
1394 /* we must store the result on stack */
1395 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1396 // operands on stack are accessible via "FSR2 + index" with index
1397 // starting at 2 for arguments and growing from 0 downwards for
1398 // local variables (index == 0 is not assigned so we add one here)
1399 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1404 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1405 for(i=0;i<aop->size;i++) {
1406 /* initialise for stack access via frame pointer */
1407 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1408 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1409 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1412 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1416 for(i=0;i<aop->size;i++) {
1417 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1419 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1420 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1421 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1428 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1429 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1430 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1431 deleteSetItem( &_G.sregsAllocSet, sr );
1442 int stk = aop->aopu.aop_stk + aop->size;
1443 bitVectUnSetBit(ic->rUsed,R0_IDX);
1444 bitVectUnSetBit(ic->rUsed,R1_IDX);
1446 getFreePtr(ic,&aop,FALSE);
1448 if (options.stack10bit)
1450 /* I'm not sure what to do here yet... */
1453 "*** Warning: probably generating bad code for "
1454 "10 bit stack mode.\n");
1458 pic16_emitcode ("mov","a,_bp");
1459 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1460 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1462 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1466 pic16_emitcode("pop","acc");
1467 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1469 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1472 pic16_freeAsmop(op,NULL,ic,TRUE);
1474 pic16_emitcode("pop","ar0");
1479 pic16_emitcode("pop","ar1");
1489 /* all other cases just dealloc */
1493 OP_SYMBOL(op)->aop = NULL;
1494 /* if the symbol has a spill */
1496 SPIL_LOC(op)->aop = NULL;
1501 /*-----------------------------------------------------------------*/
1502 /* pic16_aopGet - for fetching value of the aop */
1503 /*-----------------------------------------------------------------*/
1504 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1509 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1511 /* offset is greater than size then zero */
1512 if (offset > (aop->size - 1) &&
1513 aop->type != AOP_LIT)
1516 /* depending on type */
1517 switch (aop->type) {
1521 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1522 rs = Safe_calloc(1, strlen(s)+1);
1527 /* if we need to increment it */
1528 while (offset > aop->coff)
1530 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1534 while (offset < aop->coff)
1536 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1542 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1543 return (dname ? "acc" : "a");
1545 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1546 rs = Safe_calloc (1, strlen (s) + 1);
1554 sprintf (s,"%s",aop->aopu.aop_immd);
1557 sprintf(s,"(%s >> %d)",
1562 aop->aopu.aop_immd);
1563 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1564 rs = Safe_calloc(1,strlen(s)+1);
1570 sprintf(s,"(%s + %d)",
1573 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1575 sprintf(s,"%s",aop->aopu.aop_dir);
1576 rs = Safe_calloc(1,strlen(s)+1);
1581 return aop->aopu.aop_reg[offset]->name;
1584 return aop->aopu.aop_dir;
1587 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1588 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1590 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1591 rs = Safe_strdup("WREG");
1595 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1596 rs = Safe_calloc(1,strlen(s)+1);
1601 aop->coff = offset ;
1603 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1606 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1607 aop->type = AOP_ACC;
1608 return Safe_strdup("_WREG");
1610 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1612 return aop->aopu.aop_str[offset];
1616 pCodeOp *pcop = aop->aopu.pcop;
1617 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1619 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1620 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1622 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1624 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1627 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1630 rs = Safe_calloc(1,strlen(s)+1);
1636 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1638 sprintf(s,"(%s + %d)",
1642 sprintf(s,"%s",aop->aopu.aop_dir);
1643 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644 rs = Safe_calloc(1,strlen(s)+1);
1650 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1654 // pCodeOp *pcop = aop->aop
1659 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1660 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1661 "aopget got unsupported aop->type");
1667 /* lock has the following meaning: When allocating temporary registers
1668 * for stack variables storage, the value of the temporary register is
1669 * saved on stack. Its value is restored at the end. This procedure is
1670 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1671 * a possibility that before a call to pic16_aopOp, a temporary register
1672 * is allocated for a while and it is freed after some time, this will
1673 * mess the stack and values will not be restored properly. So use lock=1
1674 * to allocate temporary registers used internally by the programmer, and
1675 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1676 * to inform the compiler developer about a possible bug. This is an internal
1677 * feature for developing the compiler -- VR */
1679 int _TempReg_lock = 0;
1680 /*-----------------------------------------------------------------*/
1681 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1682 /*-----------------------------------------------------------------*/
1683 pCodeOp *pic16_popGetTempReg(int lock)
1688 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1690 // werror(W_POSSBUG2, __FILE__, __LINE__);
1693 _TempReg_lock += lock;
1703 /* this code might seem better but it does the *same* job with
1704 * the old code, it all depends on ralloc.c to get a free/unused
1708 while(i < pic16_nRegs) {
1709 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1710 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1711 if((!rr || (rr && rr->isFree))
1712 && !bitVectBitValue(cfunc->regsUsed, i)) {
1713 pcop = pic16_newpCodeOpReg( i );
1714 PCOR(pcop)->r->wasUsed = 1;
1715 PCOR(pcop)->r->isFree = 0;
1722 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1726 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1727 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1728 PCOR(pcop)->r->wasUsed=1;
1729 PCOR(pcop)->r->isFree=0;
1731 /* push value on stack */
1732 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741 /*-----------------------------------------------------------------*/
1742 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1743 /* is not part of f, but don't save if */
1745 /*-----------------------------------------------------------------*/
1746 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1752 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1755 // werror(W_POSSBUG2, __FILE__, __LINE__);
1758 _TempReg_lock += lock;
1763 i = bitVectFirstBit(f);
1766 /* bypass registers that are used by function */
1767 if(!bitVectBitValue(f, i)) {
1769 /* bypass registers that are already allocated for stack access */
1770 if(!bitVectBitValue(v, i)) {
1772 // debugf("getting register rIdx = %d\n", i);
1773 /* ok, get the operand */
1774 pcop = pic16_newpCodeOpReg( i );
1776 /* should never by NULL */
1777 assert( pcop != NULL );
1781 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1784 PCOR(pcop)->r->wasUsed=1;
1785 PCOR(pcop)->r->isFree=0;
1791 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1793 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1794 /* already used in previous steps, break */
1801 /* caller takes care of the following */
1802 // bitVectSetBit(v, i);
1805 /* push value on stack */
1806 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1807 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1823 /*-----------------------------------------------------------------*/
1824 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1825 /*-----------------------------------------------------------------*/
1826 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1830 _TempReg_lock -= lock;
1832 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1833 PCOR(pcop)->r->isFree = 1;
1835 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1840 /*-----------------------------------------------------------------*/
1841 pCodeOp *pic16_popGetLabel(int key)
1844 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1849 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popCopyReg - copy a pcode operator */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1859 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1860 memcpy (pcor, pc, sizeof (pCodeOpReg));
1861 pcor->r->wasUsed = 1;
1863 //pcor->pcop.type = pc->pcop.type;
1865 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1866 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1868 pcor->pcop.name = NULL;
1871 //pcor->rIdx = pc->rIdx;
1872 //pcor->r->wasUsed=1;
1873 //pcor->instance = pc->instance;
1875 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1880 /*-----------------------------------------------------------------*/
1881 /* pic16_popGetLit - asm operator to pcode operator conversion */
1882 /*-----------------------------------------------------------------*/
1883 pCodeOp *pic16_popGetLit(int lit)
1885 return pic16_newpCodeOpLit(lit);
1888 /* Allow for 12 bit literals (LFSR x, <here!>). */
1889 pCodeOp *pic16_popGetLit12(int lit)
1891 return pic16_newpCodeOpLit12(lit);
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1899 return pic16_newpCodeOpLit2(lit, arg2);
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1908 return pic16_newpCodeOpImmd(name, offset,index, 0);
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGet - asm operator to pcode operator conversion */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetWithString(char *str)
1921 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1925 pcop = pic16_newpCodeOp(str,PO_STR);
1930 /*-----------------------------------------------------------------*/
1931 /* pic16_popRegFromString - */
1932 /*-----------------------------------------------------------------*/
1933 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1936 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1937 pcop->type = PO_DIR;
1939 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1940 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1945 pcop->name = Safe_calloc(1,strlen(str)+1);
1946 strcpy(pcop->name,str);
1948 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1950 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1951 // PCOR(pcop)->r->wasUsed = 1;
1953 /* make sure that register doesn't exist,
1954 * and operand isn't NULL
1955 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1956 if((PCOR(pcop)->r == NULL)
1958 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1959 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1960 // __FUNCTION__, __LINE__, str, size, offset);
1962 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1963 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1966 PCOR(pcop)->instance = offset;
1971 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1975 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1976 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1978 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1979 PCOR(pcop)->rIdx = rIdx;
1980 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1982 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1984 PCOR(pcop)->r->isFree = 0;
1985 PCOR(pcop)->r->wasUsed = 1;
1987 pcop->type = PCOR(pcop)->r->pc_type;
1992 /*---------------------------------------------------------------------------------*/
1993 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1995 /*---------------------------------------------------------------------------------*/
1996 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1998 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1999 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2005 /*--------------------------------------------------------------------------------.-*/
2006 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2007 /* VR 030601 , adapted by Hans Dorn */
2008 /*--------------------------------------------------------------------------------.-*/
2009 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2012 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2016 /*---------------------------------------------------------------------------------*/
2017 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2018 /* movff instruction */
2019 /*---------------------------------------------------------------------------------*/
2020 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2022 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2023 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2029 /*-----------------------------------------------------------------*/
2030 /* pic16_popGet - asm operator to pcode operator conversion */
2031 /*-----------------------------------------------------------------*/
2032 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2034 // char *s = buffer ;
2039 /* offset is greater than
2042 // if (offset > (aop->size - 1) &&
2043 // aop->type != AOP_LIT)
2044 // return NULL; //zero;
2046 /* depending on type */
2047 switch (aop->type) {
2052 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2053 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2059 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2060 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2061 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2062 PCOR(pcop)->r->wasUsed = 1;
2063 PCOR(pcop)->r->isFree = 0;
2065 PCOR(pcop)->instance = offset;
2066 pcop->type = PCOR(pcop)->r->pc_type;
2070 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2071 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2074 /* pCodeOp is already allocated from aopForSym */
2075 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2076 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2081 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2083 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2085 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2087 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2088 PCOR(pcop)->rIdx = rIdx;
2089 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2090 PCOR(pcop)->r->wasUsed=1;
2091 PCOR(pcop)->r->isFree=0;
2093 PCOR(pcop)->instance = offset;
2094 pcop->type = PCOR(pcop)->r->pc_type;
2095 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2099 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2100 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2106 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2107 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2111 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2112 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2118 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2119 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2121 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2123 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2124 // pcop->type = PO_GPR_REGISTER;
2125 PCOR(pcop)->rIdx = rIdx;
2126 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2127 PCOR(pcop)->r->wasUsed=1;
2128 PCOR(pcop)->r->isFree=0;
2130 PCOR(pcop)->instance = offset;
2131 pcop->type = PCOR(pcop)->r->pc_type;
2133 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2134 // rs = aop->aopu.aop_reg[offset]->name;
2135 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2140 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2142 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2143 PCOR(pcop)->instance = offset;
2144 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2145 //if(PCOR(pcop)->r == NULL)
2146 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2150 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2151 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2154 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2155 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2158 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2159 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2160 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2161 pcop->type = PCOR(pcop)->r->pc_type;
2162 pcop->name = PCOR(pcop)->r->name;
2168 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2170 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2171 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2172 switch( aop->aopu.pcop->type ) {
2173 case PO_DIR: PCOR(pcop)->instance += offset; break;
2174 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2179 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2180 assert( 0 ); /* should never reach here */;
2185 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2186 "pic16_popGet got unsupported aop->type");
2189 /*-----------------------------------------------------------------*/
2190 /* pic16_aopPut - puts a string for a aop */
2191 /*-----------------------------------------------------------------*/
2192 void pic16_aopPut (asmop *aop, char *s, int offset)
2199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2201 if (aop->size && offset > ( aop->size - 1)) {
2202 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2203 "pic16_aopPut got offset > aop->size");
2207 /* will assign value to value */
2208 /* depending on where it is ofcourse */
2209 switch (aop->type) {
2212 sprintf(d,"(%s + %d)",
2213 aop->aopu.aop_dir,offset);
2214 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2217 sprintf(d,"%s",aop->aopu.aop_dir);
2220 DEBUGpic16_emitcode(";","%d",__LINE__);
2222 pic16_emitcode("movf","%s,w",s);
2223 pic16_emitcode("movwf","%s",d);
2226 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2227 if(offset >= aop->size) {
2228 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2231 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2234 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2241 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2242 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2245 strcmp(s,"r0") == 0 ||
2246 strcmp(s,"r1") == 0 ||
2247 strcmp(s,"r2") == 0 ||
2248 strcmp(s,"r3") == 0 ||
2249 strcmp(s,"r4") == 0 ||
2250 strcmp(s,"r5") == 0 ||
2251 strcmp(s,"r6") == 0 ||
2252 strcmp(s,"r7") == 0 )
2253 pic16_emitcode("mov","%s,%s ; %d",
2254 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2258 if(strcmp(s,"W")==0 )
2259 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2261 pic16_emitcode("movwf","%s",
2262 aop->aopu.aop_reg[offset]->name);
2264 if(strcmp(s,zero)==0) {
2265 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2267 } else if(strcmp(s,"W")==0) {
2268 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2269 pcop->type = PO_GPR_REGISTER;
2271 PCOR(pcop)->rIdx = -1;
2272 PCOR(pcop)->r = NULL;
2274 DEBUGpic16_emitcode(";","%d",__LINE__);
2275 pcop->name = Safe_strdup(s);
2276 pic16_emitpcode(POC_MOVFW,pcop);
2277 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2278 } else if(strcmp(s,one)==0) {
2279 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2280 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2282 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2290 if (aop->type == AOP_DPTR2)
2296 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2297 "pic16_aopPut writting to code space");
2301 while (offset > aop->coff) {
2303 pic16_emitcode ("inc","dptr");
2306 while (offset < aop->coff) {
2308 pic16_emitcode("lcall","__decdptr");
2313 /* if not in accumulater */
2316 pic16_emitcode ("movx","@dptr,a");
2318 if (aop->type == AOP_DPTR2)
2326 while (offset > aop->coff) {
2328 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2330 while (offset < aop->coff) {
2332 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2338 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2343 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2345 if (strcmp(s,"r0") == 0 ||
2346 strcmp(s,"r1") == 0 ||
2347 strcmp(s,"r2") == 0 ||
2348 strcmp(s,"r3") == 0 ||
2349 strcmp(s,"r4") == 0 ||
2350 strcmp(s,"r5") == 0 ||
2351 strcmp(s,"r6") == 0 ||
2352 strcmp(s,"r7") == 0 ) {
2354 sprintf(buffer,"a%s",s);
2355 pic16_emitcode("mov","@%s,%s",
2356 aop->aopu.aop_ptr->name,buffer);
2358 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2363 if (strcmp(s,"a") == 0)
2364 pic16_emitcode("push","acc");
2366 pic16_emitcode("push","%s",s);
2371 /* if bit variable */
2372 if (!aop->aopu.aop_dir) {
2373 pic16_emitcode("clr","a");
2374 pic16_emitcode("rlc","a");
2377 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2380 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2383 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2385 lbl = newiTempLabel(NULL);
2387 if (strcmp(s,"a")) {
2390 pic16_emitcode("clr","c");
2391 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2392 pic16_emitcode("cpl","c");
2393 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2394 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2401 if (strcmp(aop->aopu.aop_str[offset],s))
2402 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2407 if (!offset && (strcmp(s,"acc") == 0))
2410 if (strcmp(aop->aopu.aop_str[offset],s))
2411 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2415 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2416 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2417 // "pic16_aopPut got unsupported aop->type");
2423 /*-----------------------------------------------------------------*/
2424 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2425 /*-----------------------------------------------------------------*/
2426 void pic16_mov2w (asmop *aop, int offset)
2428 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2431 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2433 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2436 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2438 if(is_LitAOp(src)) {
2439 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2440 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2442 if(pic16_sameRegsOfs(src, dst, offset))return;
2443 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2444 pic16_popGet(dst, offset)));
2448 static void pic16_movLit2f(pCodeOp *pc, int lit)
2450 if (0 == (lit & 0x00ff))
2452 pic16_emitpcode (POC_CLRF, pc);
2453 } else if (0xff == (lit & 0x00ff))
2455 pic16_emitpcode (POC_SETF, pc);
2457 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2458 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2462 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2464 if(is_LitAOp(src)) {
2465 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2466 pic16_emitpcode(POC_MOVWF, dst);
2468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2472 void pic16_testStackOverflow(void)
2474 #define GSTACK_TEST_NAME "_gstack_test"
2476 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2481 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2482 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2483 // strcpy(sym->rname, GSTACK_TEST_NAME);
2484 checkAddSym(&externs, sym);
2489 /* push pcop into stack */
2490 void pic16_pushpCodeOp(pCodeOp *pcop)
2492 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2494 if(pic16_options.gstack)
2495 pic16_testStackOverflow();
2499 /* pop pcop from stack */
2500 void pic16_poppCodeOp(pCodeOp *pcop)
2502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2503 if(pic16_options.gstack)
2504 pic16_testStackOverflow();
2508 /*-----------------------------------------------------------------*/
2509 /* pushw - pushes wreg to stack */
2510 /*-----------------------------------------------------------------*/
2513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2514 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2515 if(pic16_options.gstack)
2516 pic16_testStackOverflow();
2520 /*-----------------------------------------------------------------*/
2521 /* pushaop - pushes aop to stack */
2522 /*-----------------------------------------------------------------*/
2523 void pushaop(asmop *aop, int offset)
2525 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2527 if(_G.resDirect)return;
2529 if(is_LitAOp(aop)) {
2530 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2531 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2533 pic16_emitpcode(POC_MOVFF,
2534 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2537 if(pic16_options.gstack)
2538 pic16_testStackOverflow();
2541 /*-----------------------------------------------------------------*/
2542 /* popaop - pops aop from stack */
2543 /*-----------------------------------------------------------------*/
2544 void popaop(asmop *aop, int offset)
2546 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2547 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2548 if(pic16_options.gstack)
2549 pic16_testStackOverflow();
2552 void popaopidx(asmop *aop, int offset, int index)
2556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2558 if(STACK_MODEL_LARGE)ofs++;
2560 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2561 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2562 if(pic16_options.gstack)
2563 pic16_testStackOverflow();
2566 #if !(USE_GENERIC_SIGNED_SHIFT)
2567 /*-----------------------------------------------------------------*/
2568 /* reAdjustPreg - points a register back to where it should */
2569 /*-----------------------------------------------------------------*/
2570 static void reAdjustPreg (asmop *aop)
2574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2576 if ((size = aop->size) <= 1)
2579 switch (aop->type) {
2583 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2587 if (aop->type == AOP_DPTR2)
2593 pic16_emitcode("lcall","__decdptr");
2596 if (aop->type == AOP_DPTR2)
2608 /*-----------------------------------------------------------------*/
2609 /* opIsGptr: returns non-zero if the passed operand is */
2610 /* a generic pointer type. */
2611 /*-----------------------------------------------------------------*/
2612 static int opIsGptr(operand *op)
2614 sym_link *type = operandType(op);
2616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2617 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2625 /*-----------------------------------------------------------------*/
2626 /* pic16_getDataSize - get the operand data size */
2627 /*-----------------------------------------------------------------*/
2628 int pic16_getDataSize(operand *op)
2630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2633 return AOP_SIZE(op);
2635 // tsd- in the pic port, the genptr size is 1, so this code here
2636 // fails. ( in the 8051 port, the size was 4).
2639 size = AOP_SIZE(op);
2640 if (size == GPTRSIZE)
2642 sym_link *type = operandType(op);
2643 if (IS_GENPTR(type))
2645 /* generic pointer; arithmetic operations
2646 * should ignore the high byte (pointer type).
2649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2656 /*-----------------------------------------------------------------*/
2657 /* pic16_outAcc - output Acc */
2658 /*-----------------------------------------------------------------*/
2659 void pic16_outAcc(operand *result)
2662 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2663 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2666 size = pic16_getDataSize(result);
2668 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2671 /* unsigned or positive */
2673 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outBitC - output a bit C */
2680 /* Move to result the value of Carry flag -- VR */
2681 /*-----------------------------------------------------------------*/
2682 void pic16_outBitC(operand *result)
2686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2688 /* if the result is bit */
2689 if (AOP_TYPE(result) == AOP_CRY) {
2690 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2691 pic16_aopPut(AOP(result),"c",0);
2694 i = AOP_SIZE(result);
2696 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2698 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2702 /*-----------------------------------------------------------------*/
2703 /* pic16_outBitOp - output a bit from Op */
2704 /* Move to result the value of set/clr op -- VR */
2705 /*-----------------------------------------------------------------*/
2706 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2712 /* if the result is bit */
2713 if (AOP_TYPE(result) == AOP_CRY) {
2714 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2715 pic16_aopPut(AOP(result),"c",0);
2718 i = AOP_SIZE(result);
2720 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2722 pic16_emitpcode(POC_RRCF, pcop);
2723 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2727 /*-----------------------------------------------------------------*/
2728 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2729 /*-----------------------------------------------------------------*/
2730 void pic16_toBoolean(operand *oper)
2732 int size = AOP_SIZE(oper) - 1;
2735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2737 if ( AOP_TYPE(oper) != AOP_ACC) {
2738 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2745 /*-----------------------------------------------------------------*/
2746 /* genUminusFloat - unary minus for floating points */
2747 /*-----------------------------------------------------------------*/
2748 static void genUminusFloat(operand *op,operand *result)
2750 int size ,offset =0 ;
2753 /* for this we just need to flip the
2754 first it then copy the rest in place */
2755 size = AOP_SIZE(op);
2756 assert( size == AOP_SIZE(result) );
2759 pic16_mov2f(AOP(result), AOP(op), offset);
2763 /* toggle the MSB's highest bit */
2764 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2767 /*-----------------------------------------------------------------*/
2768 /* genUminus - unary minus code generation */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminus (iCode *ic)
2773 sym_link *optype, *rtype;
2780 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2781 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2783 /* if both in bit space then special case */
2784 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2785 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2787 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2788 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2789 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2793 optype = operandType(IC_LEFT(ic));
2794 rtype = operandType(IC_RESULT(ic));
2797 /* if float then do float stuff */
2798 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2799 if(IS_FIXED(optype))
2800 debugf("implement fixed16x16 type\n", 0);
2802 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2806 /* otherwise subtract from zero by taking the 2's complement */
2807 size = AOP_SIZE(IC_LEFT(ic));
2808 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2809 label = newiTempLabel ( NULL );
2811 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2812 for (i=size-1; i > 0; i--) {
2813 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2815 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2816 for (i=1; i < size; i++) {
2817 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2818 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2821 for (i=size-1; i >= 0; i--) {
2822 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2823 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2826 for (i=0; i < size-2; i++) {
2827 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2828 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2830 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2832 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2835 pic16_emitpLabel (label->key);
2838 /* release the aops */
2839 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2840 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2844 /*-----------------------------------------------------------------*/
2845 /* saveRegisters - will look for a call and save the registers */
2846 /*-----------------------------------------------------------------*/
2847 static void saveRegisters(iCode *lic)
2854 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2856 for (ic = lic ; ic ; ic = ic->next)
2857 if (ic->op == CALL || ic->op == PCALL)
2861 fprintf(stderr,"found parameter push with no function call\n");
2865 /* if the registers have been saved already then
2867 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2870 /* find the registers in use at this time
2871 and push them away to safety */
2872 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2876 if (options.useXstack) {
2877 if (bitVectBitValue(rsave,R0_IDX))
2878 pic16_emitcode("mov","b,r0");
2879 pic16_emitcode("mov","r0,%s",spname);
2880 for (i = 0 ; i < pic16_nRegs ; i++) {
2881 if (bitVectBitValue(rsave,i)) {
2883 pic16_emitcode("mov","a,b");
2885 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2886 pic16_emitcode("movx","@r0,a");
2887 pic16_emitcode("inc","r0");
2890 pic16_emitcode("mov","%s,r0",spname);
2891 if (bitVectBitValue(rsave,R0_IDX))
2892 pic16_emitcode("mov","r0,b");
2894 //for (i = 0 ; i < pic16_nRegs ; i++) {
2895 // if (bitVectBitValue(rsave,i))
2896 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2899 dtype = operandType(IC_LEFT(ic));
2900 if (currFunc && dtype &&
2901 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2902 IFFUNC_ISISR(currFunc->type) &&
2905 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2908 /*-----------------------------------------------------------------*/
2909 /* unsaveRegisters - pop the pushed registers */
2910 /*-----------------------------------------------------------------*/
2911 static void unsaveRegisters (iCode *ic)
2916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2917 /* find the registers in use at this time
2918 and push them away to safety */
2919 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2922 if (options.useXstack) {
2923 pic16_emitcode("mov","r0,%s",spname);
2924 for (i = pic16_nRegs ; i >= 0 ; i--) {
2925 if (bitVectBitValue(rsave,i)) {
2926 pic16_emitcode("dec","r0");
2927 pic16_emitcode("movx","a,@r0");
2929 pic16_emitcode("mov","b,a");
2931 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2935 pic16_emitcode("mov","%s,r0",spname);
2936 if (bitVectBitValue(rsave,R0_IDX))
2937 pic16_emitcode("mov","r0,b");
2939 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2940 // if (bitVectBitValue(rsave,i))
2941 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2948 /*-----------------------------------------------------------------*/
2950 /*-----------------------------------------------------------------*/
2951 static void pushSide(operand * oper, int size)
2954 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2956 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2957 if (AOP_TYPE(oper) != AOP_REG &&
2958 AOP_TYPE(oper) != AOP_DIR &&
2960 pic16_emitcode("mov","a,%s",l);
2961 pic16_emitcode("push","acc");
2963 pic16_emitcode("push","%s",l);
2968 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2970 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2971 pic16_emitpcode(POC_MOVFW, src);
2972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2974 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2975 src, pic16_popGet(AOP(op), offset)));
2980 /*-----------------------------------------------------------------*/
2981 /* assignResultValue - assign results to oper, rescall==1 is */
2982 /* called from genCall() or genPcall() */
2983 /*-----------------------------------------------------------------*/
2984 static void assignResultValue(operand * oper, int rescall)
2986 int size = AOP_SIZE(oper);
2990 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2991 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2994 /* assign result from a call/pcall function() */
2996 /* function results are stored in a special order,
2997 * see top of file with Function return policy, or manual */
3000 /* 8-bits, result in WREG */
3001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3004 /* 16-bits, result in PRODL:WREG */
3005 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3009 /* 24-bits, result in PRODH:PRODL:WREG */
3010 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3014 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3015 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3019 /* >32-bits, result on stack, and FSR0 points to beginning.
3020 * Fix stack when done */
3022 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3024 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3025 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3027 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3033 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3034 if(STACK_MODEL_LARGE) {
3036 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3040 int areg = 0; /* matching argument register */
3042 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3043 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3046 /* its called from genReceive (probably) -- VR */
3047 /* I hope this code will not be called from somewhere else in the future!
3048 * We manually set the pseudo stack pointer in genReceive. - dw
3050 if(!GpsuedoStkPtr && _G.useWreg) {
3051 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3053 /* The last byte in the assignment is in W */
3054 if(areg <= GpsuedoStkPtr) {
3056 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3058 // debugf("receive from WREG\n", 0);
3060 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3063 _G.stack_lat = AOP_SIZE(oper)-1;
3068 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3069 // debugf("receive from STACK\n", 0);
3076 /*-----------------------------------------------------------------*/
3077 /* genIpush - generate code for pushing this gets a little complex */
3078 /*-----------------------------------------------------------------*/
3079 static void genIpush (iCode *ic)
3081 // int size, offset=0;
3084 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3087 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3089 /* send to stack as normal */
3090 addSet(&_G.sendSet,ic);
3091 // addSetHead(&_G.sendSet,ic);
3092 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3097 int size, offset = 0 ;
3101 /* if this is not a parm push : ie. it is spill push
3102 and spill push is always done on the local stack */
3103 if (!ic->parmPush) {
3105 /* and the item is spilt then do nothing */
3106 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3109 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3110 size = AOP_SIZE(IC_LEFT(ic));
3111 /* push it on the stack */
3113 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3118 pic16_emitcode("push","%s",l);
3123 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3127 /*-----------------------------------------------------------------*/
3128 /* genIpop - recover the registers: can happen only for spilling */
3129 /*-----------------------------------------------------------------*/
3130 static void genIpop (iCode *ic)
3133 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3138 /* if the temp was not pushed then */
3139 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3142 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3143 size = AOP_SIZE(IC_LEFT(ic));
3146 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3149 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3154 /*-----------------------------------------------------------------*/
3155 /* unsaverbank - restores the resgister bank from stack */
3156 /*-----------------------------------------------------------------*/
3157 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3159 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3165 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3167 if (options.useXstack) {
3169 r = getFreePtr(ic,&aop,FALSE);
3172 pic16_emitcode("mov","%s,_spx",r->name);
3173 pic16_emitcode("movx","a,@%s",r->name);
3174 pic16_emitcode("mov","psw,a");
3175 pic16_emitcode("dec","%s",r->name);
3178 pic16_emitcode ("pop","psw");
3181 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3182 if (options.useXstack) {
3183 pic16_emitcode("movx","a,@%s",r->name);
3184 //pic16_emitcode("mov","(%s+%d),a",
3185 // regspic16[i].base,8*bank+regspic16[i].offset);
3186 pic16_emitcode("dec","%s",r->name);
3189 pic16_emitcode("pop",""); //"(%s+%d)",
3190 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3193 if (options.useXstack) {
3195 pic16_emitcode("mov","_spx,%s",r->name);
3196 pic16_freeAsmop(NULL,aop,ic,TRUE);
3202 /*-----------------------------------------------------------------*/
3203 /* saverbank - saves an entire register bank on the stack */
3204 /*-----------------------------------------------------------------*/
3205 static void saverbank (int bank, iCode *ic, bool pushPsw)
3207 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3214 if (options.useXstack) {
3217 r = getFreePtr(ic,&aop,FALSE);
3218 pic16_emitcode("mov","%s,_spx",r->name);
3222 for (i = 0 ; i < pic16_nRegs ;i++) {
3223 if (options.useXstack) {
3224 pic16_emitcode("inc","%s",r->name);
3225 //pic16_emitcode("mov","a,(%s+%d)",
3226 // regspic16[i].base,8*bank+regspic16[i].offset);
3227 pic16_emitcode("movx","@%s,a",r->name);
3229 pic16_emitcode("push","");// "(%s+%d)",
3230 //regspic16[i].base,8*bank+regspic16[i].offset);
3234 if (options.useXstack) {
3235 pic16_emitcode("mov","a,psw");
3236 pic16_emitcode("movx","@%s,a",r->name);
3237 pic16_emitcode("inc","%s",r->name);
3238 pic16_emitcode("mov","_spx,%s",r->name);
3239 pic16_freeAsmop (NULL,aop,ic,TRUE);
3242 pic16_emitcode("push","psw");
3244 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3252 static int wparamCmp(void *p1, void *p2)
3254 return (!strcmp((char *)p1, (char *)p2));
3257 int inWparamList(char *s)
3259 return isinSetWith(wparamList, s, wparamCmp);
3263 /*-----------------------------------------------------------------*/
3264 /* genCall - generates a call statement */
3265 /*-----------------------------------------------------------------*/
3266 static void genCall (iCode *ic)
3276 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3277 /* if caller saves & we have not saved then */
3278 // if (!ic->regsSaved)
3279 // saveRegisters(ic);
3281 /* initialise stackParms for IPUSH pushes */
3282 // stackParms = psuedoStkPtr;
3283 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3284 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3285 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3288 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3291 /* if send set is not empty the assign */
3294 int psuedoStkPtr=-1;
3295 int firstTimeThruLoop = 1;
3298 /* reverse sendSet if function is not reentrant */
3299 if(!IFFUNC_ISREENT(ftype))
3300 _G.sendSet = reverseSet(_G.sendSet);
3302 /* First figure how many parameters are getting passed */
3306 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3310 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3311 size = AOP_SIZE(IC_LEFT(sic));
3315 /* pass the last byte through WREG */
3319 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3320 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3321 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3323 if(!firstTimeThruLoop) {
3324 /* If this is not the first time we've been through the loop
3325 * then we need to save the parameter in a temporary
3326 * register. The last byte of the last parameter is
3330 // --psuedoStkPtr; // sanity check
3334 firstTimeThruLoop=0;
3336 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3341 /* all arguments are passed via stack */
3345 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3349 // pushaop(AOP(IC_LEFT(sic)), size);
3350 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3357 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3361 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3362 pushw(); /* save last parameter to stack if functions has varargs */
3366 } else use_wreg = 0;
3368 _G.stackRegSet = _G.sendSet;
3373 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3377 /* if we need to assign a result value */
3378 if ((IS_ITEMP(IC_RESULT(ic))
3379 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3380 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3381 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3384 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3387 assignResultValue(IC_RESULT(ic), 1);
3389 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3390 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3392 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3395 if(!stackParms && ic->parmBytes) {
3396 stackParms = ic->parmBytes;
3399 stackParms -= use_wreg;
3402 if(stackParms == 1) {
3403 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3405 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3406 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3408 if(STACK_MODEL_LARGE) {
3410 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3415 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3418 /* adjust the stack for parameters if required */
3419 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3422 /* if register bank was saved then pop them */
3424 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3426 /* if we hade saved some registers then unsave them */
3427 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3428 unsaveRegisters (ic);
3434 /*-----------------------------------------------------------------*/
3435 /* genPcall - generates a call by pointer statement */
3436 /* new version, created from genCall - HJD */
3437 /*-----------------------------------------------------------------*/
3438 static void genPcall (iCode *ic)
3442 symbol *retlbl = newiTempLabel(NULL);
3443 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3447 fntype = operandType( IC_LEFT(ic) )->next;
3449 /* if send set is not empty the assign */
3452 int psuedoStkPtr=-1;
3454 /* reverse sendSet if function is not reentrant */
3455 if(!IFFUNC_ISREENT(fntype))
3456 _G.sendSet = reverseSet(_G.sendSet);
3460 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3463 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3464 size = AOP_SIZE(IC_LEFT(sic));
3467 /* all parameters are passed via stack, since WREG is clobbered
3468 * by the calling sequence */
3470 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3471 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3472 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3474 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3478 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3481 _G.stackRegSet = _G.sendSet;
3485 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3487 // push return address
3488 // push $ on return stack, then replace with retlbl
3490 /* Thanks to Thorsten Klose for pointing out that the following
3491 * snippet should be interrupt safe */
3492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3493 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3495 pic16_emitpcodeNULLop(POC_PUSH);
3497 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3498 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3499 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3500 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3501 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3502 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3505 /* restore interrupt control register */
3506 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3507 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3509 /* make the call by writing the pointer into pc */
3510 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3511 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3513 // note: MOVFF to PCL not allowed
3514 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3515 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3518 /* return address is here: (X) */
3519 pic16_emitpLabelFORCE(retlbl->key);
3521 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3524 /* if we need assign a result value */
3525 if ((IS_ITEMP(IC_RESULT(ic))
3526 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3527 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3528 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3531 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3534 assignResultValue(IC_RESULT(ic), 1);
3536 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3537 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3539 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3542 // stackParms -= use_wreg;
3545 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3546 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3547 if(STACK_MODEL_LARGE) {
3549 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3554 /*-----------------------------------------------------------------*/
3555 /* resultRemat - result is rematerializable */
3556 /*-----------------------------------------------------------------*/
3557 static int resultRemat (iCode *ic)
3559 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3560 if (SKIP_IC(ic) || ic->op == IFX)
3563 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3564 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3565 if (sym->remat && !POINTER_SET(ic))
3572 #if defined(__BORLANDC__) || defined(_MSC_VER)
3573 #define STRCASECMP stricmp
3575 #define STRCASECMP strcasecmp
3579 /*-----------------------------------------------------------------*/
3580 /* inExcludeList - return 1 if the string is in exclude Reg list */
3581 /*-----------------------------------------------------------------*/
3582 static bool inExcludeList(char *s)
3584 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 if (options.excludeRegs[i] &&
3589 STRCASECMP(options.excludeRegs[i],"none") == 0)
3592 for ( i = 0 ; options.excludeRegs[i]; i++) {
3593 if (options.excludeRegs[i] &&
3594 STRCASECMP(s,options.excludeRegs[i]) == 0)
3601 /*-----------------------------------------------------------------*/
3602 /* genFunction - generated code for function entry */
3603 /*-----------------------------------------------------------------*/
3604 static void genFunction (iCode *ic)
3610 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3612 pic16_labelOffset += (max_key+4);
3617 ftype = operandType(IC_LEFT(ic));
3618 sym = OP_SYMBOL(IC_LEFT(ic));
3620 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3621 /* create an absolute section at the interrupt vector:
3622 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3627 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3629 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3630 sprintf(asymname, "ivec_%s", sym->name);
3632 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3634 /* when an interrupt is declared as naked, do not emit the special
3635 * wrapper segment at vector address. The user should take care for
3636 * this instead. -- VR */
3638 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3639 asym = newSymbol(asymname, 0);
3640 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3641 pic16_addpBlock( apb );
3643 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3644 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3645 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3646 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3647 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3649 /* mark the end of this tiny function */
3650 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3652 sprintf(asymname, "%s", sym->rname);
3658 abSym = Safe_calloc(1, sizeof(absSym));
3659 strcpy(abSym->name, asymname);
3661 switch( FUNC_INTNO(sym->type) ) {
3662 case 0: abSym->address = 0x000000; break;
3663 case 1: abSym->address = 0x000008; break;
3664 case 2: abSym->address = 0x000018; break;
3667 // fprintf(stderr, "no interrupt number is given\n");
3668 abSym->address = -1; break;
3671 /* relocate interrupt vectors if needed */
3672 if(abSym->address != -1)
3673 abSym->address += pic16_options.ivt_loc;
3675 addSet(&absSymSet, abSym);
3679 /* create the function header */
3680 pic16_emitcode(";","-----------------------------------------");
3681 pic16_emitcode(";"," function %s",sym->name);
3682 pic16_emitcode(";","-----------------------------------------");
3684 pic16_emitcode("","%s:",sym->rname);
3685 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3690 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3691 if(!strcmp(ab->name, sym->rname)) {
3692 pic16_pBlockConvert2Absolute(pb);
3698 if(IFFUNC_ISNAKED(ftype)) {
3699 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3703 /* if critical function then turn interrupts off */
3704 if (IFFUNC_ISCRITICAL(ftype)) {
3705 //pic16_emitcode("clr","ea");
3708 currFunc = sym; /* update the currFunc symbol */
3709 _G.fregsUsed = sym->regsUsed;
3710 _G.sregsAlloc = newBitVect(128);
3713 /* if this is an interrupt service routine then
3714 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3715 if (IFFUNC_ISISR(sym->type)) {
3716 _G.usefastretfie = 1; /* use shadow registers by default */
3718 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3719 if(!FUNC_ISSHADOWREGS(sym->type)) {
3720 /* do not save WREG,STATUS,BSR for high priority interrupts
3721 * because they are stored in the hardware shadow registers already */
3722 _G.usefastretfie = 0;
3723 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3724 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3725 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3728 /* these should really be optimized somehow, because not all
3729 * interrupt handlers modify them */
3730 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3731 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3732 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3733 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3735 // pic16_pBlockConvert2ISR(pb);
3738 /* emit code to setup stack frame if user enabled,
3739 * and function is not main() */
3741 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3742 if(strcmp(sym->name, "main")) {
3744 || !options.ommitFramePtr
3746 || IFFUNC_ARGS(sym->type)
3747 || FUNC_HASSTACKPARM(sym->etype)
3749 /* setup the stack frame */
3750 if(STACK_MODEL_LARGE)
3751 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3752 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3754 if(STACK_MODEL_LARGE)
3755 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3756 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3760 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3763 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3765 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3766 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3768 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3771 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3772 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3779 /* if callee-save to be used for this function
3780 * then save the registers being used in this function */
3781 // if (IFFUNC_CALLEESAVES(sym->type))
3782 if(strcmp(sym->name, "main")) {
3785 /* if any registers used */
3786 if (sym->regsUsed) {
3787 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3790 /* save the registers used */
3791 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3792 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3793 if (bitVectBitValue(sym->regsUsed,i)) {
3795 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3797 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3800 if(!pic16_regWithIdx(i)->wasUsed) {
3801 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3802 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3803 pic16_regWithIdx(i)->wasUsed = 1;
3810 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3811 for(i=0;i<sym->regsUsed->size;i++) {
3812 if(bitVectBitValue(sym->regsUsed, i)) {
3817 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3820 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3825 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3826 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3829 /*-----------------------------------------------------------------*/
3830 /* genEndFunction - generates epilogue for functions */
3831 /*-----------------------------------------------------------------*/
3832 static void genEndFunction (iCode *ic)
3834 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3838 if(IFFUNC_ISNAKED(sym->type)) {
3839 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3845 /* add code for ISCRITICAL */
3846 if(IFFUNC_ISCRITICAL(sym->type)) {
3847 /* if critical function, turn on interrupts */
3849 /* TODO: add code here -- VR */
3852 // sym->regsUsed = _G.fregsUsed;
3854 /* now we need to restore the registers */
3855 /* if any registers used */
3857 /* first restore registers that might be used for stack access */
3858 if(_G.sregsAllocSet) {
3861 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3862 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3863 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3867 if (strcmp(sym->name, "main") && sym->regsUsed) {
3870 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3871 /* restore registers used */
3872 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3873 for ( i = sym->regsUsed->size; i >= 0; i--) {
3874 if (bitVectBitValue(sym->regsUsed,i)) {
3875 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3879 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3884 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3886 if (sym->stack == 1) {
3887 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3888 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3890 // we have to add more than one...
3891 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3892 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3893 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3895 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3897 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3901 if(strcmp(sym->name, "main")) {
3903 || !options.ommitFramePtr
3905 || IFFUNC_ARGS(sym->type)
3906 || FUNC_HASSTACKPARM(sym->etype)
3908 /* restore stack frame */
3909 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3910 if(STACK_MODEL_LARGE)
3911 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3917 if (IFFUNC_ISISR(sym->type)) {
3918 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3919 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3920 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3921 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3923 if(!FUNC_ISSHADOWREGS(sym->type)) {
3924 /* do not restore interrupt vector for WREG,STATUS,BSR
3925 * for high priority interrupt, see genFunction */
3926 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3928 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3930 // _G.interruptvector = 0; /* sanity check */
3933 /* if debug then send end of function */
3934 /* if (options.debug && currFunc) */
3936 debugFile->writeEndFunction (currFunc, ic, 1);
3939 if(_G.usefastretfie)
3940 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3942 pic16_emitpcodeNULLop(POC_RETFIE);
3944 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3946 _G.usefastretfie = 0;
3950 if (IFFUNC_ISCRITICAL(sym->type)) {
3951 pic16_emitcode("setb","ea");
3954 /* if debug then send end of function */
3956 debugFile->writeEndFunction (currFunc, ic, 1);
3959 /* insert code to restore stack frame, if user enabled it
3960 * and function is not main() */
3963 pic16_emitpcodeNULLop(POC_RETURN);
3965 /* Mark the end of a function */
3966 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3970 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3972 unsigned long lit=1;
3977 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3978 if(AOP_TYPE(op) == AOP_LIT) {
3979 if(!IS_FLOAT(operandType( op ))) {
3980 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3983 unsigned long lit_int;
3987 /* take care if literal is a float */
3988 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3993 if (AOP_TYPE(op) == AOP_LIT) {
3994 /* FIXME: broken for
3995 * char __at(0x456) foo;
3997 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3998 pic16_movLit2f(dest, (lit >> (8ul*offset)));
3999 } else if (AOP_TYPE(op) == AOP_PCODE
4000 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4001 /* char *s= "aaa"; return s; */
4002 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4003 * that the generic pointer is interpreted correctly
4004 * as referring to __code space, but this is fragile! */
4005 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4006 /* XXX: should check that dest != WREG */
4007 pic16_emitpcode(POC_MOVWF, dest);
4009 if(dest->type == PO_WREG && (offset == 0)) {
4010 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4013 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4017 /*-----------------------------------------------------------------*/
4018 /* genRet - generate code for return statement */
4019 /*-----------------------------------------------------------------*/
4020 static void genRet (iCode *ic)
4026 /* if we have no return value then
4027 * just generate the "ret" */
4032 /* we have something to return then
4033 * move the return value into place */
4034 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4035 size = AOP_SIZE(IC_LEFT(ic));
4039 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4042 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4045 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4047 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4050 /* >32-bits, setup stack and FSR0 */
4052 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4053 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4055 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4057 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4062 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4063 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4065 if(STACK_MODEL_LARGE) {
4066 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4067 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4069 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4074 /* old code, left here for reference -- VR */
4078 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4080 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4081 pic16_emitpcomment("push %s",l);
4084 DEBUGpic16_emitcode(";", "%d", __LINE__);
4085 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4086 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4088 if (strcmp(fReturn[offset],l)) {
4089 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4090 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4091 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4093 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4097 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4107 if (strcmp(fReturn[pushed],"a"))
4108 pic16_emitcode("pop",fReturn[pushed]);
4110 pic16_emitcode("pop","acc");
4116 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4119 /* generate a jump to the return label
4120 * if the next is not the return statement */
4121 if (!(ic->next && ic->next->op == LABEL
4122 && IC_LABEL(ic->next) == returnLabel)) {
4124 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4125 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4129 /*-----------------------------------------------------------------*/
4130 /* genLabel - generates a label */
4131 /*-----------------------------------------------------------------*/
4132 static void genLabel (iCode *ic)
4136 /* special case never generate */
4137 if (IC_LABEL(ic) == entryLabel)
4140 pic16_emitpLabel(IC_LABEL(ic)->key);
4141 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4144 /*-----------------------------------------------------------------*/
4145 /* genGoto - generates a goto */
4146 /*-----------------------------------------------------------------*/
4148 static void genGoto (iCode *ic)
4151 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4152 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4156 /*-----------------------------------------------------------------*/
4157 /* genMultbits :- multiplication of bits */
4158 /*-----------------------------------------------------------------*/
4159 static void genMultbits (operand *left,
4165 if(!pic16_sameRegs(AOP(result),AOP(right)))
4166 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4168 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4169 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4170 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4175 /*-----------------------------------------------------------------*/
4176 /* genMultOneByte : 8 bit multiplication & division */
4177 /*-----------------------------------------------------------------*/
4178 static void genMultOneByte (operand *left,
4184 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4185 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4187 /* (if two literals, the value is computed before) */
4188 /* if one literal, literal on the right */
4189 if (AOP_TYPE(left) == AOP_LIT){
4195 /* size is already checked in genMult == 1 */
4196 // size = AOP_SIZE(result);
4198 if (AOP_TYPE(right) == AOP_LIT){
4199 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4200 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4201 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4202 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4204 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4205 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4206 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4207 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210 pic16_genMult8X8_8 (left, right,result);
4213 /*-----------------------------------------------------------------*/
4214 /* genMultOneWord : 16 bit multiplication */
4215 /*-----------------------------------------------------------------*/
4216 static void genMultOneWord (operand *left,
4221 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4222 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4224 /* (if two literals, the value is computed before)
4225 * if one literal, literal on the right */
4226 if (AOP_TYPE(left) == AOP_LIT){
4232 /* size is checked already == 2 */
4233 // size = AOP_SIZE(result);
4235 if (AOP_TYPE(right) == AOP_LIT) {
4236 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4237 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4238 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4239 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4241 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4242 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4243 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4244 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4247 pic16_genMult16X16_16(left, right,result);
4250 /*-----------------------------------------------------------------*/
4251 /* genMultOneLong : 32 bit multiplication */
4252 /*-----------------------------------------------------------------*/
4253 static void genMultOneLong (operand *left,
4258 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4259 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4261 /* (if two literals, the value is computed before)
4262 * if one literal, literal on the right */
4263 if (AOP_TYPE(left) == AOP_LIT){
4269 /* size is checked already == 4 */
4270 // size = AOP_SIZE(result);
4272 if (AOP_TYPE(right) == AOP_LIT) {
4273 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4274 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4275 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4276 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4278 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4279 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4280 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4281 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4284 pic16_genMult32X32_32(left, right,result);
4289 /*-----------------------------------------------------------------*/
4290 /* genMult - generates code for multiplication */
4291 /*-----------------------------------------------------------------*/
4292 static void genMult (iCode *ic)
4294 operand *left = IC_LEFT(ic);
4295 operand *right = IC_RIGHT(ic);
4296 operand *result= IC_RESULT(ic);
4299 /* assign the amsops */
4300 pic16_aopOp (left,ic,FALSE);
4301 pic16_aopOp (right,ic,FALSE);
4302 pic16_aopOp (result,ic,TRUE);
4304 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4306 /* special cases first *
4308 if (AOP_TYPE(left) == AOP_CRY
4309 && AOP_TYPE(right)== AOP_CRY) {
4310 genMultbits(left,right,result);
4314 /* if both are of size == 1 */
4315 if(AOP_SIZE(left) == 1
4316 && AOP_SIZE(right) == 1) {
4317 genMultOneByte(left,right,result);
4321 /* if both are of size == 2 */
4322 if(AOP_SIZE(left) == 2
4323 && AOP_SIZE(right) == 2) {
4324 genMultOneWord(left, right, result);
4328 /* if both are of size == 4 */
4329 if(AOP_SIZE(left) == 4
4330 && AOP_SIZE(right) == 4) {
4331 genMultOneLong(left, right, result);
4335 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4338 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4339 /* should have been converted to function call */
4343 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4344 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4345 pic16_freeAsmop(result,NULL,ic,TRUE);
4348 /*-----------------------------------------------------------------*/
4349 /* genDivbits :- division of bits */
4350 /*-----------------------------------------------------------------*/
4351 static void genDivbits (operand *left,
4358 /* the result must be bit */
4359 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4360 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4364 pic16_emitcode("div","ab");
4365 pic16_emitcode("rrc","a");
4366 pic16_aopPut(AOP(result),"c",0);
4369 /*-----------------------------------------------------------------*/
4370 /* genDivOneByte : 8 bit division */
4371 /*-----------------------------------------------------------------*/
4372 static void genDivOneByte (operand *left,
4376 sym_link *opetype = operandType(result);
4381 /* result = divident / divisor
4382 * - divident may be a register or a literal,
4383 * - divisor may be a register or a literal,
4384 * so there are 3 cases (literal / literal is optimized
4385 * by the front-end) to handle.
4386 * In addition we must handle signed and unsigned, which
4387 * result in 6 final different cases -- VR */
4391 size = AOP_SIZE(result) - 1;
4393 /* signed or unsigned */
4394 if (SPEC_USIGN(opetype)) {
4395 pCodeOp *pct1, /* count */
4398 symbol *label1, *label2, *label3;;
4401 /* unsigned is easy */
4403 pct1 = pic16_popGetTempReg(1);
4404 pct2 = pic16_popGetTempReg(1);
4405 pct3 = pic16_popGetTempReg(1);
4407 label1 = newiTempLabel(NULL);
4408 label2 = newiTempLabel(NULL);
4409 label3 = newiTempLabel(NULL);
4411 /* the following algorithm is extracted from divuint.c */
4413 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4414 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4416 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4420 pic16_emitpLabel(label1->key);
4423 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4427 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4431 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4433 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4434 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4436 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4437 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4438 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4440 pic16_emitpLabel( label3->key );
4441 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4442 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4446 pic16_emitpLabel(label2->key);
4447 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4448 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4449 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4451 /* result is in wreg */
4452 if(AOP_TYPE(result) != AOP_ACC)
4453 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4455 pic16_popReleaseTempReg( pct3, 1);
4456 pic16_popReleaseTempReg( pct2, 1);
4457 pic16_popReleaseTempReg( pct1, 1);
4462 /* signed is a little bit more difficult */
4464 /* save the signs of the operands */
4465 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4467 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4468 pic16_emitcode("push","acc"); /* save it on the stack */
4470 /* now sign adjust for both left & right */
4471 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4473 lbl = newiTempLabel(NULL);
4474 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4475 pic16_emitcode("cpl","a");
4476 pic16_emitcode("inc","a");
4477 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4478 pic16_emitcode("mov","b,a");
4480 /* sign adjust left side */
4481 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4484 lbl = newiTempLabel(NULL);
4485 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4486 pic16_emitcode("cpl","a");
4487 pic16_emitcode("inc","a");
4488 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4490 /* now the division */
4491 pic16_emitcode("div","ab");
4492 /* we are interested in the lower order
4494 pic16_emitcode("mov","b,a");
4495 lbl = newiTempLabel(NULL);
4496 pic16_emitcode("pop","acc");
4497 /* if there was an over flow we don't
4498 adjust the sign of the result */
4499 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4500 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4502 pic16_emitcode("clr","a");
4503 pic16_emitcode("subb","a,b");
4504 pic16_emitcode("mov","b,a");
4505 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4507 /* now we are done */
4508 pic16_aopPut(AOP(result),"b",0);
4510 pic16_emitcode("mov","c,b.7");
4511 pic16_emitcode("subb","a,acc");
4514 pic16_aopPut(AOP(result),"a",offset++);
4518 /*-----------------------------------------------------------------*/
4519 /* genDiv - generates code for division */
4520 /*-----------------------------------------------------------------*/
4521 static void genDiv (iCode *ic)
4523 operand *left = IC_LEFT(ic);
4524 operand *right = IC_RIGHT(ic);
4525 operand *result= IC_RESULT(ic);
4528 /* Division is a very lengthy algorithm, so it is better
4529 * to call support routines than inlining algorithm.
4530 * Division functions written here just in case someone
4531 * wants to inline and not use the support libraries -- VR */
4535 /* assign the amsops */
4536 pic16_aopOp (left,ic,FALSE);
4537 pic16_aopOp (right,ic,FALSE);
4538 pic16_aopOp (result,ic,TRUE);
4540 /* special cases first */
4542 if (AOP_TYPE(left) == AOP_CRY &&
4543 AOP_TYPE(right)== AOP_CRY) {
4544 genDivbits(left,right,result);
4548 /* if both are of size == 1 */
4549 if (AOP_SIZE(left) == 1 &&
4550 AOP_SIZE(right) == 1 ) {
4551 genDivOneByte(left,right,result);
4555 /* should have been converted to function call */
4558 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4559 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4560 pic16_freeAsmop(result,NULL,ic,TRUE);
4563 /*-----------------------------------------------------------------*/
4564 /* genModbits :- modulus of bits */
4565 /*-----------------------------------------------------------------*/
4566 static void genModbits (operand *left,
4574 werror(W_POSSBUG2, __FILE__, __LINE__);
4575 /* the result must be bit */
4576 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4577 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4581 pic16_emitcode("div","ab");
4582 pic16_emitcode("mov","a,b");
4583 pic16_emitcode("rrc","a");
4584 pic16_aopPut(AOP(result),"c",0);
4587 /*-----------------------------------------------------------------*/
4588 /* genModOneByte : 8 bit modulus */
4589 /*-----------------------------------------------------------------*/
4590 static void genModOneByte (operand *left,
4594 sym_link *opetype = operandType(result);
4599 werror(W_POSSBUG2, __FILE__, __LINE__);
4601 /* signed or unsigned */
4602 if (SPEC_USIGN(opetype)) {
4603 /* unsigned is easy */
4604 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4605 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4607 pic16_emitcode("div","ab");
4608 pic16_aopPut(AOP(result),"b",0);
4612 /* signed is a little bit more difficult */
4614 /* save the signs of the operands */
4615 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4618 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4619 pic16_emitcode("push","acc"); /* save it on the stack */
4621 /* now sign adjust for both left & right */
4622 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4625 lbl = newiTempLabel(NULL);
4626 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4627 pic16_emitcode("cpl","a");
4628 pic16_emitcode("inc","a");
4629 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4630 pic16_emitcode("mov","b,a");
4632 /* sign adjust left side */
4633 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4636 lbl = newiTempLabel(NULL);
4637 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4638 pic16_emitcode("cpl","a");
4639 pic16_emitcode("inc","a");
4640 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4642 /* now the multiplication */
4643 pic16_emitcode("div","ab");
4644 /* we are interested in the lower order
4646 lbl = newiTempLabel(NULL);
4647 pic16_emitcode("pop","acc");
4648 /* if there was an over flow we don't
4649 adjust the sign of the result */
4650 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4651 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4653 pic16_emitcode("clr","a");
4654 pic16_emitcode("subb","a,b");
4655 pic16_emitcode("mov","b,a");
4656 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4658 /* now we are done */
4659 pic16_aopPut(AOP(result),"b",0);
4663 /*-----------------------------------------------------------------*/
4664 /* genMod - generates code for division */
4665 /*-----------------------------------------------------------------*/
4666 static void genMod (iCode *ic)
4668 operand *left = IC_LEFT(ic);
4669 operand *right = IC_RIGHT(ic);
4670 operand *result= IC_RESULT(ic);
4674 /* assign the amsops */
4675 pic16_aopOp (left,ic,FALSE);
4676 pic16_aopOp (right,ic,FALSE);
4677 pic16_aopOp (result,ic,TRUE);
4679 /* special cases first */
4681 if (AOP_TYPE(left) == AOP_CRY &&
4682 AOP_TYPE(right)== AOP_CRY) {
4683 genModbits(left,right,result);
4687 /* if both are of size == 1 */
4688 if (AOP_SIZE(left) == 1 &&
4689 AOP_SIZE(right) == 1 ) {
4690 genModOneByte(left,right,result);
4694 /* should have been converted to function call */
4698 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4700 pic16_freeAsmop(result,NULL,ic,TRUE);
4703 /*-----------------------------------------------------------------*/
4704 /* genIfxJump :- will create a jump depending on the ifx */
4705 /*-----------------------------------------------------------------*/
4707 note: May need to add parameter to indicate when a variable is in bit space.
4709 static void genIfxJump (iCode *ic, char *jval)
4713 /* if true label then we jump if condition
4715 if ( IC_TRUE(ic) ) {
4717 if(strcmp(jval,"a") == 0)
4719 else if (strcmp(jval,"c") == 0)
4722 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4723 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4726 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4727 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4731 /* false label is present */
4732 if(strcmp(jval,"a") == 0)
4734 else if (strcmp(jval,"c") == 0)
4737 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4738 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4741 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4742 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4747 /* mark the icode as generated */
4751 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4755 /* if true label then we jump if condition
4757 if ( IC_TRUE(ic) ) {
4758 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4759 pic16_emitpcode(POC_BTFSC, jop);
4761 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4762 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4765 /* false label is present */
4766 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4767 pic16_emitpcode(POC_BTFSS, jop);
4769 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4770 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4774 /* mark the icode as generated */
4781 /*-----------------------------------------------------------------*/
4783 /*-----------------------------------------------------------------*/
4784 static void genSkip(iCode *ifx,int status_bit)
4786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4790 if ( IC_TRUE(ifx) ) {
4791 switch(status_bit) {
4806 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4807 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4811 switch(status_bit) {
4825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4826 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4833 /*-----------------------------------------------------------------*/
4835 /*-----------------------------------------------------------------*/
4836 static void genSkipc(resolvedIfx *rifx)
4838 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4848 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4849 rifx->generated = 1;
4852 #if !(USE_SIMPLE_GENCMP)
4853 /*-----------------------------------------------------------------*/
4855 /*-----------------------------------------------------------------*/
4856 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4858 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4863 if( (rifx->condition ^ invert_condition) & 1)
4868 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4869 rifx->generated = 1;
4874 /*-----------------------------------------------------------------*/
4876 /*-----------------------------------------------------------------*/
4877 static void genSkipz(iCode *ifx, int condition)
4888 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4890 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4893 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4895 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4900 #if !(USE_SIMPLE_GENCMP)
4901 /*-----------------------------------------------------------------*/
4903 /*-----------------------------------------------------------------*/
4904 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4910 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4912 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4915 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4916 rifx->generated = 1;
4921 /*-----------------------------------------------------------------*/
4922 /* genChkZeroes :- greater or less than comparison */
4923 /* For each byte in a literal that is zero, inclusive or the */
4924 /* the corresponding byte in the operand with W */
4925 /* returns true if any of the bytes are zero */
4926 /*-----------------------------------------------------------------*/
4927 static int genChkZeroes(operand *op, int lit, int size)
4934 i = (lit >> (size*8)) & 0xff;
4938 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4940 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4950 /*-----------------------------------------------------------------*/
4951 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4952 /* aop (if it's NOT a literal) or from lit (if */
4953 /* aop is a literal) */
4954 /*-----------------------------------------------------------------*/
4955 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4956 if (aop->type == AOP_LIT) {
4957 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4959 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4963 /*-----------------------------------------------------------------*/
4964 /* genCmp :- greater or less than comparison */
4965 /*-----------------------------------------------------------------*/
4967 #if USE_SIMPLE_GENCMP /* { */
4969 /* genCmp performs a left < right comparison, stores
4970 * the outcome in result (if != NULL) and generates
4971 * control flow code for the ifx (if != NULL).
4973 * This version leaves in sequences like
4974 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4975 * which should be optmized by the peephole
4976 * optimizer - RN 2005-01-01 */
4977 static void genCmp (operand *left,operand *right,
4978 operand *result, iCode *ifx, int sign)
4991 assert (left && right);
4992 assert (AOP_SIZE(left) == AOP_SIZE(right));
4994 size = AOP_SIZE(right) - 1;
4995 mask = (0x100UL << (size*8)) - 1;
4996 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5001 resolveIfx (&rIfx, ifx);
5003 /* handle for special cases */
5004 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5007 /**********************************************************************
5008 * handle bits - bit compares are promoted to int compares seemingly! *
5009 **********************************************************************/
5011 // THIS IS COMPLETELY UNTESTED!
5012 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5013 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5014 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5015 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5018 // 1 < {0,1} is false --> clear C by skipping the next instruction
5019 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5020 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5021 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5022 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5023 emitCLRC; // only skipped for left=0 && right=1
5025 goto correct_result_in_carry;
5029 /*************************************************
5030 * make sure that left is register (or the like) *
5031 *************************************************/
5032 if (!isAOP_REGlike(left)) {
5033 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5034 assert (isAOP_LIT(left));
5035 assert (isAOP_REGlike(right));
5036 // swap left and right
5037 // left < right <==> right > left <==> (right >= left + 1)
5038 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5040 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5041 // MAXVALUE < right? always false
5042 if (performedLt) emitCLRC; else emitSETC;
5043 goto correct_result_in_carry;
5046 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5047 // that's why we handled it above.
5054 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5055 } else if (isAOP_LIT(right)) {
5056 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5059 assert (isAOP_REGlike(left)); // left must be register or the like
5060 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5062 /*************************************************
5063 * special cases go here *
5064 *************************************************/
5066 if (isAOP_LIT(right)) {
5068 // unsigned comparison to a literal
5069 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5071 // unsigned left < 0? always false
5072 if (performedLt) emitCLRC; else emitSETC;
5073 goto correct_result_in_carry;
5076 // signed comparison to a literal
5077 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5078 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5079 // signed left < 0x80000000? always false
5080 if (performedLt) emitCLRC; else emitSETC;
5081 goto correct_result_in_carry;
5082 } else if (lit == 0) {
5083 // compare left < 0; set CARRY if SIGNBIT(left) is set
5084 if (performedLt) emitSETC; else emitCLRC;
5085 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5086 if (performedLt) emitCLRC; else emitSETC;
5087 goto correct_result_in_carry;
5090 } // right is literal
5092 /*************************************************
5093 * perform a general case comparison *
5094 * make sure we get CARRY==1 <==> left >= right *
5095 *************************************************/
5096 // compare most significant bytes
5097 //DEBUGpc ("comparing bytes at offset %d", size);
5099 // unsigned comparison
5100 mov2w_regOrLit (AOP(right), lit, size);
5101 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5103 // signed comparison
5104 // (add 2^n to both operands then perform an unsigned comparison)
5105 if (isAOP_LIT(right)) {
5106 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5107 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5109 if (litbyte == 0x80) {
5110 // left >= 0x80 -- always true, but more bytes to come
5111 pic16_mov2w (AOP(left), size);
5112 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5115 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5116 pic16_mov2w (AOP(left), size);
5117 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5118 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5121 /* using PRODL as a temporary register here */
5122 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5123 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5124 pic16_mov2w (AOP(left), size);
5125 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5126 pic16_emitpcode (POC_MOVWF, pctemp);
5127 pic16_mov2w (AOP(right), size);
5128 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5129 pic16_emitpcode (POC_SUBFW, pctemp);
5130 //pic16_popReleaseTempReg(pctemp, 1);
5134 // compare remaining bytes (treat as unsigned case from above)
5135 templbl = newiTempLabel ( NULL );
5138 //DEBUGpc ("comparing bytes at offset %d", offs);
5139 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5140 mov2w_regOrLit (AOP(right), lit, offs);
5141 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5143 pic16_emitpLabel (templbl->key);
5144 goto result_in_carry;
5148 /****************************************************
5149 * now CARRY contains the result of the comparison: *
5150 * SUBWF sets CARRY iff *
5151 * F-W >= 0 <==> F >= W <==> !(F < W) *
5152 * (F=left, W=right) *
5153 ****************************************************/
5156 if (result && AOP_TYPE(result) != AOP_CRY) {
5157 // value will be stored
5160 // value wil only be used in the following genSkipc()
5161 rIfx.condition ^= 1;
5165 correct_result_in_carry:
5167 // assign result to variable (if neccessary)
5168 if (result && AOP_TYPE(result) != AOP_CRY) {
5169 //DEBUGpc ("assign result");
5170 size = AOP_SIZE(result);
5172 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5174 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5177 // perform conditional jump
5179 //DEBUGpc ("generate control flow");
5188 static void genCmp (operand *left,operand *right,
5189 operand *result, iCode *ifx, int sign)
5191 int size; //, offset = 0 ;
5192 unsigned long lit = 0L,i = 0;
5193 resolvedIfx rFalseIfx;
5194 // resolvedIfx rTrueIfx;
5196 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5199 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5200 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5206 resolveIfx(&rFalseIfx,ifx);
5207 truelbl = newiTempLabel(NULL);
5208 size = max(AOP_SIZE(left),AOP_SIZE(right));
5210 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5214 /* if literal is on the right then swap with left */
5215 if ((AOP_TYPE(right) == AOP_LIT)) {
5216 operand *tmp = right ;
5217 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5218 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5221 lit = (lit - 1) & mask;
5224 rFalseIfx.condition ^= 1;
5227 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5228 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5232 //if(IC_TRUE(ifx) == NULL)
5233 /* if left & right are bit variables */
5234 if (AOP_TYPE(left) == AOP_CRY &&
5235 AOP_TYPE(right) == AOP_CRY ) {
5236 assert (0 && "bit variables used in genCmp");
5237 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5238 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5240 /* subtract right from left if at the
5241 end the carry flag is set then we know that
5242 left is greater than right */
5244 symbol *lbl = newiTempLabel(NULL);
5247 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5248 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5252 if(AOP_TYPE(right) == AOP_LIT) {
5254 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5256 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5263 genSkipCond(&rFalseIfx,left,size-1,7);
5265 /* no need to compare to 0...*/
5266 /* NOTE: this is a de-generate compare that most certainly
5267 * creates some dead code. */
5268 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5270 if(ifx) ifx->generated = 1;
5277 //i = (lit >> (size*8)) & 0xff;
5278 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5280 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5282 i = ((0-lit) & 0xff);
5285 /* lit is 0x7f, all signed chars are less than
5286 * this except for 0x7f itself */
5287 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5288 genSkipz2(&rFalseIfx,0);
5290 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5291 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5292 genSkipc(&rFalseIfx);
5297 genSkipz2(&rFalseIfx,1);
5299 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5300 genSkipc(&rFalseIfx);
5304 if(ifx) ifx->generated = 1;
5308 /* chars are out of the way. now do ints and longs */
5311 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5318 genSkipCond(&rFalseIfx,left,size,7);
5319 if(ifx) ifx->generated = 1;
5324 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5326 //rFalseIfx.condition ^= 1;
5327 //genSkipCond(&rFalseIfx,left,size,7);
5328 //rFalseIfx.condition ^= 1;
5330 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5331 if(rFalseIfx.condition)
5332 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5334 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5336 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5337 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5338 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5341 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5343 if(rFalseIfx.condition) {
5345 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5351 genSkipc(&rFalseIfx);
5352 pic16_emitpLabel(truelbl->key);
5353 if(ifx) ifx->generated = 1;
5360 if( (lit & 0xff) == 0) {
5361 /* lower byte is zero */
5362 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5363 i = ((lit >> 8) & 0xff) ^0x80;
5364 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5365 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5366 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5367 genSkipc(&rFalseIfx);
5370 if(ifx) ifx->generated = 1;
5375 /* Special cases for signed longs */
5376 if( (lit & 0xffffff) == 0) {
5377 /* lower byte is zero */
5378 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5379 i = ((lit >> 8*3) & 0xff) ^0x80;
5380 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5381 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5382 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5383 genSkipc(&rFalseIfx);
5386 if(ifx) ifx->generated = 1;
5394 if(lit & (0x80 << (size*8))) {
5395 /* lit is negative */
5396 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5398 //genSkipCond(&rFalseIfx,left,size,7);
5400 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5402 if(rFalseIfx.condition)
5403 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5405 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5409 /* lit is positive */
5410 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5411 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5412 if(rFalseIfx.condition)
5413 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5415 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5420 This works, but is only good for ints.
5421 It also requires a "known zero" register.
5422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5423 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5424 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5425 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5426 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5427 genSkipc(&rFalseIfx);
5429 pic16_emitpLabel(truelbl->key);
5430 if(ifx) ifx->generated = 1;
5434 /* There are no more special cases, so perform a general compare */
5436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5437 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5443 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5445 //rFalseIfx.condition ^= 1;
5446 genSkipc(&rFalseIfx);
5448 pic16_emitpLabel(truelbl->key);
5450 if(ifx) ifx->generated = 1;
5457 /* sign is out of the way. So now do an unsigned compare */
5458 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5461 /* General case - compare to an unsigned literal on the right.*/
5463 i = (lit >> (size*8)) & 0xff;
5464 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5465 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5467 i = (lit >> (size*8)) & 0xff;
5470 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5472 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5474 /* this byte of the lit is zero,
5475 *if it's not the last then OR in the variable */
5477 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5482 pic16_emitpLabel(lbl->key);
5483 // pic16_emitpLabel(truelbl->key);
5484 //if(emitFinalCheck)
5485 genSkipc(&rFalseIfx);
5487 pic16_emitpLabel(truelbl->key);
5489 if(ifx) ifx->generated = 1;
5496 if(AOP_TYPE(left) == AOP_LIT) {
5497 //symbol *lbl = newiTempLabel(NULL);
5499 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5502 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5505 if((lit == 0) && (sign == 0)){
5508 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5510 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5512 genSkipz2(&rFalseIfx,0);
5513 if(ifx) ifx->generated = 1;
5520 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5521 /* degenerate compare can never be true */
5522 if(rFalseIfx.condition == 0)
5523 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5525 if(ifx) ifx->generated = 1;
5530 /* signed comparisons to a literal byte */
5532 int lp1 = (lit+1) & 0xff;
5534 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5537 rFalseIfx.condition ^= 1;
5538 genSkipCond(&rFalseIfx,right,0,7);
5541 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5542 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5543 genSkipz2(&rFalseIfx,1);
5546 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5548 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5549 rFalseIfx.condition ^= 1;
5550 genSkipc(&rFalseIfx);
5554 /* unsigned comparisons to a literal byte */
5556 switch(lit & 0xff ) {
5558 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5559 genSkipz2(&rFalseIfx,0);
5562 rFalseIfx.condition ^= 1;
5563 genSkipCond(&rFalseIfx,right,0,7);
5567 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5568 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5569 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5570 rFalseIfx.condition ^= 1;
5571 if (AOP_TYPE(result) == AOP_CRY)
5572 genSkipc(&rFalseIfx);
5574 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5575 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5581 if(ifx) ifx->generated = 1;
5582 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5588 /* Size is greater than 1 */
5596 /* this means lit = 0xffffffff, or -1 */
5599 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5600 rFalseIfx.condition ^= 1;
5601 genSkipCond(&rFalseIfx,right,size,7);
5602 if(ifx) ifx->generated = 1;
5604 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5613 if(rFalseIfx.condition) {
5614 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5615 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5618 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5620 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5624 if(rFalseIfx.condition) {
5625 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5626 pic16_emitpLabel(truelbl->key);
5628 rFalseIfx.condition ^= 1;
5629 genSkipCond(&rFalseIfx,right,s,7);
5632 if(ifx) ifx->generated = 1;
5634 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5640 if((size == 1) && (0 == (lp1&0xff))) {
5641 /* lower byte of signed word is zero */
5642 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5643 i = ((lp1 >> 8) & 0xff) ^0x80;
5644 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5645 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5646 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5648 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5650 if(ifx) ifx->generated = 1;
5653 rFalseIfx.condition ^= 1;
5654 genSkipc(&rFalseIfx);
5655 if(ifx) ifx->generated = 1;
5661 if(lit & (0x80 << (size*8))) {
5662 /* Lit is less than zero */
5663 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5664 //rFalseIfx.condition ^= 1;
5665 //genSkipCond(&rFalseIfx,left,size,7);
5666 //rFalseIfx.condition ^= 1;
5667 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5668 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5670 if(rFalseIfx.condition)
5671 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5673 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5677 /* Lit is greater than or equal to zero */
5678 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5679 //rFalseIfx.condition ^= 1;
5680 //genSkipCond(&rFalseIfx,right,size,7);
5681 //rFalseIfx.condition ^= 1;
5683 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5684 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5686 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5687 if(rFalseIfx.condition)
5688 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5690 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5694 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5695 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5701 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5703 rFalseIfx.condition ^= 1;
5704 //rFalseIfx.condition = 1;
5705 genSkipc(&rFalseIfx);
5707 pic16_emitpLabel(truelbl->key);
5709 if(ifx) ifx->generated = 1;
5712 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5719 /* compare word or long to an unsigned literal on the right.*/
5724 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5727 break; /* handled above */
5730 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5732 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5733 genSkipz2(&rFalseIfx,0);
5737 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5739 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742 if(rFalseIfx.condition)
5743 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5745 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5748 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5749 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5751 rFalseIfx.condition ^= 1;
5752 genSkipc(&rFalseIfx);
5755 pic16_emitpLabel(truelbl->key);
5757 if(ifx) ifx->generated = 1;
5759 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5767 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5768 i = (lit >> (size*8)) & 0xff;
5770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5771 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5774 i = (lit >> (size*8)) & 0xff;
5777 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5779 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5781 /* this byte of the lit is zero,
5782 * if it's not the last then OR in the variable */
5784 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5789 pic16_emitpLabel(lbl->key);
5791 rFalseIfx.condition ^= 1;
5793 genSkipc(&rFalseIfx);
5797 pic16_emitpLabel(truelbl->key);
5798 if(ifx) ifx->generated = 1;
5800 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5806 /* Compare two variables */
5808 DEBUGpic16_emitcode(";sign","%d",sign);
5812 /* Sigh. thus sucks... */
5816 pctemp = pic16_popGetTempReg(1);
5817 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5818 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5819 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5820 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5822 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5823 pic16_popReleaseTempReg(pctemp, 1);
5825 /* Signed char comparison */
5826 /* Special thanks to Nikolai Golovchenko for this snippet */
5827 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5828 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5829 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5830 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5831 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5832 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5835 genSkipc(&rFalseIfx);
5837 if(ifx) ifx->generated = 1;
5839 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5847 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5848 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5852 /* The rest of the bytes of a multi-byte compare */
5856 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5859 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5860 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5865 pic16_emitpLabel(lbl->key);
5867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5868 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5869 (AOP_TYPE(result) == AOP_REG)) {
5870 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5871 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5873 genSkipc(&rFalseIfx);
5875 //genSkipc(&rFalseIfx);
5876 if(ifx) ifx->generated = 1;
5879 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5887 if ((AOP_TYPE(result) != AOP_CRY)
5888 && AOP_SIZE(result)) {
5889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5891 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5893 pic16_outBitC(result);
5895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5896 /* if the result is used in the next
5897 ifx conditional branch then generate
5898 code a little differently */
5900 genIfxJump (ifx,"c");
5902 pic16_outBitC(result);
5903 /* leave the result in acc */
5908 #elif 0 /* VR version of genCmp() */ /* } else { */
5910 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5911 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5912 operand *result, int offset, int invert_op)
5916 /* check condition, > or < ?? */
5917 if(rIfx->condition != 0)invert_op ^= 1;
5919 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5921 if(!ifx)invert_op ^= 1;
5923 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5924 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5927 if(!invert_op)return POC_CPFSGT;
5928 else return POC_CPFSLT;
5931 static int compareAopfirstpass=1;
5933 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5934 operand *oper, int offset, operand *result,
5935 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5941 /* invert if there is a result to be loaded, in order to fit,
5942 * SETC/CLRC sequence */
5943 if(AOP_SIZE(result))invert_op ^= 1;
5945 // if(sign && !offset)invert_op ^= 1;
5947 // if(sign)invert_op ^= 1;
5949 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5951 if(AOP_SIZE(result) && compareAopfirstpass) {
5954 pic16_emitpcode(POC_SETF, pcop2);
5959 pic16_emitpcode(POC_CLRF, pcop2);
5965 compareAopfirstpass = 0;
5967 /* there is a bug when comparing operands with size > 1,
5968 * because higher bytes can be equal and test should be performed
5969 * to the next lower byte, current algorithm, considers operands
5970 * inequal in these cases! -- VR 20041107 */
5974 pic16_emitpcode(op, pcop);
5976 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5979 if((!sign || !offset) && AOP_SIZE(result)) {
5982 pic16_emitpcode(POC_CLRF, pcop2);
5987 pic16_emitpcode(POC_SETF, pcop2);
5992 /* don't emit final branch (offset == 0) */
5996 pic16_emitpcode(POC_RRCF, pcop2);
5998 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6001 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6002 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6003 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6005 truelbl = newiTempLabel( NULL );
6006 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6007 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6008 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6010 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6011 pic16_emitpLabel(truelbl->key);
6013 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6018 static void genCmp (operand *left, operand *right,
6019 operand *result, iCode *ifx, int sign)
6023 resolvedIfx rFalseIfx;
6024 symbol *falselbl, *tlbl;
6028 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6030 resolveIfx(&rFalseIfx, ifx);
6031 size = max(AOP_SIZE(left), AOP_SIZE(right));
6033 /* if left & right are bit variables */
6034 if(AOP_TYPE(left) == AOP_CRY
6035 && AOP_TYPE(right) == AOP_CRY ) {
6037 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6038 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6040 werror(W_POSSBUG2, __FILE__, __LINE__);
6044 /* if literal is on the right then swap with left */
6045 if((AOP_TYPE(right) == AOP_LIT)) {
6046 operand *tmp = right ;
6047 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6049 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6051 // lit = (lit - 1) & mask;
6054 rFalseIfx.condition ^= 1; /* reverse compare */
6056 if ((AOP_TYPE(left) == AOP_LIT)) {
6057 /* float compares are handled by support functions */
6058 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6061 /* actual comparing algorithm */
6062 // size = AOP_SIZE( right );
6064 falselbl = newiTempLabel( NULL );
6065 if(AOP_TYPE(left) == AOP_LIT) {
6066 /* compare to literal */
6067 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6070 pCodeOp *pct, *pct2;
6073 /* signed compare */
6074 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6076 /* using PRODL:PRODH as a temporary register here */
6077 pct = pic16_popCopyReg(&pic16_pc_prodl);
6078 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6079 tlbl = newiTempLabel( NULL );
6081 /* first compare signs:
6082 * a. if both are positive, compare just like unsigned
6083 * b. if both are negative, invert cmpop, compare just like unsigned
6084 * c. if different signs, determine the result directly */
6090 tlbl1 = newiTempLabel( NULL );
6091 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6095 /* literal is zero or positive:
6096 * a. if carry is zero, too, continue compare,
6097 * b. if carry is set, then continue depending on cmpop ^ condition:
6098 * 1. '<' return false (literal < variable),
6099 * 2. '>' return true (literal > variable) */
6100 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6101 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6104 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6105 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6109 /* literal is negative:
6110 * a. if carry is set, too, continue compare,
6111 * b. if carry is zero, then continue depending on cmpop ^ condition:
6112 * 1. '<' return true (literal < variable),
6113 * 2. '>' return false (literal > variable) */
6114 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6115 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6117 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6118 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6123 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6125 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6126 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6131 pic16_emitpLabel( tlbl1->key );
6134 compareAopfirstpass=1;
6135 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6136 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6137 // pic16_emitpcode(POC_MOVWF, pct);
6139 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6140 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6141 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6142 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6146 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6147 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6148 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6149 // pic16_emitpcode(POC_MOVWF, pct);
6151 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6152 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6153 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6154 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6155 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6158 if(ifx)ifx->generated = 1;
6160 if(AOP_SIZE(result)) {
6161 pic16_emitpLabel(tlbl->key);
6162 pic16_emitpLabel(falselbl->key);
6163 pic16_outBitOp( result, pct2 );
6165 pic16_emitpLabel(tlbl->key);
6169 /* unsigned compare */
6170 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6172 compareAopfirstpass=1;
6175 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6176 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6179 if(ifx)ifx->generated = 1;
6181 if(AOP_SIZE(result)) {
6182 pic16_emitpLabel(falselbl->key);
6183 pic16_outBitC( result );
6188 /* compare registers */
6189 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6193 pCodeOp *pct, *pct2;
6195 /* signed compare */
6196 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6198 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6199 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6200 tlbl = newiTempLabel( NULL );
6202 compareAopfirstpass=1;
6205 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6206 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6207 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6208 pic16_emitpcode(POC_MOVWF, pct);
6210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6211 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214 /* WREG already holds left + 0x80 */
6215 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6219 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6220 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6221 pic16_emitpcode(POC_MOVWF, pct);
6223 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6224 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6225 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6227 /* WREG already holds left + 0x80 */
6228 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6229 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6232 if(ifx)ifx->generated = 1;
6234 if(AOP_SIZE(result)) {
6235 pic16_emitpLabel(tlbl->key);
6236 pic16_emitpLabel(falselbl->key);
6237 pic16_outBitOp( result, pct2 );
6239 pic16_emitpLabel(tlbl->key);
6243 /* unsigned compare */
6244 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6246 compareAopfirstpass=1;
6249 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6250 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6254 if(ifx)ifx->generated = 1;
6255 if(AOP_SIZE(result)) {
6257 pic16_emitpLabel(falselbl->key);
6258 pic16_outBitC( result );
6269 /*-----------------------------------------------------------------*/
6270 /* genCmpGt :- greater than comparison */
6271 /*-----------------------------------------------------------------*/
6272 static void genCmpGt (iCode *ic, iCode *ifx)
6274 operand *left, *right, *result;
6275 sym_link *letype , *retype;
6281 right= IC_RIGHT(ic);
6282 result = IC_RESULT(ic);
6284 letype = getSpec(operandType(left));
6285 retype =getSpec(operandType(right));
6286 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6287 /* assign the amsops */
6288 pic16_aopOp (left,ic,FALSE);
6289 pic16_aopOp (right,ic,FALSE);
6290 pic16_aopOp (result,ic,TRUE);
6292 genCmp(right, left, result, ifx, sign);
6294 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296 pic16_freeAsmop(result,NULL,ic,TRUE);
6299 /*-----------------------------------------------------------------*/
6300 /* genCmpLt - less than comparisons */
6301 /*-----------------------------------------------------------------*/
6302 static void genCmpLt (iCode *ic, iCode *ifx)
6304 operand *left, *right, *result;
6305 sym_link *letype , *retype;
6311 right= IC_RIGHT(ic);
6312 result = IC_RESULT(ic);
6314 letype = getSpec(operandType(left));
6315 retype =getSpec(operandType(right));
6316 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6318 /* assign the amsops */
6319 pic16_aopOp (left,ic,FALSE);
6320 pic16_aopOp (right,ic,FALSE);
6321 pic16_aopOp (result,ic,TRUE);
6323 genCmp(left, right, result, ifx, sign);
6325 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6327 pic16_freeAsmop(result,NULL,ic,TRUE);
6332 // FIXME reenable literal optimisation when the pic16 port is stable
6334 /*-----------------------------------------------------------------*/
6335 /* genc16bit2lit - compare a 16 bit value to a literal */
6336 /*-----------------------------------------------------------------*/
6337 static void genc16bit2lit(operand *op, int lit, int offset)
6341 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6342 if( (lit&0xff) == 0)
6347 switch( BYTEofLONG(lit,i)) {
6349 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6352 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6355 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6358 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6364 switch( BYTEofLONG(lit,i)) {
6366 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6370 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6374 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6377 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6379 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6388 /*-----------------------------------------------------------------*/
6389 /* gencjneshort - compare and jump if not equal */
6390 /*-----------------------------------------------------------------*/
6391 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6393 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6395 int res_offset = 0; /* the result may be a different size then left or right */
6396 int res_size = AOP_SIZE(result);
6398 symbol *lbl, *lbl_done;
6400 unsigned long lit = 0L;
6401 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6404 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6406 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6407 resolveIfx(&rIfx,ifx);
6408 lbl = newiTempLabel(NULL);
6409 lbl_done = newiTempLabel(NULL);
6412 /* if the left side is a literal or
6413 if the right is in a pointer register and left
6415 if ((AOP_TYPE(left) == AOP_LIT) ||
6416 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6421 if(AOP_TYPE(right) == AOP_LIT)
6422 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6424 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6425 preserve_result = 1;
6427 if(result && !preserve_result)
6430 for(i = 0; i < AOP_SIZE(result); i++)
6431 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6435 /* if the right side is a literal then anything goes */
6436 if (AOP_TYPE(right) == AOP_LIT &&
6437 AOP_TYPE(left) != AOP_DIR ) {
6440 genc16bit2lit(left, lit, 0);
6442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6448 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6451 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6457 if(res_offset < res_size-1)
6465 /* if the right side is in a register or in direct space or
6466 if the left is a pointer register & right is not */
6467 else if (AOP_TYPE(right) == AOP_REG ||
6468 AOP_TYPE(right) == AOP_DIR ||
6469 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6470 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6471 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6472 int lbl_key = lbl->key;
6475 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6476 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6478 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6479 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6480 __FUNCTION__,__LINE__);
6484 /* switch(size) { */
6486 /* genc16bit2lit(left, lit, 0); */
6488 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6493 if((AOP_TYPE(left) == AOP_DIR) &&
6494 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6496 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6499 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6501 switch (lit & 0xff) {
6503 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6507 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6512 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6519 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6525 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6528 if(AOP_TYPE(result) == AOP_CRY) {
6529 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6534 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6536 /* fix me. probably need to check result size too */
6537 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6542 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6543 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6550 if(res_offset < res_size-1)
6555 } else if(AOP_TYPE(right) == AOP_REG &&
6556 AOP_TYPE(left) != AOP_DIR){
6559 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6560 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6561 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6566 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6568 if(res_offset < res_size-1)
6573 /* right is a pointer reg need both a & b */
6575 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6577 pic16_emitcode("mov","b,%s",l);
6578 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6579 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6584 if(result && preserve_result)
6587 for(i = 0; i < AOP_SIZE(result); i++)
6588 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6591 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6593 if(result && preserve_result)
6594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6599 pic16_emitpLabel(lbl->key);
6601 if(result && preserve_result)
6604 for(i = 0; i < AOP_SIZE(result); i++)
6605 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6607 pic16_emitpLabel(lbl_done->key);
6610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6618 /*-----------------------------------------------------------------*/
6619 /* gencjne - compare and jump if not equal */
6620 /*-----------------------------------------------------------------*/
6621 static void gencjne(operand *left, operand *right, iCode *ifx)
6623 symbol *tlbl = newiTempLabel(NULL);
6625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6626 gencjneshort(left, right, lbl);
6628 pic16_emitcode("mov","a,%s",one);
6629 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6630 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6631 pic16_emitcode("clr","a");
6632 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6634 pic16_emitpLabel(lbl->key);
6635 pic16_emitpLabel(tlbl->key);
6641 /*-----------------------------------------------------------------*/
6642 /* is_LitOp - check if operand has to be treated as literal */
6643 /*-----------------------------------------------------------------*/
6644 static bool is_LitOp(operand *op)
6646 return ((AOP_TYPE(op) == AOP_LIT)
6647 || ( (AOP_TYPE(op) == AOP_PCODE)
6648 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6649 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6652 /*-----------------------------------------------------------------*/
6653 /* is_LitAOp - check if operand has to be treated as literal */
6654 /*-----------------------------------------------------------------*/
6655 static bool is_LitAOp(asmop *aop)
6657 return ((aop->type == AOP_LIT)
6658 || ( (aop->type == AOP_PCODE)
6659 && ( (aop->aopu.pcop->type == PO_LITERAL)
6660 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6665 /*-----------------------------------------------------------------*/
6666 /* genCmpEq - generates code for equal to */
6667 /*-----------------------------------------------------------------*/
6668 static void genCmpEq (iCode *ic, iCode *ifx)
6670 operand *left, *right, *result;
6671 symbol *falselbl = newiTempLabel(NULL);
6672 symbol *donelbl = newiTempLabel(NULL);
6674 int preserve_result = 0;
6675 int generate_result = 0;
6677 unsigned long lit = -1;
6681 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6682 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6683 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6685 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6687 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6689 werror(W_POSSBUG2, __FILE__, __LINE__);
6690 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6691 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6695 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6697 operand *tmp = right ;
6702 if (AOP_TYPE(right) == AOP_LIT) {
6703 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6706 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6707 preserve_result = 1;
6709 if(result && AOP_SIZE(result))
6710 generate_result = 1;
6712 if(generate_result && !preserve_result)
6714 for(i = 0; i < AOP_SIZE(result); i++)
6715 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6718 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6719 for(i=0; i < AOP_SIZE(left); i++)
6721 if(AOP_TYPE(left) != AOP_ACC)
6724 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6726 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6728 if(is_LitOp(right)) {
6729 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6730 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6733 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6735 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6740 if(generate_result && preserve_result)
6742 for(i = 0; i < AOP_SIZE(result); i++)
6743 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6747 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6749 if(generate_result && preserve_result)
6750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6752 if(ifx && IC_TRUE(ifx))
6753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6755 if(ifx && IC_FALSE(ifx))
6756 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6758 pic16_emitpLabel(falselbl->key);
6762 if(ifx && IC_FALSE(ifx))
6763 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6765 if(generate_result && preserve_result)
6767 for(i = 0; i < AOP_SIZE(result); i++)
6768 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6771 pic16_emitpLabel(donelbl->key);
6777 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6778 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6779 pic16_freeAsmop(result,NULL,ic,TRUE);
6785 // old version kept for reference
6787 /*-----------------------------------------------------------------*/
6788 /* genCmpEq - generates code for equal to */
6789 /*-----------------------------------------------------------------*/
6790 static void genCmpEq (iCode *ic, iCode *ifx)
6792 operand *left, *right, *result;
6793 unsigned long lit = 0L;
6795 symbol *falselbl = newiTempLabel(NULL);
6798 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6801 DEBUGpic16_emitcode ("; ifx is non-null","");
6803 DEBUGpic16_emitcode ("; ifx is null","");
6805 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6806 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6807 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6809 size = max(AOP_SIZE(left),AOP_SIZE(right));
6811 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6813 /* if literal, literal on the right or
6814 if the right is in a pointer register and left
6816 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6817 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6818 operand *tmp = right ;
6824 if(ifx && !AOP_SIZE(result)){
6826 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6827 /* if they are both bit variables */
6828 if (AOP_TYPE(left) == AOP_CRY &&
6829 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6830 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6831 if(AOP_TYPE(right) == AOP_LIT){
6832 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6834 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6835 pic16_emitcode("cpl","c");
6836 } else if(lit == 1L) {
6837 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6839 pic16_emitcode("clr","c");
6841 /* AOP_TYPE(right) == AOP_CRY */
6843 symbol *lbl = newiTempLabel(NULL);
6844 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6845 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6846 pic16_emitcode("cpl","c");
6847 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6849 /* if true label then we jump if condition
6851 tlbl = newiTempLabel(NULL);
6852 if ( IC_TRUE(ifx) ) {
6853 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6854 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6856 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6857 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6859 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6862 /* left and right are both bit variables, result is carry */
6865 resolveIfx(&rIfx,ifx);
6867 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6868 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6869 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6870 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6875 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6877 /* They're not both bit variables. Is the right a literal? */
6878 if(AOP_TYPE(right) == AOP_LIT) {
6879 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6884 switch(lit & 0xff) {
6886 if ( IC_TRUE(ifx) ) {
6887 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6891 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6892 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6896 if ( IC_TRUE(ifx) ) {
6897 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6901 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6902 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6906 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6908 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6913 /* end of size == 1 */
6917 genc16bit2lit(left,lit,offset);
6920 /* end of size == 2 */
6925 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6926 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6927 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6928 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6931 /* search for patterns that can be optimized */
6933 genc16bit2lit(left,lit,0);
6937 emitSKPZ; // if hi word unequal
6939 emitSKPNZ; // if hi word equal
6941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6942 genc16bit2lit(left,lit,2);
6945 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6946 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6950 pic16_emitpLabel(falselbl->key);
6959 } else if(AOP_TYPE(right) == AOP_CRY ) {
6960 /* we know the left is not a bit, but that the right is */
6961 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6962 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6963 pic16_popGet(AOP(right),offset));
6964 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6966 /* if the two are equal, then W will be 0 and the Z bit is set
6967 * we could test Z now, or go ahead and check the high order bytes if
6968 * the variable we're comparing is larger than a byte. */
6971 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6973 if ( IC_TRUE(ifx) ) {
6975 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6976 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6979 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6980 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6984 /* They're both variables that are larger than bits */
6987 tlbl = newiTempLabel(NULL);
6990 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6991 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6993 if ( IC_TRUE(ifx) ) {
6997 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6999 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7000 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7004 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7007 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7008 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7013 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7015 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7016 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7020 if(s>1 && IC_TRUE(ifx)) {
7021 pic16_emitpLabel(tlbl->key);
7022 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7026 /* mark the icode as generated */
7031 /* if they are both bit variables */
7032 if (AOP_TYPE(left) == AOP_CRY &&
7033 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7034 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7035 if(AOP_TYPE(right) == AOP_LIT){
7036 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7038 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7039 pic16_emitcode("cpl","c");
7040 } else if(lit == 1L) {
7041 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7043 pic16_emitcode("clr","c");
7045 /* AOP_TYPE(right) == AOP_CRY */
7047 symbol *lbl = newiTempLabel(NULL);
7048 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7049 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7050 pic16_emitcode("cpl","c");
7051 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7054 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7055 pic16_outBitC(result);
7059 genIfxJump (ifx,"c");
7062 /* if the result is used in an arithmetic operation
7063 then put the result in place */
7064 pic16_outBitC(result);
7067 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7068 gencjne(left,right,result,ifx);
7071 gencjne(left,right,newiTempLabel(NULL));
7073 if(IC_TRUE(ifx)->key)
7074 gencjne(left,right,IC_TRUE(ifx)->key);
7076 gencjne(left,right,IC_FALSE(ifx)->key);
7080 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7081 pic16_aopPut(AOP(result),"a",0);
7086 genIfxJump (ifx,"a");
7090 /* if the result is used in an arithmetic operation
7091 then put the result in place */
7093 if (AOP_TYPE(result) != AOP_CRY)
7094 pic16_outAcc(result);
7096 /* leave the result in acc */
7100 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7102 pic16_freeAsmop(result,NULL,ic,TRUE);
7106 /*-----------------------------------------------------------------*/
7107 /* ifxForOp - returns the icode containing the ifx for operand */
7108 /*-----------------------------------------------------------------*/
7109 static iCode *ifxForOp ( operand *op, iCode *ic )
7113 /* if true symbol then needs to be assigned */
7114 if (IS_TRUE_SYMOP(op))
7117 /* if this has register type condition and
7118 the next instruction is ifx with the same operand
7119 and live to of the operand is upto the ifx only then */
7121 && ic->next->op == IFX
7122 && IC_COND(ic->next)->key == op->key
7123 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7125 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7131 ic->next->op == IFX &&
7132 IC_COND(ic->next)->key == op->key) {
7133 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7138 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7140 ic->next->op == IFX)
7141 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7144 ic->next->op == IFX &&
7145 IC_COND(ic->next)->key == op->key) {
7146 DEBUGpic16_emitcode ("; "," key is okay");
7147 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7148 OP_SYMBOL(op)->liveTo,
7153 /* the code below is completely untested
7154 * it just allows ulong2fs.c compile -- VR */
7157 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7158 __FILE__, __FUNCTION__, __LINE__);
7160 /* if this has register type condition and
7161 the next instruction is ifx with the same operand
7162 and live to of the operand is upto the ifx only then */
7164 ic->next->op == IFX &&
7165 IC_COND(ic->next)->key == op->key &&
7166 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7170 ic->next->op == IFX &&
7171 IC_COND(ic->next)->key == op->key) {
7172 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7176 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7177 __FILE__, __FUNCTION__, __LINE__);
7179 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7184 /*-----------------------------------------------------------------*/
7185 /* genAndOp - for && operation */
7186 /*-----------------------------------------------------------------*/
7187 static void genAndOp (iCode *ic)
7189 operand *left,*right, *result;
7194 /* note here that && operations that are in an
7195 if statement are taken away by backPatchLabels
7196 only those used in arthmetic operations remain */
7197 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7198 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7199 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7201 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7203 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7204 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7205 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7207 /* if both are bit variables */
7208 /* if (AOP_TYPE(left) == AOP_CRY && */
7209 /* AOP_TYPE(right) == AOP_CRY ) { */
7210 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7211 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7212 /* pic16_outBitC(result); */
7214 /* tlbl = newiTempLabel(NULL); */
7215 /* pic16_toBoolean(left); */
7216 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7217 /* pic16_toBoolean(right); */
7218 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7219 /* pic16_outBitAcc(result); */
7222 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7223 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7224 pic16_freeAsmop(result,NULL,ic,TRUE);
7228 /*-----------------------------------------------------------------*/
7229 /* genOrOp - for || operation */
7230 /*-----------------------------------------------------------------*/
7233 modified this code, but it doesn't appear to ever get called
7236 static void genOrOp (iCode *ic)
7238 operand *left,*right, *result;
7243 /* note here that || operations that are in an
7244 if statement are taken away by backPatchLabels
7245 only those used in arthmetic operations remain */
7246 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7247 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7248 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7250 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7252 /* if both are bit variables */
7253 if (AOP_TYPE(left) == AOP_CRY &&
7254 AOP_TYPE(right) == AOP_CRY ) {
7255 pic16_emitcode("clrc","");
7256 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7257 AOP(left)->aopu.aop_dir,
7258 AOP(left)->aopu.aop_dir);
7259 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7260 AOP(right)->aopu.aop_dir,
7261 AOP(right)->aopu.aop_dir);
7262 pic16_emitcode("setc","");
7265 tlbl = newiTempLabel(NULL);
7266 pic16_toBoolean(left);
7268 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7269 pic16_toBoolean(right);
7270 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7272 pic16_outBitAcc(result);
7275 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7276 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7277 pic16_freeAsmop(result,NULL,ic,TRUE);
7280 /*-----------------------------------------------------------------*/
7281 /* isLiteralBit - test if lit == 2^n */
7282 /*-----------------------------------------------------------------*/
7283 static int isLiteralBit(unsigned long lit)
7285 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7286 0x100L,0x200L,0x400L,0x800L,
7287 0x1000L,0x2000L,0x4000L,0x8000L,
7288 0x10000L,0x20000L,0x40000L,0x80000L,
7289 0x100000L,0x200000L,0x400000L,0x800000L,
7290 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7291 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7294 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7295 for(idx = 0; idx < 32; idx++)
7301 /*-----------------------------------------------------------------*/
7302 /* continueIfTrue - */
7303 /*-----------------------------------------------------------------*/
7304 static void continueIfTrue (iCode *ic)
7308 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7312 /*-----------------------------------------------------------------*/
7314 /*-----------------------------------------------------------------*/
7315 static void jumpIfTrue (iCode *ic)
7319 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7323 /*-----------------------------------------------------------------*/
7324 /* jmpTrueOrFalse - */
7325 /*-----------------------------------------------------------------*/
7326 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7328 // ugly but optimized by peephole
7331 symbol *nlbl = newiTempLabel(NULL);
7332 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7333 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7334 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7335 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7337 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7338 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7343 /*-----------------------------------------------------------------*/
7344 /* genAnd - code for and */
7345 /*-----------------------------------------------------------------*/
7346 static void genAnd (iCode *ic, iCode *ifx)
7348 operand *left, *right, *result;
7350 unsigned long lit = 0L;
7356 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7357 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7358 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7360 resolveIfx(&rIfx,ifx);
7362 /* if left is a literal & right is not then exchange them */
7363 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7364 AOP_NEEDSACC(left)) {
7365 operand *tmp = right ;
7370 /* if result = right then exchange them */
7371 if(pic16_sameRegs(AOP(result),AOP(right))){
7372 operand *tmp = right ;
7377 /* if right is bit then exchange them */
7378 if (AOP_TYPE(right) == AOP_CRY &&
7379 AOP_TYPE(left) != AOP_CRY){
7380 operand *tmp = right ;
7384 if(AOP_TYPE(right) == AOP_LIT)
7385 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7387 size = AOP_SIZE(result);
7389 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7392 // result = bit & yy;
7393 if (AOP_TYPE(left) == AOP_CRY){
7394 // c = bit & literal;
7395 if(AOP_TYPE(right) == AOP_LIT){
7397 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7400 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7403 if(size && (AOP_TYPE(result) == AOP_CRY)){
7404 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7407 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7411 pic16_emitcode("clr","c");
7414 if (AOP_TYPE(right) == AOP_CRY){
7416 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7417 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7420 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7422 pic16_emitcode("rrc","a");
7423 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7429 pic16_outBitC(result);
7431 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7432 genIfxJump(ifx, "c");
7436 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7437 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7438 if((AOP_TYPE(right) == AOP_LIT) &&
7439 (AOP_TYPE(result) == AOP_CRY) &&
7440 (AOP_TYPE(left) != AOP_CRY)){
7441 int posbit = isLiteralBit(lit);
7445 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7448 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7454 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7457 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7458 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7461 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7462 size = AOP_SIZE(left);
7465 int bp = posbit, ofs=0;
7472 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7473 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7477 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7478 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7480 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7487 symbol *tlbl = newiTempLabel(NULL);
7488 int sizel = AOP_SIZE(left);
7494 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7496 /* patch provided by Aaron Colwell */
7497 if((posbit = isLiteralBit(bytelit)) != 0) {
7498 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7499 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7500 (posbit-1),0, PO_GPR_REGISTER));
7502 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7503 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7505 if (bytelit == 0xff) {
7506 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7507 * a peephole could optimize it out -- VR */
7508 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7510 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7511 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7514 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7515 pic16_popGetLabel(tlbl->key));
7519 /* old code, left here for reference -- VR 09/2004 */
7520 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7522 if((posbit = isLiteralBit(bytelit)) != 0)
7523 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7525 if(bytelit != 0x0FFL)
7526 pic16_emitcode("anl","a,%s",
7527 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7528 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7534 // bit = left & literal
7537 pic16_emitpLabel(tlbl->key);
7539 // if(left & literal)
7542 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7545 pic16_emitpLabel(tlbl->key);
7550 pic16_outBitC(result);
7554 /* if left is same as result */
7555 if(pic16_sameRegs(AOP(result),AOP(left))){
7557 for(;size--; offset++,lit>>=8) {
7558 if(AOP_TYPE(right) == AOP_LIT){
7559 switch(lit & 0xff) {
7561 /* and'ing with 0 has clears the result */
7562 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7563 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7566 /* and'ing with 0xff is a nop when the result and left are the same */
7571 int p = pic16_my_powof2( (~lit) & 0xff );
7573 /* only one bit is set in the literal, so use a bcf instruction */
7574 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7575 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7578 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7579 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7580 if(know_W != (lit&0xff))
7581 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7583 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7588 if (AOP_TYPE(left) == AOP_ACC) {
7589 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7591 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7592 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7599 // left & result in different registers
7600 if(AOP_TYPE(result) == AOP_CRY){
7602 // if(size), result in bit
7603 // if(!size && ifx), conditional oper: if(left & right)
7604 symbol *tlbl = newiTempLabel(NULL);
7605 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7607 pic16_emitcode("setb","c");
7609 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7610 pic16_emitcode("anl","a,%s",
7611 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7612 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7617 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7618 pic16_outBitC(result);
7620 jmpTrueOrFalse(ifx, tlbl);
7622 for(;(size--);offset++) {
7624 // result = left & right
7625 if(AOP_TYPE(right) == AOP_LIT){
7626 int t = (lit >> (offset*8)) & 0x0FFL;
7629 pic16_emitcode("clrf","%s",
7630 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7631 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7634 pic16_emitcode("movf","%s,w",
7635 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7636 pic16_emitcode("movwf","%s",
7637 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7638 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7639 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7642 pic16_emitcode("movlw","0x%x",t);
7643 pic16_emitcode("andwf","%s,w",
7644 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645 pic16_emitcode("movwf","%s",
7646 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7648 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7649 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7650 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7655 if (AOP_TYPE(left) == AOP_ACC) {
7656 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7659 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7660 pic16_emitcode("andwf","%s,w",
7661 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7662 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7663 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7665 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7666 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7672 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7673 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7674 pic16_freeAsmop(result,NULL,ic,TRUE);
7677 /*-----------------------------------------------------------------*/
7678 /* genOr - code for or */
7679 /*-----------------------------------------------------------------*/
7680 static void genOr (iCode *ic, iCode *ifx)
7682 operand *left, *right, *result;
7684 unsigned long lit = 0L;
7686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7688 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7689 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7690 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7692 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7694 /* if left is a literal & right is not then exchange them */
7695 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7696 AOP_NEEDSACC(left)) {
7697 operand *tmp = right ;
7702 /* if result = right then exchange them */
7703 if(pic16_sameRegs(AOP(result),AOP(right))){
7704 operand *tmp = right ;
7709 /* if right is bit then exchange them */
7710 if (AOP_TYPE(right) == AOP_CRY &&
7711 AOP_TYPE(left) != AOP_CRY){
7712 operand *tmp = right ;
7717 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7719 if(AOP_TYPE(right) == AOP_LIT)
7720 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7722 size = AOP_SIZE(result);
7726 if (AOP_TYPE(left) == AOP_CRY){
7727 if(AOP_TYPE(right) == AOP_LIT){
7728 // c = bit & literal;
7730 // lit != 0 => result = 1
7731 if(AOP_TYPE(result) == AOP_CRY){
7733 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7734 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7735 // AOP(result)->aopu.aop_dir,
7736 // AOP(result)->aopu.aop_dir);
7738 continueIfTrue(ifx);
7742 // lit == 0 => result = left
7743 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7745 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7748 if (AOP_TYPE(right) == AOP_CRY){
7749 if(pic16_sameRegs(AOP(result),AOP(left))){
7751 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7752 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7753 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7755 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7756 AOP(result)->aopu.aop_dir,
7757 AOP(result)->aopu.aop_dir);
7758 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7759 AOP(right)->aopu.aop_dir,
7760 AOP(right)->aopu.aop_dir);
7761 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7762 AOP(result)->aopu.aop_dir,
7763 AOP(result)->aopu.aop_dir);
7765 if( AOP_TYPE(result) == AOP_ACC) {
7766 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(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_MOVLW, pic16_popGetLit(1));
7773 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7774 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7775 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7776 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7778 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7779 AOP(result)->aopu.aop_dir,
7780 AOP(result)->aopu.aop_dir);
7781 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7782 AOP(right)->aopu.aop_dir,
7783 AOP(right)->aopu.aop_dir);
7784 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7785 AOP(left)->aopu.aop_dir,
7786 AOP(left)->aopu.aop_dir);
7787 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7788 AOP(result)->aopu.aop_dir,
7789 AOP(result)->aopu.aop_dir);
7794 symbol *tlbl = newiTempLabel(NULL);
7795 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7798 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7799 if( AOP_TYPE(right) == AOP_ACC) {
7800 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7802 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7803 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7808 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7809 pic16_emitcode(";XXX setb","c");
7810 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7811 AOP(left)->aopu.aop_dir,tlbl->key+100);
7812 pic16_toBoolean(right);
7813 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7814 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7815 jmpTrueOrFalse(ifx, tlbl);
7819 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7826 pic16_outBitC(result);
7828 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7829 genIfxJump(ifx, "c");
7833 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7834 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7835 if((AOP_TYPE(right) == AOP_LIT) &&
7836 (AOP_TYPE(result) == AOP_CRY) &&
7837 (AOP_TYPE(left) != AOP_CRY)){
7839 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7842 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7844 continueIfTrue(ifx);
7847 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7848 // lit = 0, result = boolean(left)
7850 pic16_emitcode(";XXX setb","c");
7851 pic16_toBoolean(right);
7853 symbol *tlbl = newiTempLabel(NULL);
7854 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7856 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7858 genIfxJump (ifx,"a");
7862 pic16_outBitC(result);
7866 /* if left is same as result */
7867 if(pic16_sameRegs(AOP(result),AOP(left))){
7869 for(;size--; offset++,lit>>=8) {
7870 if(AOP_TYPE(right) == AOP_LIT){
7871 if((lit & 0xff) == 0)
7872 /* or'ing with 0 has no effect */
7875 int p = pic16_my_powof2(lit & 0xff);
7877 /* only one bit is set in the literal, so use a bsf instruction */
7878 pic16_emitpcode(POC_BSF,
7879 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7881 if(know_W != (lit & 0xff))
7882 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7883 know_W = lit & 0xff;
7884 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7889 if (AOP_TYPE(left) == AOP_ACC) {
7890 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7891 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7894 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7896 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7903 // left & result in different registers
7904 if(AOP_TYPE(result) == AOP_CRY){
7906 // if(size), result in bit
7907 // if(!size && ifx), conditional oper: if(left | right)
7908 symbol *tlbl = newiTempLabel(NULL);
7909 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7910 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7914 pic16_emitcode(";XXX setb","c");
7916 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7917 pic16_emitcode(";XXX orl","a,%s",
7918 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7919 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7924 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7925 pic16_outBitC(result);
7927 jmpTrueOrFalse(ifx, tlbl);
7928 } else for(;(size--);offset++){
7930 // result = left & right
7931 if(AOP_TYPE(right) == AOP_LIT){
7932 int t = (lit >> (offset*8)) & 0x0FFL;
7935 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7938 // pic16_emitcode("movf","%s,w",
7939 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7940 // pic16_emitcode("movwf","%s",
7941 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7944 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7945 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7948 // pic16_emitcode("movlw","0x%x",t);
7949 // pic16_emitcode("iorwf","%s,w",
7950 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7951 // pic16_emitcode("movwf","%s",
7952 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7958 // faster than result <- left, anl result,right
7959 // and better if result is SFR
7960 if (AOP_TYPE(left) == AOP_ACC) {
7961 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7962 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7964 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7965 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7967 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7968 // pic16_emitcode("iorwf","%s,w",
7969 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7972 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7977 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7978 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7979 pic16_freeAsmop(result,NULL,ic,TRUE);
7982 /*-----------------------------------------------------------------*/
7983 /* genXor - code for xclusive or */
7984 /*-----------------------------------------------------------------*/
7985 static void genXor (iCode *ic, iCode *ifx)
7987 operand *left, *right, *result;
7989 unsigned long lit = 0L;
7991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7993 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7994 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7995 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7997 /* if left is a literal & right is not ||
7998 if left needs acc & right does not */
7999 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8000 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8001 operand *tmp = right ;
8006 /* if result = right then exchange them */
8007 if(pic16_sameRegs(AOP(result),AOP(right))){
8008 operand *tmp = right ;
8013 /* if right is bit then exchange them */
8014 if (AOP_TYPE(right) == AOP_CRY &&
8015 AOP_TYPE(left) != AOP_CRY){
8016 operand *tmp = right ;
8020 if(AOP_TYPE(right) == AOP_LIT)
8021 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8023 size = AOP_SIZE(result);
8027 if (AOP_TYPE(left) == AOP_CRY){
8028 if(AOP_TYPE(right) == AOP_LIT){
8029 // c = bit & literal;
8031 // lit>>1 != 0 => result = 1
8032 if(AOP_TYPE(result) == AOP_CRY){
8034 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8035 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8037 continueIfTrue(ifx);
8040 pic16_emitcode("setb","c");
8044 // lit == 0, result = left
8045 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8047 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8049 // lit == 1, result = not(left)
8050 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8051 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8052 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8053 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8056 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8057 pic16_emitcode("cpl","c");
8064 symbol *tlbl = newiTempLabel(NULL);
8065 if (AOP_TYPE(right) == AOP_CRY){
8067 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8070 int sizer = AOP_SIZE(right);
8072 // if val>>1 != 0, result = 1
8073 pic16_emitcode("setb","c");
8075 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8077 // test the msb of the lsb
8078 pic16_emitcode("anl","a,#0xfe");
8079 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8083 pic16_emitcode("rrc","a");
8085 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8086 pic16_emitcode("cpl","c");
8087 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8092 pic16_outBitC(result);
8094 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8095 genIfxJump(ifx, "c");
8099 if(pic16_sameRegs(AOP(result),AOP(left))){
8100 /* if left is same as result */
8101 for(;size--; offset++) {
8102 if(AOP_TYPE(right) == AOP_LIT){
8103 int t = (lit >> (offset*8)) & 0x0FFL;
8107 if (IS_AOP_PREG(left)) {
8108 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8109 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8110 pic16_aopPut(AOP(result),"a",offset);
8112 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8113 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8114 pic16_emitcode("xrl","%s,%s",
8115 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8116 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8119 if (AOP_TYPE(left) == AOP_ACC)
8120 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8123 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8125 if (IS_AOP_PREG(left)) {
8126 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8127 pic16_aopPut(AOP(result),"a",offset);
8129 pic16_emitcode("xrl","%s,a",
8130 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136 // left & result in different registers
8137 if(AOP_TYPE(result) == AOP_CRY){
8139 // if(size), result in bit
8140 // if(!size && ifx), conditional oper: if(left ^ right)
8141 symbol *tlbl = newiTempLabel(NULL);
8142 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8144 pic16_emitcode("setb","c");
8146 if((AOP_TYPE(right) == AOP_LIT) &&
8147 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8148 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8150 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 pic16_emitcode("xrl","a,%s",
8152 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8154 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8159 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8160 pic16_outBitC(result);
8162 jmpTrueOrFalse(ifx, tlbl);
8163 } else for(;(size--);offset++){
8165 // result = left & right
8166 if(AOP_TYPE(right) == AOP_LIT){
8167 int t = (lit >> (offset*8)) & 0x0FFL;
8170 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8171 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8172 pic16_emitcode("movf","%s,w",
8173 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174 pic16_emitcode("movwf","%s",
8175 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8178 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8179 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8180 pic16_emitcode("comf","%s,w",
8181 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8182 pic16_emitcode("movwf","%s",
8183 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8186 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8187 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189 pic16_emitcode("movlw","0x%x",t);
8190 pic16_emitcode("xorwf","%s,w",
8191 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8192 pic16_emitcode("movwf","%s",
8193 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8199 // faster than result <- left, anl result,right
8200 // and better if result is SFR
8201 if (AOP_TYPE(left) == AOP_ACC) {
8202 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8203 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8206 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8207 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8208 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8210 if ( AOP_TYPE(result) != AOP_ACC){
8211 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8212 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8218 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8219 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8220 pic16_freeAsmop(result,NULL,ic,TRUE);
8223 /*-----------------------------------------------------------------*/
8224 /* genInline - write the inline code out */
8225 /*-----------------------------------------------------------------*/
8226 static void genInline (iCode *ic)
8228 char *buffer, *bp, *bp1;
8230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8232 _G.inLine += (!options.asmpeep);
8234 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8235 strcpy(buffer,IC_INLINE(ic));
8237 while((bp1=strstr(bp, "\\n"))) {
8245 /* This is an experimental code for #pragma inline
8246 and is temporarily disabled for 2.5.0 release */
8254 cbuf = Safe_strdup(buffer);
8255 cblen = strlen(buffer)+1;
8256 memset(cbuf, 0, cblen);
8261 if(*bp != '%')*bp1++ = *bp++;
8267 if(i>elementsInSet(asmInlineMap))break;
8270 s = indexSet(asmInlineMap, i);
8271 DEBUGpc("searching symbol s = `%s'", s);
8272 sym = findSym(SymbolTab, NULL, s);
8275 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8277 strcat(bp1, sym->rname);
8283 if(strlen(bp1) > cblen - 16) {
8284 int i = strlen(cbuf);
8286 cbuf = realloc(cbuf, cblen);
8287 memset(cbuf+i, 0, 50);
8293 buffer = Safe_strdup( cbuf );
8300 /* emit each line as a code */
8306 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8314 /* print label, use this special format with NULL directive
8315 * to denote that the argument should not be indented with tab */
8316 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8319 /* advance to end of line (prevent splitting of comments at ':' */
8320 while (*bp && *bp != '\n') {
8328 if ((bp1 != bp) && *bp1)
8329 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8334 _G.inLine -= (!options.asmpeep);
8337 /*-----------------------------------------------------------------*/
8338 /* genRRC - rotate right with carry */
8339 /*-----------------------------------------------------------------*/
8340 static void genRRC (iCode *ic)
8342 operand *left , *result ;
8343 int size, offset = 0, same;
8345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8347 /* rotate right with carry */
8349 result=IC_RESULT(ic);
8350 pic16_aopOp (left,ic,FALSE);
8351 pic16_aopOp (result,ic,TRUE);
8353 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8355 same = pic16_sameRegs(AOP(result),AOP(left));
8357 size = AOP_SIZE(result);
8359 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8361 /* get the lsb and put it into the carry */
8362 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8369 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8371 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8372 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8378 pic16_freeAsmop(left,NULL,ic,TRUE);
8379 pic16_freeAsmop(result,NULL,ic,TRUE);
8382 /*-----------------------------------------------------------------*/
8383 /* genRLC - generate code for rotate left with carry */
8384 /*-----------------------------------------------------------------*/
8385 static void genRLC (iCode *ic)
8387 operand *left , *result ;
8388 int size, offset = 0;
8391 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8392 /* rotate right with carry */
8394 result=IC_RESULT(ic);
8395 pic16_aopOp (left,ic,FALSE);
8396 pic16_aopOp (result,ic,TRUE);
8398 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8400 same = pic16_sameRegs(AOP(result),AOP(left));
8402 /* move it to the result */
8403 size = AOP_SIZE(result);
8405 /* get the msb and put it into the carry */
8406 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8413 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8415 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8416 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8423 pic16_freeAsmop(left,NULL,ic,TRUE);
8424 pic16_freeAsmop(result,NULL,ic,TRUE);
8428 /* gpasm can get the highest order bit with HIGH/UPPER
8429 * so the following probably is not needed -- VR */
8431 /*-----------------------------------------------------------------*/
8432 /* genGetHbit - generates code get highest order bit */
8433 /*-----------------------------------------------------------------*/
8434 static void genGetHbit (iCode *ic)
8436 operand *left, *result;
8438 result=IC_RESULT(ic);
8439 pic16_aopOp (left,ic,FALSE);
8440 pic16_aopOp (result,ic,FALSE);
8442 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8443 /* get the highest order byte into a */
8444 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8445 if(AOP_TYPE(result) == AOP_CRY){
8446 pic16_emitcode("rlc","a");
8447 pic16_outBitC(result);
8450 pic16_emitcode("rl","a");
8451 pic16_emitcode("anl","a,#0x01");
8452 pic16_outAcc(result);
8456 pic16_freeAsmop(left,NULL,ic,TRUE);
8457 pic16_freeAsmop(result,NULL,ic,TRUE);
8461 /*-----------------------------------------------------------------*/
8462 /* AccRol - rotate left accumulator by known count */
8463 /*-----------------------------------------------------------------*/
8464 static void AccRol (int shCount)
8466 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8467 shCount &= 0x0007; // shCount : 0..7
8472 pic16_emitcode("rl","a");
8475 pic16_emitcode("rl","a");
8476 pic16_emitcode("rl","a");
8479 pic16_emitcode("swap","a");
8480 pic16_emitcode("rr","a");
8483 pic16_emitcode("swap","a");
8486 pic16_emitcode("swap","a");
8487 pic16_emitcode("rl","a");
8490 pic16_emitcode("rr","a");
8491 pic16_emitcode("rr","a");
8494 pic16_emitcode("rr","a");
8500 /*-----------------------------------------------------------------*/
8501 /* AccLsh - left shift accumulator by known count */
8502 /*-----------------------------------------------------------------*/
8503 static void AccLsh (int shCount, int doMask)
8505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8511 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8515 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8525 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8526 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8530 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8533 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8537 /* no masking is required in genPackBits */
8538 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8542 /*-----------------------------------------------------------------*/
8543 /* AccRsh - right shift accumulator by known count */
8544 /*-----------------------------------------------------------------*/
8545 static void AccRsh (int shCount, int andmask)
8547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8574 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8581 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8585 /*-----------------------------------------------------------------*/
8586 /* AccSRsh - signed right shift accumulator by known count */
8587 /*-----------------------------------------------------------------*/
8588 static void AccSRsh (int shCount)
8591 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8594 pic16_emitcode("mov","c,acc.7");
8595 pic16_emitcode("rrc","a");
8596 } else if(shCount == 2){
8597 pic16_emitcode("mov","c,acc.7");
8598 pic16_emitcode("rrc","a");
8599 pic16_emitcode("mov","c,acc.7");
8600 pic16_emitcode("rrc","a");
8602 tlbl = newiTempLabel(NULL);
8603 /* rotate right accumulator */
8604 AccRol(8 - shCount);
8605 /* and kill the higher order bits */
8606 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8607 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8608 pic16_emitcode("orl","a,#0x%02x",
8609 (unsigned char)~SRMask[shCount]);
8610 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8616 /*-----------------------------------------------------------------*/
8617 /* shiftR1Left2Result - shift right one byte from left to result */
8618 /*-----------------------------------------------------------------*/
8619 static void shiftR1Left2ResultSigned (operand *left, int offl,
8620 operand *result, int offr,
8625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8627 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8631 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8633 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8635 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8636 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8644 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8647 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8649 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8650 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8656 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8659 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8662 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8663 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8664 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8666 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8667 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8675 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8676 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8681 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8687 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8689 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8690 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8696 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8697 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8698 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8699 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8700 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8712 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8713 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8714 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8715 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8717 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8718 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8727 /*-----------------------------------------------------------------*/
8728 /* shiftR1Left2Result - shift right one byte from left to result */
8729 /*-----------------------------------------------------------------*/
8730 static void shiftR1Left2Result (operand *left, int offl,
8731 operand *result, int offr,
8732 int shCount, int sign)
8736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8738 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8740 /* Copy the msb into the carry if signed. */
8742 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8752 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8754 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8779 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8780 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8786 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8792 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8795 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8801 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8802 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8810 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8811 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8820 /*-----------------------------------------------------------------*/
8821 /* shiftL1Left2Result - shift left one byte from left to result */
8822 /*-----------------------------------------------------------------*/
8823 static void shiftL1Left2Result (operand *left, int offl,
8824 operand *result, int offr, int shCount)
8829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8831 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8832 DEBUGpic16_emitcode ("; ***","same = %d",same);
8833 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8835 /* shift left accumulator */
8836 //AccLsh(shCount, 1); // don't comment out just yet...
8837 // pic16_aopPut(AOP(result),"a",offr);
8841 /* Shift left 1 bit position */
8842 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8844 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8846 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8847 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8851 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8852 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8853 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8858 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8861 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8865 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8866 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8870 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8871 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8876 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8877 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8883 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8888 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8893 /*-----------------------------------------------------------------*/
8894 /* movLeft2Result - move byte from left to result */
8895 /*-----------------------------------------------------------------*/
8896 static void movLeft2Result (operand *left, int offl,
8897 operand *result, int offr)
8900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8901 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8902 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8904 if (*l == '@' && (IS_AOP_PREG(result))) {
8905 pic16_emitcode("mov","a,%s",l);
8906 pic16_aopPut(AOP(result),"a",offr);
8908 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8914 /*-----------------------------------------------------------------*/
8915 /* shiftL2Left2Result - shift left two bytes from left to result */
8916 /*-----------------------------------------------------------------*/
8917 static void shiftL2Left2Result (operand *left, int offl,
8918 operand *result, int offr, int shCount)
8920 int same = pic16_sameRegs(AOP(result), AOP(left));
8923 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8925 if (same && (offl != offr)) { // shift bytes
8928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8929 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8931 } else { // just treat as different later on
8944 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8945 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8958 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8973 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8976 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8982 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8983 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8984 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8985 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8996 /* note, use a mov/add for the shift since the mov has a
8997 chance of getting optimized out */
8998 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9006 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9013 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9019 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9024 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9029 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9030 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9032 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9035 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9037 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9038 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9045 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9046 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9047 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9053 /*-----------------------------------------------------------------*/
9054 /* shiftR2Left2Result - shift right two bytes from left to result */
9055 /*-----------------------------------------------------------------*/
9056 static void shiftR2Left2Result (operand *left, int offl,
9057 operand *result, int offr,
9058 int shCount, int sign)
9060 int same = pic16_sameRegs(AOP(result), AOP(left));
9062 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9064 if (same && (offl != offr)) { // shift right bytes
9067 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9068 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9070 } else { // just treat as different later on
9082 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9087 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9090 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9091 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9092 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9093 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9101 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9110 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9115 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9116 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9119 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9120 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9123 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9124 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9125 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9126 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9130 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9131 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9136 pic16_emitpcode(POC_BTFSC,
9137 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9138 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9147 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9149 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9150 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9151 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9154 pic16_emitpcode(POC_BTFSC,
9155 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9156 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9158 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9159 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9169 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9170 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9172 pic16_emitpcode(POC_BTFSC,
9173 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9174 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9177 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9184 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9187 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9190 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9192 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9197 /*-----------------------------------------------------------------*/
9198 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9199 /*-----------------------------------------------------------------*/
9200 static void shiftLLeftOrResult (operand *left, int offl,
9201 operand *result, int offr, int shCount)
9203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9206 /* shift left accumulator */
9208 /* or with result */
9209 /* back to result */
9210 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9213 /*-----------------------------------------------------------------*/
9214 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9215 /*-----------------------------------------------------------------*/
9216 static void shiftRLeftOrResult (operand *left, int offl,
9217 operand *result, int offr, int shCount)
9219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9221 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9222 /* shift right accumulator */
9224 /* or with result */
9225 /* back to result */
9226 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9229 /*-----------------------------------------------------------------*/
9230 /* genlshOne - left shift a one byte quantity by known count */
9231 /*-----------------------------------------------------------------*/
9232 static void genlshOne (operand *result, operand *left, int shCount)
9234 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9235 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9238 /*-----------------------------------------------------------------*/
9239 /* genlshTwo - left shift two bytes by known amount != 0 */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshTwo (operand *result,operand *left, int shCount)
9245 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9246 size = pic16_getDataSize(result);
9248 /* if shCount >= 8 */
9254 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9256 movLeft2Result(left, LSB, result, MSB16);
9258 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9261 /* 1 <= shCount <= 7 */
9264 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9266 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9270 /*-----------------------------------------------------------------*/
9271 /* shiftLLong - shift left one long from left to result */
9272 /* offr = LSB or MSB16 */
9273 /*-----------------------------------------------------------------*/
9274 static void shiftLLong (operand *left, operand *result, int offr )
9276 int size = AOP_SIZE(result);
9277 int same = pic16_sameRegs(AOP(left),AOP(result));
9280 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9282 if (same && (offr == MSB16)) { //shift one byte
9283 for(i=size-1;i>=MSB16;i--) {
9284 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9285 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9288 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9291 if (size > LSB+offr ){
9293 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9295 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9296 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9300 if(size > MSB16+offr){
9302 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9304 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9305 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9309 if(size > MSB24+offr){
9311 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9313 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9314 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9318 if(size > MSB32+offr){
9320 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9322 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9323 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9327 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9331 /*-----------------------------------------------------------------*/
9332 /* genlshFour - shift four byte by a known amount != 0 */
9333 /*-----------------------------------------------------------------*/
9334 static void genlshFour (operand *result, operand *left, int shCount)
9338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9339 size = AOP_SIZE(result);
9341 /* if shifting more that 3 bytes */
9342 if (shCount >= 24 ) {
9345 /* lowest order of left goes to the highest
9346 order of the destination */
9347 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9349 movLeft2Result(left, LSB, result, MSB32);
9351 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9352 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9353 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9358 /* more than two bytes */
9359 else if ( shCount >= 16 ) {
9360 /* lower order two bytes goes to higher order two bytes */
9362 /* if some more remaining */
9364 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9366 movLeft2Result(left, MSB16, result, MSB32);
9367 movLeft2Result(left, LSB, result, MSB24);
9369 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9370 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9374 /* if more than 1 byte */
9375 else if ( shCount >= 8 ) {
9376 /* lower order three bytes goes to higher order three bytes */
9380 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9382 movLeft2Result(left, LSB, result, MSB16);
9384 else{ /* size = 4 */
9386 movLeft2Result(left, MSB24, result, MSB32);
9387 movLeft2Result(left, MSB16, result, MSB24);
9388 movLeft2Result(left, LSB, result, MSB16);
9389 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9391 else if(shCount == 1)
9392 shiftLLong(left, result, MSB16);
9394 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9395 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9396 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9397 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9402 /* 1 <= shCount <= 7 */
9403 else if(shCount <= 3)
9405 shiftLLong(left, result, LSB);
9406 while(--shCount >= 1)
9407 shiftLLong(result, result, LSB);
9409 /* 3 <= shCount <= 7, optimize */
9411 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9412 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9413 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9417 /*-----------------------------------------------------------------*/
9418 /* genLeftShiftLiteral - left shifting by known count */
9419 /*-----------------------------------------------------------------*/
9420 void pic16_genLeftShiftLiteral (operand *left,
9425 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9429 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9430 pic16_freeAsmop(right,NULL,ic,TRUE);
9432 pic16_aopOp(left,ic,FALSE);
9433 pic16_aopOp(result,ic,TRUE);
9435 size = getSize(operandType(result));
9438 pic16_emitcode("; shift left ","result %d, left %d",size,
9442 /* I suppose that the left size >= result size */
9445 movLeft2Result(left, size, result, size);
9449 else if(shCount >= (size * 8))
9451 pic16_aopPut(AOP(result),zero,size);
9455 genlshOne (result,left,shCount);
9460 genlshTwo (result,left,shCount);
9464 genlshFour (result,left,shCount);
9468 pic16_freeAsmop(left,NULL,ic,TRUE);
9469 pic16_freeAsmop(result,NULL,ic,TRUE);
9472 /*-----------------------------------------------------------------*
9473 * genMultiAsm - repeat assembly instruction for size of register.
9474 * if endian == 1, then the high byte (i.e base address + size of
9475 * register) is used first else the low byte is used first;
9476 *-----------------------------------------------------------------*/
9477 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9482 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9495 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9501 #if !(USE_GENERIC_SIGNED_SHIFT)
9502 /*-----------------------------------------------------------------*/
9503 /* genLeftShift - generates code for left shifting */
9504 /*-----------------------------------------------------------------*/
9505 static void genLeftShift (iCode *ic)
9507 operand *left,*right, *result;
9510 symbol *tlbl , *tlbl1;
9513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9515 right = IC_RIGHT(ic);
9517 result = IC_RESULT(ic);
9519 pic16_aopOp(right,ic,FALSE);
9521 /* if the shift count is known then do it
9522 as efficiently as possible */
9523 if (AOP_TYPE(right) == AOP_LIT) {
9524 pic16_genLeftShiftLiteral (left,right,result,ic);
9528 /* shift count is unknown then we have to form
9529 * a loop. Get the loop count in WREG : Note: we take
9530 * only the lower order byte since shifting
9531 * more than 32 bits make no sense anyway, ( the
9532 * largest size of an object can be only 32 bits ) */
9534 pic16_aopOp(left,ic,FALSE);
9535 pic16_aopOp(result,ic,FALSE);
9537 /* now move the left to the result if they are not the
9538 * same, and if size > 1,
9539 * and if right is not same to result (!!!) -- VR */
9540 if (!pic16_sameRegs(AOP(left),AOP(result))
9541 && (AOP_SIZE(result) > 1)) {
9543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 size = AOP_SIZE(result);
9550 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9551 if (*l == '@' && (IS_AOP_PREG(result))) {
9553 pic16_emitcode("mov","a,%s",l);
9554 pic16_aopPut(AOP(result),"a",offset);
9558 /* we don't know if left is a literal or a register, take care -- VR */
9559 pic16_mov2f(AOP(result), AOP(left), offset);
9565 size = AOP_SIZE(result);
9567 /* if it is only one byte then */
9569 if(optimized_for_speed) {
9570 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9571 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9572 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9573 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9574 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9575 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9576 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9577 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9578 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9579 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9580 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9581 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9584 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9586 tlbl = newiTempLabel(NULL);
9589 /* this is already done, why change it? */
9590 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9591 pic16_mov2f(AOP(result), AOP(left), 0);
9595 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9596 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9597 pic16_emitpLabel(tlbl->key);
9598 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9599 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9606 if (pic16_sameRegs(AOP(left),AOP(result))) {
9608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9610 tlbl = newiTempLabel(NULL);
9611 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9612 genMultiAsm(POC_RRCF, result, size,1);
9613 pic16_emitpLabel(tlbl->key);
9614 genMultiAsm(POC_RLCF, result, size,0);
9615 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9617 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9621 //tlbl = newiTempLabel(NULL);
9623 //tlbl1 = newiTempLabel(NULL);
9625 //reAdjustPreg(AOP(result));
9627 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9628 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9629 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9631 //pic16_emitcode("add","a,acc");
9632 //pic16_aopPut(AOP(result),"a",offset++);
9634 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9636 // pic16_emitcode("rlc","a");
9637 // pic16_aopPut(AOP(result),"a",offset++);
9639 //reAdjustPreg(AOP(result));
9641 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9642 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9645 tlbl = newiTempLabel(NULL);
9646 tlbl1= newiTempLabel(NULL);
9648 size = AOP_SIZE(result);
9651 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9655 /* offset should be 0, 1 or 3 */
9657 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9659 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9661 pic16_emitpcode(POC_MOVWF, pctemp);
9664 pic16_emitpLabel(tlbl->key);
9667 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9669 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9671 pic16_emitpcode(POC_DECFSZ, pctemp);
9672 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9673 pic16_emitpLabel(tlbl1->key);
9675 pic16_popReleaseTempReg(pctemp,1);
9679 pic16_freeAsmop (right,NULL,ic,TRUE);
9680 pic16_freeAsmop(left,NULL,ic,TRUE);
9681 pic16_freeAsmop(result,NULL,ic,TRUE);
9687 #error old code (left here for reference)
9688 /*-----------------------------------------------------------------*/
9689 /* genLeftShift - generates code for left shifting */
9690 /*-----------------------------------------------------------------*/
9691 static void genLeftShift (iCode *ic)
9693 operand *left,*right, *result;
9696 symbol *tlbl , *tlbl1;
9699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9701 right = IC_RIGHT(ic);
9703 result = IC_RESULT(ic);
9705 pic16_aopOp(right,ic,FALSE);
9707 /* if the shift count is known then do it
9708 as efficiently as possible */
9709 if (AOP_TYPE(right) == AOP_LIT) {
9710 pic16_genLeftShiftLiteral (left,right,result,ic);
9714 /* shift count is unknown then we have to form
9715 a loop get the loop count in B : Note: we take
9716 only the lower order byte since shifting
9717 more that 32 bits make no sense anyway, ( the
9718 largest size of an object can be only 32 bits ) */
9721 pic16_aopOp(left,ic,FALSE);
9722 pic16_aopOp(result,ic,FALSE);
9724 /* now move the left to the result if they are not the
9726 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9727 AOP_SIZE(result) > 1) {
9729 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9731 size = AOP_SIZE(result);
9734 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9735 if (*l == '@' && (IS_AOP_PREG(result))) {
9737 pic16_emitcode("mov","a,%s",l);
9738 pic16_aopPut(AOP(result),"a",offset);
9741 /* we don't know if left is a literal or a register, take care -- VR */
9742 pic16_mov2f(AOP(result), AOP(left), offset);
9748 size = AOP_SIZE(result);
9750 /* if it is only one byte then */
9752 if(optimized_for_speed) {
9753 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9754 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9755 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9756 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9758 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9759 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9760 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9762 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9763 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9764 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9769 tlbl = newiTempLabel(NULL);
9770 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9771 pic16_mov2f(AOP(result), AOP(left), 0);
9773 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9774 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9777 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9778 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9779 pic16_emitpLabel(tlbl->key);
9780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9781 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9783 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9788 if (pic16_sameRegs(AOP(left),AOP(result))) {
9790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9792 tlbl = newiTempLabel(NULL);
9793 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9794 genMultiAsm(POC_RRCF, result, size,1);
9795 pic16_emitpLabel(tlbl->key);
9796 genMultiAsm(POC_RLCF, result, size,0);
9797 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9803 //tlbl = newiTempLabel(NULL);
9805 //tlbl1 = newiTempLabel(NULL);
9807 //reAdjustPreg(AOP(result));
9809 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9810 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9811 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9813 //pic16_emitcode("add","a,acc");
9814 //pic16_aopPut(AOP(result),"a",offset++);
9816 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9818 // pic16_emitcode("rlc","a");
9819 // pic16_aopPut(AOP(result),"a",offset++);
9821 //reAdjustPreg(AOP(result));
9823 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9824 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9827 tlbl = newiTempLabel(NULL);
9828 tlbl1= newiTempLabel(NULL);
9830 size = AOP_SIZE(result);
9833 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9835 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9837 /* offset should be 0, 1 or 3 */
9839 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9841 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9843 pic16_emitpcode(POC_MOVWF, pctemp);
9846 pic16_emitpLabel(tlbl->key);
9849 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9851 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9853 pic16_emitpcode(POC_DECFSZ, pctemp);
9854 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9855 pic16_emitpLabel(tlbl1->key);
9857 pic16_popReleaseTempReg(pctemp,1);
9861 pic16_freeAsmop (right,NULL,ic,TRUE);
9862 pic16_freeAsmop(left,NULL,ic,TRUE);
9863 pic16_freeAsmop(result,NULL,ic,TRUE);
9867 /*-----------------------------------------------------------------*/
9868 /* genrshOne - right shift a one byte quantity by known count */
9869 /*-----------------------------------------------------------------*/
9870 static void genrshOne (operand *result, operand *left,
9871 int shCount, int sign)
9873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9874 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9877 /*-----------------------------------------------------------------*/
9878 /* genrshTwo - right shift two bytes by known amount != 0 */
9879 /*-----------------------------------------------------------------*/
9880 static void genrshTwo (operand *result,operand *left,
9881 int shCount, int sign)
9883 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9884 /* if shCount >= 8 */
9888 shiftR1Left2Result(left, MSB16, result, LSB,
9891 movLeft2Result(left, MSB16, result, LSB);
9893 pic16_addSign (result, 1, sign);
9896 /* 1 <= shCount <= 7 */
9898 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9901 /*-----------------------------------------------------------------*/
9902 /* shiftRLong - shift right one long from left to result */
9903 /* offl = LSB or MSB16 */
9904 /*-----------------------------------------------------------------*/
9905 static void shiftRLong (operand *left, int offl,
9906 operand *result, int sign)
9908 int size = AOP_SIZE(result);
9909 int same = pic16_sameRegs(AOP(left),AOP(result));
9911 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9913 if (same && (offl == MSB16)) { //shift one byte right
9914 for(i=MSB16;i<size;i++) {
9915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9916 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9921 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9927 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9929 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9934 /* add sign of "a" */
9935 pic16_addSign(result, MSB32, sign);
9939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9953 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9956 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9957 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9962 /*-----------------------------------------------------------------*/
9963 /* genrshFour - shift four byte by a known amount != 0 */
9964 /*-----------------------------------------------------------------*/
9965 static void genrshFour (operand *result, operand *left,
9966 int shCount, int sign)
9968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9969 /* if shifting more that 3 bytes */
9970 if(shCount >= 24 ) {
9973 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9975 movLeft2Result(left, MSB32, result, LSB);
9977 pic16_addSign(result, MSB16, sign);
9979 else if(shCount >= 16){
9982 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9984 movLeft2Result(left, MSB24, result, LSB);
9985 movLeft2Result(left, MSB32, result, MSB16);
9987 pic16_addSign(result, MSB24, sign);
9989 else if(shCount >= 8){
9992 shiftRLong(left, MSB16, result, sign);
9993 else if(shCount == 0){
9994 movLeft2Result(left, MSB16, result, LSB);
9995 movLeft2Result(left, MSB24, result, MSB16);
9996 movLeft2Result(left, MSB32, result, MSB24);
9997 pic16_addSign(result, MSB32, sign);
9999 else{ //shcount >= 2
10000 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10001 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10002 /* the last shift is signed */
10003 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10004 pic16_addSign(result, MSB32, sign);
10007 else{ /* 1 <= shCount <= 7 */
10009 shiftRLong(left, LSB, result, sign);
10011 shiftRLong(result, LSB, result, sign);
10014 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10015 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10016 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10021 /*-----------------------------------------------------------------*/
10022 /* genRightShiftLiteral - right shifting by known count */
10023 /*-----------------------------------------------------------------*/
10024 static void genRightShiftLiteral (operand *left,
10030 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10031 int lsize,res_size;
10033 pic16_freeAsmop(right,NULL,ic,TRUE);
10035 pic16_aopOp(left,ic,FALSE);
10036 pic16_aopOp(result,ic,TRUE);
10038 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10041 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10045 lsize = pic16_getDataSize(left);
10046 res_size = pic16_getDataSize(result);
10047 /* test the LEFT size !!! */
10049 /* I suppose that the left size >= result size */
10051 assert (res_size <= lsize);
10052 while (res_size--) {
10053 pic16_mov2f (AOP(result), AOP(left), res_size);
10057 else if(shCount >= (lsize * 8)){
10059 if(res_size == 1) {
10060 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10062 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10068 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10069 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10077 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10082 switch (res_size) {
10084 genrshOne (result,left,shCount,sign);
10088 genrshTwo (result,left,shCount,sign);
10092 genrshFour (result,left,shCount,sign);
10100 pic16_freeAsmop(left,NULL,ic,TRUE);
10101 pic16_freeAsmop(result,NULL,ic,TRUE);
10104 #if !(USE_GENERIC_SIGNED_SHIFT)
10105 /*-----------------------------------------------------------------*/
10106 /* genSignedRightShift - right shift of signed number */
10107 /*-----------------------------------------------------------------*/
10108 static void genSignedRightShift (iCode *ic)
10110 operand *right, *left, *result;
10113 symbol *tlbl, *tlbl1 ;
10116 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10118 /* we do it the hard way put the shift count in b
10119 and loop thru preserving the sign */
10120 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10122 right = IC_RIGHT(ic);
10123 left = IC_LEFT(ic);
10124 result = IC_RESULT(ic);
10126 pic16_aopOp(right,ic,FALSE);
10127 pic16_aopOp(left,ic,FALSE);
10128 pic16_aopOp(result,ic,FALSE);
10131 if ( AOP_TYPE(right) == AOP_LIT) {
10132 genRightShiftLiteral (left,right,result,ic,1);
10135 /* shift count is unknown then we have to form
10136 a loop get the loop count in B : Note: we take
10137 only the lower order byte since shifting
10138 more that 32 bits make no sense anyway, ( the
10139 largest size of an object can be only 32 bits ) */
10141 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10142 //pic16_emitcode("inc","b");
10143 //pic16_freeAsmop (right,NULL,ic,TRUE);
10144 //pic16_aopOp(left,ic,FALSE);
10145 //pic16_aopOp(result,ic,FALSE);
10147 /* now move the left to the result if they are not the
10149 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10150 AOP_SIZE(result) > 1) {
10152 size = AOP_SIZE(result);
10156 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10157 if (*l == '@' && IS_AOP_PREG(result)) {
10159 pic16_emitcode("mov","a,%s",l);
10160 pic16_aopPut(AOP(result),"a",offset);
10162 pic16_aopPut(AOP(result),l,offset);
10164 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10165 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10171 /* mov the highest order bit to OVR */
10172 tlbl = newiTempLabel(NULL);
10173 tlbl1= newiTempLabel(NULL);
10175 size = AOP_SIZE(result);
10178 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10180 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10182 /* offset should be 0, 1 or 3 */
10183 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10185 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10187 pic16_emitpcode(POC_MOVWF, pctemp);
10190 pic16_emitpLabel(tlbl->key);
10192 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10193 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10196 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10199 pic16_emitpcode(POC_DECFSZ, pctemp);
10200 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10201 pic16_emitpLabel(tlbl1->key);
10203 pic16_popReleaseTempReg(pctemp,1);
10205 size = AOP_SIZE(result);
10207 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10208 pic16_emitcode("rlc","a");
10209 pic16_emitcode("mov","ov,c");
10210 /* if it is only one byte then */
10212 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10214 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10215 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10216 pic16_emitcode("mov","c,ov");
10217 pic16_emitcode("rrc","a");
10218 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10219 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10220 pic16_aopPut(AOP(result),"a",0);
10224 reAdjustPreg(AOP(result));
10225 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10227 pic16_emitcode("mov","c,ov");
10229 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10231 pic16_emitcode("rrc","a");
10232 pic16_aopPut(AOP(result),"a",offset--);
10234 reAdjustPreg(AOP(result));
10235 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10241 pic16_freeAsmop(left,NULL,ic,TRUE);
10242 pic16_freeAsmop(result,NULL,ic,TRUE);
10243 pic16_freeAsmop(right,NULL,ic,TRUE);
10247 #if !(USE_GENERIC_SIGNED_SHIFT)
10248 #warning This implementation of genRightShift() is incomplete!
10249 /*-----------------------------------------------------------------*/
10250 /* genRightShift - generate code for right shifting */
10251 /*-----------------------------------------------------------------*/
10252 static void genRightShift (iCode *ic)
10254 operand *right, *left, *result;
10258 symbol *tlbl, *tlbl1 ;
10260 /* if signed then we do it the hard way preserve the
10261 sign bit moving it inwards */
10262 letype = getSpec(operandType(IC_LEFT(ic)));
10263 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10265 if (!SPEC_USIGN(letype)) {
10266 genSignedRightShift (ic);
10270 /* signed & unsigned types are treated the same : i.e. the
10271 signed is NOT propagated inwards : quoting from the
10272 ANSI - standard : "for E1 >> E2, is equivalent to division
10273 by 2**E2 if unsigned or if it has a non-negative value,
10274 otherwise the result is implementation defined ", MY definition
10275 is that the sign does not get propagated */
10277 right = IC_RIGHT(ic);
10278 left = IC_LEFT(ic);
10279 result = IC_RESULT(ic);
10281 pic16_aopOp(right,ic,FALSE);
10283 /* if the shift count is known then do it
10284 as efficiently as possible */
10285 if (AOP_TYPE(right) == AOP_LIT) {
10286 genRightShiftLiteral (left,right,result,ic, 0);
10290 /* shift count is unknown then we have to form
10291 a loop get the loop count in B : Note: we take
10292 only the lower order byte since shifting
10293 more that 32 bits make no sense anyway, ( the
10294 largest size of an object can be only 32 bits ) */
10296 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10297 pic16_emitcode("inc","b");
10298 pic16_aopOp(left,ic,FALSE);
10299 pic16_aopOp(result,ic,FALSE);
10301 /* now move the left to the result if they are not the
10303 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10304 AOP_SIZE(result) > 1) {
10306 size = AOP_SIZE(result);
10309 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10310 if (*l == '@' && IS_AOP_PREG(result)) {
10312 pic16_emitcode("mov","a,%s",l);
10313 pic16_aopPut(AOP(result),"a",offset);
10315 pic16_aopPut(AOP(result),l,offset);
10320 tlbl = newiTempLabel(NULL);
10321 tlbl1= newiTempLabel(NULL);
10322 size = AOP_SIZE(result);
10325 /* if it is only one byte then */
10328 tlbl = newiTempLabel(NULL);
10329 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10330 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10334 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10335 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10336 pic16_emitpLabel(tlbl->key);
10337 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10338 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10340 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10345 reAdjustPreg(AOP(result));
10346 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10347 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10350 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10352 pic16_emitcode("rrc","a");
10353 pic16_aopPut(AOP(result),"a",offset--);
10355 reAdjustPreg(AOP(result));
10357 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10358 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10361 pic16_freeAsmop(left,NULL,ic,TRUE);
10362 pic16_freeAsmop (right,NULL,ic,TRUE);
10363 pic16_freeAsmop(result,NULL,ic,TRUE);
10367 #if (USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genGenericShift - generates code for left or right shifting */
10370 /*-----------------------------------------------------------------*/
10371 static void genGenericShift (iCode *ic, int isShiftLeft) {
10372 operand *left,*right, *result;
10374 int sign, signedCount;
10375 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10376 PIC_OPCODE pos_shift, neg_shift;
10380 right = IC_RIGHT(ic);
10381 left = IC_LEFT(ic);
10382 result = IC_RESULT(ic);
10384 pic16_aopOp(right,ic,FALSE);
10385 pic16_aopOp(left,ic,FALSE);
10386 pic16_aopOp(result,ic,TRUE);
10388 sign = !SPEC_USIGN(operandType (left));
10389 signedCount = !SPEC_USIGN(operandType (right));
10391 /* if the shift count is known then do it
10392 as efficiently as possible */
10393 if (AOP_TYPE(right) == AOP_LIT) {
10394 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10395 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10396 // we should modify right->aopu.aop_lit here!
10397 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10398 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10400 pic16_genLeftShiftLiteral (left,right,result,ic);
10402 genRightShiftLiteral (left,right,result,ic, sign);
10405 } // if (right is literal)
10407 /* shift count is unknown then we have to form a loop.
10408 * Note: we take only the lower order byte since shifting
10409 * more than 32 bits make no sense anyway, ( the
10410 * largest size of an object can be only 32 bits )
10411 * Note: we perform arithmetic shifts if the left operand is
10412 * signed and we do an (effective) right shift, i. e. we
10413 * shift in the sign bit from the left. */
10415 label_complete = newiTempLabel ( NULL );
10416 label_loop_pos = newiTempLabel ( NULL );
10417 label_loop_neg = NULL;
10418 label_negative = NULL;
10419 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10420 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10423 // additional labels needed
10424 label_loop_neg = newiTempLabel ( NULL );
10425 label_negative = newiTempLabel ( NULL );
10428 // copy source to result -- this will effectively truncate the left operand to the size of result!
10429 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10430 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10431 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10432 pic16_mov2f (AOP(result),AOP(left), offset);
10435 // if result is longer than left, fill with zeros (or sign)
10436 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10437 if (sign && AOP_SIZE(left) > 0) {
10438 // shift signed operand -- fill with sign
10439 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10440 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10441 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10442 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10446 // shift unsigned operand -- fill result with zeros
10447 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10451 } // if (size mismatch)
10453 pic16_mov2w (AOP(right), 0);
10454 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10455 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10458 // perform a shift by one (shift count is positive)
10459 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460 // 2n+[2,3]+({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])
10461 pic16_emitpLabel (label_loop_pos->key);
10463 if (sign && (pos_shift == POC_RRCF)) {
10464 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10467 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10468 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10469 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10471 // perform a shift by one (shift count is positive)
10472 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10473 // 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])
10474 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10475 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10477 pic16_emitpLabel (label_loop_pos->key);
10478 if (sign && (pos_shift == POC_RRCF)) {
10479 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10482 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10483 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10484 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10485 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10489 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10491 pic16_emitpLabel (label_negative->key);
10492 // perform a shift by -1 (shift count is negative)
10493 // 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)
10495 pic16_emitpLabel (label_loop_neg->key);
10496 if (sign && (neg_shift == POC_RRCF)) {
10497 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10500 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10501 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10502 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10503 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10504 } // if (signedCount)
10506 pic16_emitpLabel (label_complete->key);
10509 pic16_freeAsmop (right,NULL,ic,TRUE);
10510 pic16_freeAsmop(left,NULL,ic,TRUE);
10511 pic16_freeAsmop(result,NULL,ic,TRUE);
10514 static void genLeftShift (iCode *ic) {
10515 genGenericShift (ic, 1);
10518 static void genRightShift (iCode *ic) {
10519 genGenericShift (ic, 0);
10524 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10525 void pic16_loadFSR0(operand *op, int lit)
10527 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10528 if (AOP_TYPE(op) == AOP_LIT) {
10529 /* handle 12 bit integers correctly */
10530 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10531 if ((val & 0x0fff) != val) {
10532 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10533 val, (val & 0x0fff) );
10536 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10538 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10541 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10542 // set up FSR0 with address of result
10543 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10544 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10548 /*----------------------------------------------------------------*/
10549 /* pic16_derefPtr - move one byte from the location ptr points to */
10550 /* to WREG (doWrite == 0) or one byte from WREG */
10551 /* to the location ptr points to (doWrite != 0) */
10552 /*----------------------------------------------------------------*/
10553 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10555 if (!IS_PTR(operandType(ptr)))
10557 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10558 else pic16_mov2w (AOP(ptr), 0);
10562 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10563 /* We might determine pointer type right here: */
10564 p_type = DCL_TYPE(operandType(ptr));
10569 if (!fsr0_setup || !*fsr0_setup)
10571 pic16_loadFSR0( ptr, 0 );
10572 if (fsr0_setup) *fsr0_setup = 1;
10575 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10577 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10581 if (AOP(ptr)->aopu.aop_reg[2]) {
10582 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10583 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10584 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10585 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10586 pic16_mov2w(AOP(ptr), 2);
10587 pic16_callGenericPointerRW(doWrite, 1);
10589 // data pointer (just 2 byte given)
10590 if (!fsr0_setup || !*fsr0_setup)
10592 pic16_loadFSR0( ptr, 0 );
10593 if (fsr0_setup) *fsr0_setup = 1;
10596 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10598 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10603 assert (0 && "invalid pointer type specified");
10608 /*-----------------------------------------------------------------*/
10609 /* genUnpackBits - generates code for unpacking bits */
10610 /*-----------------------------------------------------------------*/
10611 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10614 sym_link *etype, *letype;
10615 int blen=0, bstr=0;
10620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10621 etype = getSpec(operandType(result));
10622 letype = getSpec(operandType(left));
10624 // if(IS_BITFIELD(etype)) {
10625 blen = SPEC_BLEN(etype);
10626 bstr = SPEC_BSTR(etype);
10629 lbstr = SPEC_BSTR( letype );
10631 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10632 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10635 if((blen == 1) && (bstr < 8)
10636 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10637 /* it is a single bit, so use the appropriate bit instructions */
10638 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10640 same = pic16_sameRegs(AOP(left),AOP(result));
10641 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10642 pic16_emitpcode(POC_CLRF, op);
10644 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10645 /* workaround to reduce the extra lfsr instruction */
10646 pic16_emitpcode(POC_BTFSC,
10647 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10649 assert (PIC_IS_DATA_PTR (operandType(left)));
10650 pic16_loadFSR0 (left, 0);
10651 pic16_emitpcode(POC_BTFSC,
10652 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10655 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10656 /* unsigned bitfields result in either 0 or 1 */
10657 pic16_emitpcode(POC_INCF, op);
10659 /* signed bitfields result in either 0 or -1 */
10660 pic16_emitpcode(POC_DECF, op);
10663 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10666 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10672 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10673 // access symbol directly
10674 pic16_mov2w (AOP(left), 0);
10676 pic16_derefPtr (left, ptype, 0, NULL);
10679 /* if we have bitdisplacement then it fits */
10680 /* into this byte completely or if length is */
10681 /* less than a byte */
10682 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10684 /* shift right acc */
10687 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10688 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10690 /* VR -- normally I would use the following, but since we use the hack,
10691 * to avoid the masking from AccRsh, why not mask it right now? */
10694 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10697 /* extend signed bitfields to 8 bits */
10698 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10700 assert (blen + bstr > 0);
10701 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10702 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10707 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10711 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10712 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10719 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10721 int size, offset = 0, leoffset=0 ;
10723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10724 pic16_aopOp(result, ic, TRUE);
10728 size = AOP_SIZE(result);
10729 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10733 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10734 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10735 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10740 if(AOP(left)->aopu.pcop->type == PO_DIR)
10741 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10743 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10746 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10748 // pic16_DumpOp("(result)",result);
10749 if(is_LitAOp(AOP(result))) {
10750 pic16_mov2w(AOP(left), offset); // patch 8
10751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10753 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10754 pic16_popGet(AOP(left), offset), //patch 8
10755 pic16_popGet(AOP(result), offset)));
10763 pic16_freeAsmop(result,NULL,ic,TRUE);
10768 /*-----------------------------------------------------------------*/
10769 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10770 /*-----------------------------------------------------------------*/
10771 static void genNearPointerGet (operand *left,
10775 // asmop *aop = NULL;
10776 //regs *preg = NULL ;
10777 sym_link *rtype, *retype;
10778 sym_link *ltype, *letype;
10782 rtype = operandType(result);
10783 retype= getSpec(rtype);
10784 ltype = operandType(left);
10785 letype= getSpec(ltype);
10787 pic16_aopOp(left,ic,FALSE);
10789 // pic16_DumpOp("(left)",left);
10790 // pic16_DumpOp("(result)",result);
10792 /* if left is rematerialisable and
10793 * result is not bit variable type and
10794 * the left is pointer to data space i.e
10795 * lower 128 bytes of space */
10797 if (AOP_TYPE(left) == AOP_PCODE
10798 && !IS_BITFIELD(retype)
10799 && DCL_TYPE(ltype) == POINTER) {
10801 genDataPointerGet (left,result,ic);
10802 pic16_freeAsmop(left, NULL, ic, TRUE);
10806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10807 pic16_aopOp (result,ic,TRUE);
10809 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10812 if(IS_BITFIELD( retype )
10813 && (SPEC_BLEN(operandType(result))==1)
10817 int bitstrt, bytestrt;
10819 /* if this is bitfield of size 1, see if we are checking the value
10820 * of a single bit in an if-statement,
10821 * if yes, then don't generate usual code, but execute the
10822 * genIfx directly -- VR */
10826 /* CHECK: if next iCode is IFX
10827 * and current result operand is nextic's conditional operand
10828 * and current result operand live ranges ends at nextic's key number
10830 if((nextic->op == IFX)
10831 && (result == IC_COND(nextic))
10832 && (OP_LIVETO(result) == nextic->seq)
10833 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10835 /* everything is ok then */
10836 /* find a way to optimize the genIfx iCode */
10838 bytestrt = SPEC_BSTR(operandType(result))/8;
10839 bitstrt = SPEC_BSTR(operandType(result))%8;
10841 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10843 genIfxpCOpJump(nextic, jop);
10845 pic16_freeAsmop(left, NULL, ic, TRUE);
10846 pic16_freeAsmop(result, NULL, ic, TRUE);
10852 /* if bitfield then unpack the bits */
10853 if (IS_BITFIELD(letype))
10854 genUnpackBits (result, left, NULL, POINTER);
10856 /* we have can just get the values */
10857 int size = AOP_SIZE(result);
10860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10862 pic16_loadFSR0( left, 0 );
10866 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10867 pic16_popGet(AOP(result), offset++)));
10869 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10870 pic16_popGet(AOP(result), offset++)));
10876 /* now some housekeeping stuff */
10878 /* we had to allocate for this iCode */
10879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10880 pic16_freeAsmop(NULL,aop,ic,TRUE);
10882 /* we did not allocate which means left
10883 * already in a pointer register, then
10884 * if size > 0 && this could be used again
10885 * we have to point it back to where it
10887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10888 if (AOP_SIZE(result) > 1
10889 && !OP_SYMBOL(left)->remat
10890 && ( OP_SYMBOL(left)->liveTo > ic->seq
10892 // int size = AOP_SIZE(result) - 1;
10894 // pic16_emitcode("dec","%s",rname);
10900 pic16_freeAsmop(left,NULL,ic,TRUE);
10901 pic16_freeAsmop(result,NULL,ic,TRUE);
10904 /*-----------------------------------------------------------------*/
10905 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10906 /*-----------------------------------------------------------------*/
10907 static void genPagedPointerGet (operand *left,
10912 regs *preg = NULL ;
10914 sym_link *rtype, *retype;
10916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10918 rtype = operandType(result);
10919 retype= getSpec(rtype);
10921 pic16_aopOp(left,ic,FALSE);
10923 /* if the value is already in a pointer register
10924 then don't need anything more */
10925 if (!AOP_INPREG(AOP(left))) {
10926 /* otherwise get a free pointer register */
10928 preg = getFreePtr(ic,&aop,FALSE);
10929 pic16_emitcode("mov","%s,%s",
10931 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10932 rname = preg->name ;
10934 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10936 pic16_freeAsmop(left,NULL,ic,TRUE);
10937 pic16_aopOp (result,ic,TRUE);
10939 /* if bitfield then unpack the bits */
10940 if (IS_BITFIELD(retype))
10941 genUnpackBits (result,left,rname,PPOINTER);
10943 /* we have can just get the values */
10944 int size = AOP_SIZE(result);
10949 pic16_emitcode("movx","a,@%s",rname);
10950 pic16_aopPut(AOP(result),"a",offset);
10955 pic16_emitcode("inc","%s",rname);
10959 /* now some housekeeping stuff */
10961 /* we had to allocate for this iCode */
10962 pic16_freeAsmop(NULL,aop,ic,TRUE);
10964 /* we did not allocate which means left
10965 already in a pointer register, then
10966 if size > 0 && this could be used again
10967 we have to point it back to where it
10969 if (AOP_SIZE(result) > 1 &&
10970 !OP_SYMBOL(left)->remat &&
10971 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10973 int size = AOP_SIZE(result) - 1;
10975 pic16_emitcode("dec","%s",rname);
10980 pic16_freeAsmop(result,NULL,ic,TRUE);
10986 /* This code is not adjusted to PIC16 and fails utterly.
10987 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10989 /*-----------------------------------------------------------------*/
10990 /* genFarPointerGet - gget value from far space */
10991 /*-----------------------------------------------------------------*/
10992 static void genFarPointerGet (operand *left,
10993 operand *result, iCode *ic)
10996 sym_link *retype = getSpec(operandType(result));
10998 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11000 pic16_aopOp(left,ic,FALSE);
11002 /* if the operand is already in dptr
11003 then we do nothing else we move the value to dptr */
11004 if (AOP_TYPE(left) != AOP_STR) {
11005 /* if this is remateriazable */
11006 if (AOP_TYPE(left) == AOP_IMMD)
11007 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11008 else { /* we need to get it byte by byte */
11009 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11010 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11011 if (options.model == MODEL_FLAT24)
11013 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11017 /* so dptr know contains the address */
11018 pic16_freeAsmop(left,NULL,ic,TRUE);
11019 pic16_aopOp(result,ic,TRUE);
11021 /* if bit then unpack */
11022 if (IS_BITFIELD(retype))
11023 genUnpackBits(result,left,"dptr",FPOINTER);
11025 size = AOP_SIZE(result);
11029 pic16_emitcode("movx","a,@dptr");
11030 pic16_aopPut(AOP(result),"a",offset++);
11032 pic16_emitcode("inc","dptr");
11036 pic16_freeAsmop(result,NULL,ic,TRUE);
11041 /*-----------------------------------------------------------------*/
11042 /* genCodePointerGet - get value from code space */
11043 /*-----------------------------------------------------------------*/
11044 static void genCodePointerGet (operand *left,
11045 operand *result, iCode *ic)
11048 sym_link *retype = getSpec(operandType(result));
11050 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11052 pic16_aopOp(left,ic,FALSE);
11054 /* if the operand is already in dptr
11055 then we do nothing else we move the value to dptr */
11056 if (AOP_TYPE(left) != AOP_STR) {
11057 /* if this is remateriazable */
11058 if (AOP_TYPE(left) == AOP_IMMD)
11059 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11060 else { /* we need to get it byte by byte */
11061 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11062 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11063 if (options.model == MODEL_FLAT24)
11065 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11069 /* so dptr know contains the address */
11070 pic16_freeAsmop(left,NULL,ic,TRUE);
11071 pic16_aopOp(result,ic,FALSE);
11073 /* if bit then unpack */
11074 if (IS_BITFIELD(retype))
11075 genUnpackBits(result,left,"dptr",CPOINTER);
11077 size = AOP_SIZE(result);
11081 pic16_emitcode("clr","a");
11082 pic16_emitcode("movc","a,@a+dptr");
11083 pic16_aopPut(AOP(result),"a",offset++);
11085 pic16_emitcode("inc","dptr");
11089 pic16_freeAsmop(result,NULL,ic,TRUE);
11094 /*-----------------------------------------------------------------*/
11095 /* genGenPointerGet - gget value from generic pointer space */
11096 /*-----------------------------------------------------------------*/
11097 static void genGenPointerGet (operand *left,
11098 operand *result, iCode *ic)
11100 int size, offset, lit;
11101 sym_link *retype = getSpec(operandType(result));
11103 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11104 pic16_aopOp(left,ic,FALSE);
11105 pic16_aopOp(result,ic,FALSE);
11106 size = AOP_SIZE(result);
11108 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11110 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11112 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11113 // load FSR0 from immediate
11114 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11116 // pic16_loadFSR0( left );
11121 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11130 else { /* we need to get it byte by byte */
11131 // set up FSR0 with address from left
11132 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11133 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11139 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11141 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11148 /* if bit then unpack */
11149 if (IS_BITFIELD(retype))
11150 genUnpackBits(result,left,"BAD",GPOINTER);
11153 pic16_freeAsmop(left,NULL,ic,TRUE);
11154 pic16_freeAsmop(result,NULL,ic,TRUE);
11160 /*-----------------------------------------------------------------*/
11161 /* genGenPointerGet - gget value from generic pointer space */
11162 /*-----------------------------------------------------------------*/
11163 static void genGenPointerGet (operand *left,
11164 operand *result, iCode *ic)
11166 int size, offset, lit;
11167 sym_link *letype = getSpec(operandType(left));
11169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11170 pic16_aopOp(left,ic,FALSE);
11171 pic16_aopOp(result,ic,TRUE);
11172 size = AOP_SIZE(result);
11174 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11176 /* if bit then unpack */
11177 if (IS_BITFIELD(letype)) {
11178 genUnpackBits(result,left,"BAD",GPOINTER);
11182 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11184 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11185 // load FSR0 from immediate
11186 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11188 werror(W_POSSBUG2, __FILE__, __LINE__);
11193 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11195 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11202 } else { /* we need to get it byte by byte */
11204 /* set up WREG:PRODL:FSR0L with address from left */
11205 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11206 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11207 pic16_mov2w(AOP(left), 2);
11208 pic16_callGenericPointerRW(0, size);
11210 assignResultValue(result, 1);
11216 pic16_freeAsmop(left,NULL,ic,TRUE);
11217 pic16_freeAsmop(result,NULL,ic,TRUE);
11220 /*-----------------------------------------------------------------*/
11221 /* genConstPointerGet - get value from const generic pointer space */
11222 /*-----------------------------------------------------------------*/
11223 static void genConstPointerGet (operand *left,
11224 operand *result, iCode *ic)
11226 //sym_link *retype = getSpec(operandType(result));
11227 // symbol *albl = newiTempLabel(NULL); // patch 15
11228 // symbol *blbl = newiTempLabel(NULL); //
11229 // PIC_OPCODE poc; // patch 15
11233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11234 pic16_aopOp(left,ic,FALSE);
11235 pic16_aopOp(result,ic,TRUE);
11236 size = AOP_SIZE(result);
11238 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11240 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11242 // set up table pointer
11243 if( (AOP_TYPE(left) == AOP_PCODE)
11244 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11245 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11247 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11248 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11249 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11250 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11251 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11252 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11254 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11255 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11256 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11260 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11261 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11265 pic16_freeAsmop(left,NULL,ic,TRUE);
11266 pic16_freeAsmop(result,NULL,ic,TRUE);
11270 /*-----------------------------------------------------------------*/
11271 /* genPointerGet - generate code for pointer get */
11272 /*-----------------------------------------------------------------*/
11273 static void genPointerGet (iCode *ic)
11275 operand *left, *result ;
11276 sym_link *type, *etype;
11281 left = IC_LEFT(ic);
11282 result = IC_RESULT(ic) ;
11284 /* depending on the type of pointer we need to
11285 move it to the correct pointer register */
11286 type = operandType(left);
11287 etype = getSpec(type);
11290 if (IS_PTR_CONST(type))
11292 if (IS_CODEPTR(type))
11294 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11296 /* if left is of type of pointer then it is simple */
11297 if (IS_PTR(type) && !IS_FUNC(type->next))
11298 p_type = DCL_TYPE(type);
11300 /* we have to go by the storage class */
11301 p_type = PTR_TYPE(SPEC_OCLS(etype));
11303 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11305 if (SPEC_OCLS(etype)->codesp ) {
11306 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11307 //p_type = CPOINTER ;
11309 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11310 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11311 /*p_type = FPOINTER ;*/
11313 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11314 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11315 /* p_type = PPOINTER; */
11317 if (SPEC_OCLS(etype) == idata ) {
11318 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11319 /* p_type = IPOINTER; */
11321 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11322 /* p_type = POINTER ; */
11326 /* now that we have the pointer type we assign
11327 the pointer values */
11332 genNearPointerGet (left,result,ic);
11336 genPagedPointerGet(left,result,ic);
11340 /* PICs do not support FAR pointers... */
11341 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11343 genFarPointerGet (left,result,ic);
11348 genConstPointerGet (left,result,ic);
11349 //pic16_emitcodePointerGet (left,result,ic);
11354 if (IS_PTR_CONST(type))
11355 genConstPointerGet (left,result,ic);
11358 genGenPointerGet (left,result,ic);
11362 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11363 "genPointerGet: illegal pointer type");
11368 /*-----------------------------------------------------------------*/
11369 /* genPackBits - generates code for packed bit storage */
11370 /*-----------------------------------------------------------------*/
11371 static void genPackBits (sym_link *etype , operand *result,
11373 char *rname, int p_type)
11379 int shifted_and_masked = 0;
11380 unsigned long lit = (unsigned long)-1;
11383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11384 blen = SPEC_BLEN(etype);
11385 bstr = SPEC_BSTR(etype);
11387 retype = getSpec(operandType(right));
11389 if(AOP_TYPE(right) == AOP_LIT) {
11390 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11392 if((blen == 1) && (bstr < 8)) {
11393 /* it is a single bit, so use the appropriate bit instructions */
11395 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11397 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11398 /* workaround to reduce the extra lfsr instruction */
11400 pic16_emitpcode(POC_BSF,
11401 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11403 pic16_emitpcode(POC_BCF,
11404 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11407 if (PIC_IS_DATA_PTR(operandType(result))) {
11408 pic16_loadFSR0(result, 0);
11409 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11410 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11412 /* get old value */
11413 pic16_derefPtr (result, p_type, 0, NULL);
11414 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11415 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11416 /* write back new value */
11417 pic16_derefPtr (result, p_type, 1, NULL);
11423 /* IORLW below is more efficient */
11424 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11425 lit = (lit & ((1UL << blen) - 1)) << bstr;
11426 shifted_and_masked = 1;
11429 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11430 && IS_BITFIELD(retype)
11431 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11435 rblen = SPEC_BLEN( retype );
11436 rbstr = SPEC_BSTR( retype );
11438 if(IS_BITFIELD(etype)) {
11439 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11440 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11442 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11445 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11447 if(IS_BITFIELD(etype)) {
11448 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11450 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11453 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11457 /* move right to W */
11458 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11461 /* if the bit length is less than or */
11462 /* it exactly fits a byte then */
11463 if((shCnt=SPEC_BSTR(etype))
11464 || SPEC_BLEN(etype) <= 8 ) {
11465 int fsr0_setup = 0;
11467 if (blen != 8 || bstr != 0) {
11468 // we need to combine the value with the old value
11469 if(!shifted_and_masked)
11471 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11473 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11474 SPEC_BSTR(etype), SPEC_BLEN(etype));
11476 /* shift left acc, do NOT mask the result again */
11479 /* using PRODH as a temporary register here */
11480 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11483 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11484 || IS_DIRECT(result)) {
11485 /* access symbol directly */
11486 pic16_mov2w (AOP(result), 0);
11488 /* get old value */
11489 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11492 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11493 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11494 (unsigned char)(0xff >> (8-bstr))) ));
11495 if (!shifted_and_masked) {
11496 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11498 /* We have the shifted and masked (literal) right value in `lit' */
11500 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11502 } // if (blen != 8 || bstr != 0)
11504 /* write new value back */
11505 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11506 || IS_DIRECT(result)) {
11507 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11509 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11518 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11519 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11524 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11525 rLen = SPEC_BLEN(etype)-8;
11527 /* now generate for lengths greater than one byte */
11531 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11543 pic16_emitcode("movx","@dptr,a");
11548 DEBUGpic16_emitcode(";lcall","__gptrput");
11556 pic16_mov2w(AOP(right), offset++);
11559 /* last last was not complete */
11561 /* save the byte & read byte */
11564 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11565 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11570 pic16_emitcode ("mov","b,a");
11571 pic16_emitcode("movx","a,@dptr");
11575 pic16_emitcode ("push","b");
11576 pic16_emitcode ("push","acc");
11577 pic16_emitcode ("lcall","__gptrget");
11578 pic16_emitcode ("pop","b");
11584 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11585 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11586 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11587 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11588 // pic16_emitcode ("orl","a,b");
11591 // if (p_type == GPOINTER)
11592 // pic16_emitcode("pop","b");
11597 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11598 // pic16_emitcode("mov","@%s,a",rname);
11602 pic16_emitcode("movx","@dptr,a");
11606 DEBUGpic16_emitcode(";lcall","__gptrput");
11613 // pic16_freeAsmop(right, NULL, ic, TRUE);
11616 /*-----------------------------------------------------------------*/
11617 /* genDataPointerSet - remat pointer to data space */
11618 /*-----------------------------------------------------------------*/
11619 static void genDataPointerSet(operand *right,
11623 int size, offset = 0, resoffset=0 ;
11625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11626 pic16_aopOp(right,ic,FALSE);
11628 size = AOP_SIZE(right);
11630 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11633 if ( AOP_TYPE(result) == AOP_PCODE) {
11634 fprintf(stderr,"genDataPointerSet %s, %d\n",
11635 AOP(result)->aopu.pcop->name,
11636 (AOP(result)->aopu.pcop->type == PO_DIR)?
11637 PCOR(AOP(result)->aopu.pcop)->instance:
11638 PCOI(AOP(result)->aopu.pcop)->offset);
11642 if(AOP(result)->aopu.pcop->type == PO_DIR)
11643 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11646 if (AOP_TYPE(right) == AOP_LIT) {
11649 if(!IS_FLOAT(operandType( right )))
11650 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11653 unsigned long lit_int;
11657 /* take care if literal is a float */
11658 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11659 lit = info.lit_int;
11661 lit = lit >> (8*offset);
11662 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11664 pic16_mov2w(AOP(right), offset);
11665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11671 pic16_freeAsmop(right,NULL,ic,TRUE);
11676 /*-----------------------------------------------------------------*/
11677 /* genNearPointerSet - pic16_emitcode for near pointer put */
11678 /*-----------------------------------------------------------------*/
11679 static void genNearPointerSet (operand *right,
11685 sym_link *ptype = operandType(result);
11686 sym_link *resetype;
11688 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11689 retype= getSpec(operandType(right));
11690 resetype = getSpec(operandType(result));
11692 pic16_aopOp(result,ic,FALSE);
11694 /* if the result is rematerializable &
11695 * in data space & not a bit variable */
11697 /* and result is not a bit variable */
11698 if (AOP_TYPE(result) == AOP_PCODE
11699 // && AOP_TYPE(result) == AOP_IMMD
11700 && DCL_TYPE(ptype) == POINTER
11701 && !IS_BITFIELD(retype)
11702 && !IS_BITFIELD(resetype)) {
11704 genDataPointerSet (right,result,ic);
11705 pic16_freeAsmop(result,NULL,ic,TRUE);
11709 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11710 pic16_aopOp(right,ic,FALSE);
11711 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11713 /* if bitfield then unpack the bits */
11714 if (IS_BITFIELD(resetype)) {
11715 genPackBits (resetype, result, right, NULL, POINTER);
11717 /* we have can just get the values */
11718 int size = AOP_SIZE(right);
11721 pic16_loadFSR0(result, 0);
11723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11725 if (AOP_TYPE(right) == AOP_LIT) {
11726 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11728 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11730 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11732 } else { // no literal
11734 pic16_emitpcode(POC_MOVFF,
11735 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11736 pic16_popCopyReg(&pic16_pc_postinc0)));
11738 pic16_emitpcode(POC_MOVFF,
11739 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11740 pic16_popCopyReg(&pic16_pc_indf0)));
11748 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11749 /* now some housekeeping stuff */
11751 /* we had to allocate for this iCode */
11752 pic16_freeAsmop(NULL,aop,ic,TRUE);
11754 /* we did not allocate which means left
11755 * already in a pointer register, then
11756 * if size > 0 && this could be used again
11757 * we have to point it back to where it
11759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11760 if (AOP_SIZE(right) > 1
11761 && !OP_SYMBOL(result)->remat
11762 && ( OP_SYMBOL(result)->liveTo > ic->seq
11765 int size = AOP_SIZE(right) - 1;
11768 pic16_emitcode("decf","fsr0,f");
11769 //pic16_emitcode("dec","%s",rname);
11773 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11776 pic16_freeAsmop(right,NULL,ic,TRUE);
11777 pic16_freeAsmop(result,NULL,ic,TRUE);
11780 /*-----------------------------------------------------------------*/
11781 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11782 /*-----------------------------------------------------------------*/
11783 static void genPagedPointerSet (operand *right,
11788 regs *preg = NULL ;
11792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11794 retype= getSpec(operandType(right));
11796 pic16_aopOp(result,ic,FALSE);
11798 /* if the value is already in a pointer register
11799 then don't need anything more */
11800 if (!AOP_INPREG(AOP(result))) {
11801 /* otherwise get a free pointer register */
11803 preg = getFreePtr(ic,&aop,FALSE);
11804 pic16_emitcode("mov","%s,%s",
11806 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11807 rname = preg->name ;
11809 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11811 pic16_freeAsmop(result,NULL,ic,TRUE);
11812 pic16_aopOp (right,ic,FALSE);
11814 /* if bitfield then unpack the bits */
11815 if (IS_BITFIELD(retype))
11816 genPackBits (retype,result,right,rname,PPOINTER);
11818 /* we have can just get the values */
11819 int size = AOP_SIZE(right);
11823 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11826 pic16_emitcode("movx","@%s,a",rname);
11829 pic16_emitcode("inc","%s",rname);
11835 /* now some housekeeping stuff */
11837 /* we had to allocate for this iCode */
11838 pic16_freeAsmop(NULL,aop,ic,TRUE);
11840 /* we did not allocate which means left
11841 already in a pointer register, then
11842 if size > 0 && this could be used again
11843 we have to point it back to where it
11845 if (AOP_SIZE(right) > 1 &&
11846 !OP_SYMBOL(result)->remat &&
11847 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11849 int size = AOP_SIZE(right) - 1;
11851 pic16_emitcode("dec","%s",rname);
11856 pic16_freeAsmop(right,NULL,ic,TRUE);
11862 /* This code is not adjusted to PIC16 and fails utterly...
11863 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11865 /*-----------------------------------------------------------------*/
11866 /* genFarPointerSet - set value from far space */
11867 /*-----------------------------------------------------------------*/
11868 static void genFarPointerSet (operand *right,
11869 operand *result, iCode *ic)
11872 sym_link *retype = getSpec(operandType(right));
11874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11875 pic16_aopOp(result,ic,FALSE);
11877 /* if the operand is already in dptr
11878 then we do nothing else we move the value to dptr */
11879 if (AOP_TYPE(result) != AOP_STR) {
11880 /* if this is remateriazable */
11881 if (AOP_TYPE(result) == AOP_IMMD)
11882 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11883 else { /* we need to get it byte by byte */
11884 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11885 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11886 if (options.model == MODEL_FLAT24)
11888 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11892 /* so dptr know contains the address */
11893 pic16_freeAsmop(result,NULL,ic,TRUE);
11894 pic16_aopOp(right,ic,FALSE);
11896 /* if bit then unpack */
11897 if (IS_BITFIELD(retype))
11898 genPackBits(retype,result,right,"dptr",FPOINTER);
11900 size = AOP_SIZE(right);
11904 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11906 pic16_emitcode("movx","@dptr,a");
11908 pic16_emitcode("inc","dptr");
11912 pic16_freeAsmop(right,NULL,ic,TRUE);
11916 /*-----------------------------------------------------------------*/
11917 /* genGenPointerSet - set value from generic pointer space */
11918 /*-----------------------------------------------------------------*/
11920 static void genGenPointerSet (operand *right,
11921 operand *result, iCode *ic)
11923 int i, size, offset, lit;
11924 sym_link *retype = getSpec(operandType(right));
11926 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11928 pic16_aopOp(result,ic,FALSE);
11929 pic16_aopOp(right,ic,FALSE);
11930 size = AOP_SIZE(right);
11933 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11935 /* if the operand is already in dptr
11936 then we do nothing else we move the value to dptr */
11937 if (AOP_TYPE(result) != AOP_STR) {
11938 /* if this is remateriazable */
11939 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11940 // WARNING: anythig until "else" is untested!
11941 if (AOP_TYPE(result) == AOP_IMMD) {
11942 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11943 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11944 // load FSR0 from immediate
11945 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11949 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11951 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11957 else { /* we need to get it byte by byte */
11958 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11959 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11961 // set up FSR0 with address of result
11962 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11963 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11965 /* hack hack! see if this the FSR. If so don't load W */
11966 if(AOP_TYPE(right) != AOP_ACC) {
11968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11970 if(AOP_TYPE(right) == AOP_LIT)
11973 // note: pic16_popGet handles sign extension
11974 for(i=0;i<size;i++) {
11975 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11977 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11979 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11984 for(i=0;i<size;i++) {
11986 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11987 pic16_popCopyReg(&pic16_pc_postinc0)));
11989 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11990 pic16_popCopyReg(&pic16_pc_indf0)));
11996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11997 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11999 } // if (AOP_TYPE(result) != AOP_IMMD)
12001 } // if (AOP_TYPE(result) != AOP_STR)
12002 /* so dptr know contains the address */
12005 /* if bit then unpack */
12006 if (IS_BITFIELD(retype))
12007 genPackBits(retype,result,right,"dptr",GPOINTER);
12009 size = AOP_SIZE(right);
12012 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12014 // set up FSR0 with address of result
12015 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12016 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12019 if (AOP_TYPE(right) == AOP_LIT) {
12020 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12022 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12024 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12026 } else { // no literal
12028 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12030 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12038 pic16_freeAsmop(right,NULL,ic,TRUE);
12039 pic16_freeAsmop(result,NULL,ic,TRUE);
12043 static void genGenPointerSet (operand *right,
12044 operand *result, iCode *ic)
12047 sym_link *retype = getSpec(operandType(result));
12049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12051 pic16_aopOp(result,ic,FALSE);
12052 pic16_aopOp(right,ic,FALSE);
12053 size = AOP_SIZE(right);
12055 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12058 /* if bit then unpack */
12059 if (IS_BITFIELD(retype)) {
12060 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12061 genPackBits(retype,result,right,"dptr",GPOINTER);
12065 size = AOP_SIZE(right);
12067 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12070 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12072 /* value of right+0 is placed on stack, which will be retrieved
12073 * by the support function thus restoring the stack. The important
12074 * thing is that there is no need to manually restore stack pointer
12076 pushaop(AOP(right), 0);
12077 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12078 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12079 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12080 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12082 /* load address to write to in WREG:FSR0H:FSR0L */
12083 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12084 pic16_popCopyReg(&pic16_pc_fsr0l)));
12085 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12086 pic16_popCopyReg(&pic16_pc_prodl)));
12087 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12089 pic16_callGenericPointerRW(1, size);
12092 pic16_freeAsmop(right,NULL,ic,TRUE);
12093 pic16_freeAsmop(result,NULL,ic,TRUE);
12096 /*-----------------------------------------------------------------*/
12097 /* genPointerSet - stores the value into a pointer location */
12098 /*-----------------------------------------------------------------*/
12099 static void genPointerSet (iCode *ic)
12101 operand *right, *result ;
12102 sym_link *type, *etype;
12107 right = IC_RIGHT(ic);
12108 result = IC_RESULT(ic) ;
12110 /* depending on the type of pointer we need to
12111 move it to the correct pointer register */
12112 type = operandType(result);
12113 etype = getSpec(type);
12115 /* if left is of type of pointer then it is simple */
12116 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12117 p_type = DCL_TYPE(type);
12120 /* we have to go by the storage class */
12121 p_type = PTR_TYPE(SPEC_OCLS(etype));
12123 /* if (SPEC_OCLS(etype)->codesp ) { */
12124 /* p_type = CPOINTER ; */
12127 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12128 /* p_type = FPOINTER ; */
12130 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12131 /* p_type = PPOINTER ; */
12133 /* if (SPEC_OCLS(etype) == idata ) */
12134 /* p_type = IPOINTER ; */
12136 /* p_type = POINTER ; */
12139 /* now that we have the pointer type we assign
12140 the pointer values */
12145 genNearPointerSet (right,result,ic);
12149 genPagedPointerSet (right,result,ic);
12153 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12155 genFarPointerSet (right,result,ic);
12160 genGenPointerSet (right,result,ic);
12164 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12165 "genPointerSet: illegal pointer type");
12169 /*-----------------------------------------------------------------*/
12170 /* genIfx - generate code for Ifx statement */
12171 /*-----------------------------------------------------------------*/
12172 static void genIfx (iCode *ic, iCode *popIc)
12174 operand *cond = IC_COND(ic);
12179 pic16_aopOp(cond,ic,FALSE);
12181 /* get the value into acc */
12182 if (AOP_TYPE(cond) != AOP_CRY)
12183 pic16_toBoolean(cond);
12186 /* the result is now in the accumulator */
12187 pic16_freeAsmop(cond,NULL,ic,TRUE);
12189 /* if there was something to be popped then do it */
12193 /* if the condition is a bit variable */
12194 if (isbit && IS_ITEMP(cond) &&
12196 genIfxJump(ic,"c");
12197 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12199 if (isbit && !IS_ITEMP(cond))
12200 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12202 genIfxJump(ic,"a");
12207 /*-----------------------------------------------------------------*/
12208 /* genAddrOf - generates code for address of */
12209 /*-----------------------------------------------------------------*/
12210 static void genAddrOf (iCode *ic)
12212 operand *result, *left;
12214 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12215 pCodeOp *pcop0, *pcop1, *pcop2;
12219 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12221 sym = OP_SYMBOL( IC_LEFT(ic) );
12224 /* get address of symbol on stack */
12225 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12227 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12228 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12231 // operands on stack are accessible via "FSR2 + index" with index
12232 // starting at 2 for arguments and growing from 0 downwards for
12233 // local variables (index == 0 is not assigned so we add one here)
12235 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12238 assert (soffs < 0);
12242 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12243 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12244 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12245 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12246 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12247 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12248 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12254 // if(pic16_debug_verbose) {
12255 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12256 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12259 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12260 size = AOP_SIZE(IC_RESULT(ic));
12262 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12263 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12264 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12267 pic16_emitpcode(POC_MOVLW, pcop0);
12268 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12269 pic16_emitpcode(POC_MOVLW, pcop1);
12270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12271 pic16_emitpcode(POC_MOVLW, pcop2);
12272 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12275 pic16_emitpcode(POC_MOVLW, pcop0);
12276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12277 pic16_emitpcode(POC_MOVLW, pcop1);
12278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12280 pic16_emitpcode(POC_MOVLW, pcop0);
12281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12284 pic16_freeAsmop(left, NULL, ic, FALSE);
12286 pic16_freeAsmop(result,NULL,ic,TRUE);
12291 /*-----------------------------------------------------------------*/
12292 /* genFarFarAssign - assignment when both are in far space */
12293 /*-----------------------------------------------------------------*/
12294 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12296 int size = AOP_SIZE(right);
12299 /* first push the right side on to the stack */
12301 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12303 pic16_emitcode ("push","acc");
12306 pic16_freeAsmop(right,NULL,ic,FALSE);
12307 /* now assign DPTR to result */
12308 pic16_aopOp(result,ic,FALSE);
12309 size = AOP_SIZE(result);
12311 pic16_emitcode ("pop","acc");
12312 pic16_aopPut(AOP(result),"a",--offset);
12314 pic16_freeAsmop(result,NULL,ic,FALSE);
12319 /*-----------------------------------------------------------------*/
12320 /* genAssign - generate code for assignment */
12321 /*-----------------------------------------------------------------*/
12322 static void genAssign (iCode *ic)
12324 operand *result, *right;
12325 sym_link *restype, *rtype;
12326 int size, offset,know_W;
12327 unsigned long lit = 0L;
12329 result = IC_RESULT(ic);
12330 right = IC_RIGHT(ic) ;
12334 /* if they are the same */
12335 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12338 /* reversed order operands are aopOp'ed so that result operand
12339 * is effective in case right is a stack symbol. This maneauver
12340 * allows to use the _G.resDirect flag later */
12341 pic16_aopOp(result,ic,TRUE);
12342 pic16_aopOp(right,ic,FALSE);
12344 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12346 /* if they are the same registers */
12347 if (pic16_sameRegs(AOP(right),AOP(result)))
12350 /* if the result is a bit */
12351 if (AOP_TYPE(result) == AOP_CRY) {
12352 /* if the right size is a literal then
12353 we know what the value is */
12354 if (AOP_TYPE(right) == AOP_LIT) {
12356 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12357 pic16_popGet(AOP(result),0));
12359 if (((int) operandLitValue(right)))
12360 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12361 AOP(result)->aopu.aop_dir,
12362 AOP(result)->aopu.aop_dir);
12364 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12365 AOP(result)->aopu.aop_dir,
12366 AOP(result)->aopu.aop_dir);
12371 /* the right is also a bit variable */
12372 if (AOP_TYPE(right) == AOP_CRY) {
12373 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12374 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12375 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12380 /* we need to or */
12381 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12382 pic16_toBoolean(right);
12384 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12385 //pic16_aopPut(AOP(result),"a",0);
12389 /* bit variables done */
12391 size = AOP_SIZE(result);
12394 /* bit variables done */
12396 size = AOP_SIZE(result);
12397 restype = operandType(result);
12398 rtype = operandType(right);
12401 if(AOP_TYPE(right) == AOP_LIT) {
12402 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12404 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12406 /* patch tag for literals that are cast to pointers */
12407 if (IS_CODEPTR(restype)) {
12408 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12409 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12411 if (IS_GENPTR(restype))
12413 if (IS_CODEPTR(rtype)) {
12414 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12415 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12416 } else if (PIC_IS_DATA_PTR(rtype)) {
12417 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12418 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12419 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12420 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12421 } else if (IS_PTR(rtype)) {
12422 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12423 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12429 unsigned long lit_int;
12434 if(IS_FIXED16X16(operandType(right))) {
12435 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12437 /* take care if literal is a float */
12438 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12439 lit = info.lit_int;
12444 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12445 // sizeof(unsigned long int), sizeof(float));
12448 if (AOP_TYPE(right) == AOP_REG) {
12449 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12451 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12456 /* when do we have to read the program memory?
12457 * - if right itself is a symbol in code space
12458 * (we don't care what it points to if it's a pointer)
12459 * - AND right is not a function (we would want its address)
12461 if(AOP_TYPE(right) != AOP_LIT
12462 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12463 && !IS_FUNC(OP_SYM_TYPE(right))
12464 && !IS_ITEMP(right)) {
12466 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12467 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12469 // set up table pointer
12470 if(is_LitOp(right)) {
12471 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12472 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12473 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12474 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12475 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12476 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12477 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12479 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12480 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12481 pic16_popCopyReg(&pic16_pc_tblptrl)));
12482 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12483 pic16_popCopyReg(&pic16_pc_tblptrh)));
12484 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12485 pic16_popCopyReg(&pic16_pc_tblptru)));
12488 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12489 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12491 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12493 pic16_popGet(AOP(result),offset)));
12497 /* FIXME: for pointers we need to extend differently (according
12498 * to pointer type DATA/CODE/EEPROM/... :*/
12499 size = getSize(OP_SYM_TYPE(right));
12500 if(AOP_SIZE(result) > size) {
12501 size = AOP_SIZE(result) - size;
12503 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12511 /* VR - What is this?! */
12512 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12515 if(aopIdx(AOP(result),0) == 4) {
12516 /* this is a workaround to save value of right into wreg too,
12517 * value of wreg is going to be used later */
12518 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12519 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12524 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12530 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12531 if(AOP_TYPE(right) == AOP_LIT) {
12533 if(know_W != (lit&0xff))
12534 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12536 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12538 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12542 } else if (AOP_TYPE(right) == AOP_CRY) {
12543 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12545 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12546 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12547 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12549 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12550 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12551 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12555 if(!_G.resDirect) { /* use this aopForSym feature */
12556 if(AOP_TYPE(result) == AOP_ACC) {
12557 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12559 if(AOP_TYPE(right) == AOP_ACC) {
12560 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12562 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12571 pic16_freeAsmop (right,NULL,ic,FALSE);
12572 pic16_freeAsmop (result,NULL,ic,TRUE);
12575 /*-----------------------------------------------------------------*/
12576 /* genJumpTab - generates code for jump table */
12577 /*-----------------------------------------------------------------*/
12578 static void genJumpTab (iCode *ic)
12583 pCodeOp *jt_offs_hi;
12588 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12589 /* get the condition into accumulator */
12590 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12592 /* multiply by three */
12593 pic16_emitcode("add","a,acc");
12594 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12596 jtab = newiTempLabel(NULL);
12597 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12598 pic16_emitcode("jmp","@a+dptr");
12599 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12602 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12603 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12605 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12606 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12607 pic16_emitpLabel(jtab->key);
12611 jt_offs = pic16_popGetTempReg(0);
12612 jt_offs_hi = pic16_popGetTempReg(1);
12613 jt_label = pic16_popGetLabel (jtab->key);
12614 //fprintf (stderr, "Creating jump table...\n");
12616 // calculate offset into jump table (idx * sizeof (GOTO))
12617 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12618 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12619 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12620 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12621 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12622 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12623 pic16_emitpcode(POC_MOVWF , jt_offs);
12625 // prepare PCLATx (set to first entry in jump table)
12626 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12627 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12628 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12629 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12630 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12632 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12633 pic16_emitpcode(POC_ADDWF , jt_offs);
12634 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12635 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12637 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12639 // release temporaries and prepare jump into table (new PCL --> WREG)
12640 pic16_emitpcode(POC_MOVFW , jt_offs);
12641 pic16_popReleaseTempReg (jt_offs_hi, 1);
12642 pic16_popReleaseTempReg (jt_offs, 0);
12644 // jump into the table
12645 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12647 pic16_emitpLabelFORCE(jtab->key);
12650 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12651 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12653 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12654 /* now generate the jump labels */
12655 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12656 jtab = setNextItem(IC_JTLABELS(ic))) {
12657 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12658 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12661 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12665 /*-----------------------------------------------------------------*/
12666 /* genMixedOperation - gen code for operators between mixed types */
12667 /*-----------------------------------------------------------------*/
12669 TSD - Written for the PIC port - but this unfortunately is buggy.
12670 This routine is good in that it is able to efficiently promote
12671 types to different (larger) sizes. Unfortunately, the temporary
12672 variables that are optimized out by this routine are sometimes
12673 used in other places. So until I know how to really parse the
12674 iCode tree, I'm going to not be using this routine :(.
12676 static int genMixedOperation (iCode *ic)
12679 operand *result = IC_RESULT(ic);
12680 sym_link *ctype = operandType(IC_LEFT(ic));
12681 operand *right = IC_RIGHT(ic);
12687 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12689 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12695 nextright = IC_RIGHT(nextic);
12696 nextleft = IC_LEFT(nextic);
12697 nextresult = IC_RESULT(nextic);
12699 pic16_aopOp(right,ic,FALSE);
12700 pic16_aopOp(result,ic,FALSE);
12701 pic16_aopOp(nextright, nextic, FALSE);
12702 pic16_aopOp(nextleft, nextic, FALSE);
12703 pic16_aopOp(nextresult, nextic, FALSE);
12705 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12707 operand *t = right;
12711 pic16_emitcode(";remove right +","");
12713 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12715 operand *t = right;
12719 pic16_emitcode(";remove left +","");
12723 big = AOP_SIZE(nextleft);
12724 small = AOP_SIZE(nextright);
12726 switch(nextic->op) {
12729 pic16_emitcode(";optimize a +","");
12730 /* if unsigned or not an integral type */
12731 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12732 pic16_emitcode(";add a bit to something","");
12735 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12737 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12738 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12739 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12741 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12749 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12750 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12751 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12754 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12756 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12757 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12758 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12759 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12763 pic16_emitcode("rlf","known_zero,w");
12770 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12771 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12772 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12774 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12784 pic16_freeAsmop(right,NULL,ic,TRUE);
12785 pic16_freeAsmop(result,NULL,ic,TRUE);
12786 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12787 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12789 nextic->generated = 1;
12796 /*-----------------------------------------------------------------*/
12797 /* genCast - gen code for casting */
12798 /*-----------------------------------------------------------------*/
12799 static void genCast (iCode *ic)
12801 operand *result = IC_RESULT(ic);
12802 sym_link *ctype = operandType(IC_LEFT(ic));
12803 sym_link *rtype = operandType(IC_RIGHT(ic));
12804 sym_link *restype = operandType(IC_RESULT(ic));
12805 operand *right = IC_RIGHT(ic);
12811 /* if they are equivalent then do nothing */
12812 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12815 pic16_aopOp(result,ic,FALSE);
12816 pic16_aopOp(right,ic,FALSE) ;
12818 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12821 /* if the result is a bit */
12822 if (AOP_TYPE(result) == AOP_CRY) {
12824 /* if the right size is a literal then
12825 * we know what the value is */
12826 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12828 if (AOP_TYPE(right) == AOP_LIT) {
12829 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12830 pic16_popGet(AOP(result),0));
12832 if (((int) operandLitValue(right)))
12833 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12834 AOP(result)->aopu.aop_dir,
12835 AOP(result)->aopu.aop_dir);
12837 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12838 AOP(result)->aopu.aop_dir,
12839 AOP(result)->aopu.aop_dir);
12843 /* the right is also a bit variable */
12844 if (AOP_TYPE(right) == AOP_CRY) {
12846 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12848 pic16_emitcode("clrc","");
12849 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12850 AOP(right)->aopu.aop_dir,
12851 AOP(right)->aopu.aop_dir);
12852 pic16_aopPut(AOP(result),"c",0);
12856 /* we need to or */
12857 if (AOP_TYPE(right) == AOP_REG) {
12858 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12859 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12860 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12862 pic16_toBoolean(right);
12863 pic16_aopPut(AOP(result),"a",0);
12867 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12870 size = AOP_SIZE(result);
12872 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12874 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12875 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12876 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12884 if(IS_BITFIELD(getSpec(restype))
12885 && IS_BITFIELD(getSpec(rtype))) {
12886 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12889 /* port from pic14 to cope with generic pointers */
12890 if (PIC_IS_TAGGED(restype))
12892 operand *result = IC_RESULT(ic);
12893 //operand *left = IC_LEFT(ic);
12894 operand *right = IC_RIGHT(ic);
12897 /* copy common part */
12898 int max, size = AOP_SIZE(result);
12899 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12900 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12905 pic16_mov2w (AOP(right), size);
12906 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12909 /* upcast into generic pointer type? */
12910 if (IS_GENPTR(restype)
12911 && !PIC_IS_TAGGED(rtype)
12912 && (AOP_SIZE(result) > max))
12914 /* determine appropriate tag for right */
12915 if (PIC_IS_DATA_PTR(rtype))
12916 tag = GPTR_TAG_DATA;
12917 else if (IS_CODEPTR(rtype))
12918 tag = GPTR_TAG_CODE;
12919 else if (PIC_IS_DATA_PTR(ctype)) {
12920 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12921 tag = GPTR_TAG_DATA;
12922 } else if (IS_CODEPTR(ctype)) {
12923 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12924 tag = GPTR_TAG_CODE;
12925 } else if (IS_PTR(rtype)) {
12926 PERFORM_ONCE(weirdcast,
12927 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12929 tag = GPTR_TAG_DATA;
12931 PERFORM_ONCE(weirdcast,
12932 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12934 tag = GPTR_TAG_DATA;
12937 assert (AOP_SIZE(result) == 3);
12938 /* zero-extend address... */
12939 for (size = max; size < AOP_SIZE(result)-1; size++)
12940 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12941 /* ...and add tag */
12942 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12943 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12944 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12945 for (size = max; size < AOP_SIZE(result)-1; size++)
12946 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12947 /* add __code tag */
12948 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12949 } else if (AOP_SIZE(result) > max) {
12950 /* extend non-pointers */
12951 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12952 pic16_addSign(result, max, 0);
12957 /* if they are the same size : or less */
12958 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12960 /* if they are in the same place */
12961 if (pic16_sameRegs(AOP(right),AOP(result)))
12964 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12966 if (IS_PTR_CONST(rtype))
12968 if (IS_CODEPTR(rtype))
12970 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12973 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12975 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12977 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12980 if(AOP_TYPE(right) == AOP_IMMD) {
12981 pCodeOp *pcop0, *pcop1, *pcop2;
12982 symbol *sym = OP_SYMBOL( right );
12984 size = AOP_SIZE(result);
12986 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12988 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12990 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12993 pic16_emitpcode(POC_MOVLW, pcop0);
12994 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12995 pic16_emitpcode(POC_MOVLW, pcop1);
12996 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12997 pic16_emitpcode(POC_MOVLW, pcop2);
12998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13001 pic16_emitpcode(POC_MOVLW, pcop0);
13002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13003 pic16_emitpcode(POC_MOVLW, pcop1);
13004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13006 pic16_emitpcode(POC_MOVLW, pcop0);
13007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13011 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13012 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13014 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13016 if(AOP_SIZE(result) <2)
13017 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13019 /* if they in different places then copy */
13020 size = AOP_SIZE(result);
13023 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13031 /* if the result is of type pointer */
13032 if (IS_PTR(ctype)) {
13034 sym_link *type = operandType(right);
13035 sym_link *etype = getSpec(type);
13037 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13039 /* pointer to generic pointer */
13040 if (IS_GENPTR(ctype)) {
13044 p_type = DCL_TYPE(type);
13046 /* we have to go by the storage class */
13047 p_type = PTR_TYPE(SPEC_OCLS(etype));
13049 /* if (SPEC_OCLS(etype)->codesp ) */
13050 /* p_type = CPOINTER ; */
13052 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13053 /* p_type = FPOINTER ; */
13055 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13056 /* p_type = PPOINTER; */
13058 /* if (SPEC_OCLS(etype) == idata ) */
13059 /* p_type = IPOINTER ; */
13061 /* p_type = POINTER ; */
13064 /* the first two bytes are known */
13065 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13066 size = GPTRSIZE - 1;
13069 if(offset < AOP_SIZE(right)) {
13070 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13071 pic16_mov2f(AOP(result), AOP(right), offset);
13073 if ((AOP_TYPE(right) == AOP_PCODE) &&
13074 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13075 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13076 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13079 pic16_aopPut(AOP(result),
13080 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13085 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13088 /* the last byte depending on type */
13093 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13097 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13101 pic16_emitcode(";BUG!? ","%d",__LINE__);
13106 if (GPTRSIZE > AOP_SIZE(right)) {
13107 // assume __data pointer... THIS MIGHT BE WRONG!
13108 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13110 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13115 /* this should never happen */
13116 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13117 "got unknown pointer type");
13120 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13126 /* just copy the pointers */
13127 size = AOP_SIZE(result);
13130 pic16_aopPut(AOP(result),
13131 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13140 /* so we now know that the size of destination is greater
13141 than the size of the source.
13142 Now, if the next iCode is an operator then we might be
13143 able to optimize the operation without performing a cast.
13145 if(genMixedOperation(ic))
13148 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13150 /* we move to result for the size of source */
13151 size = AOP_SIZE(right);
13156 pic16_mov2f(AOP(result), AOP(right), offset);
13160 /* now depending on the sign of the destination */
13161 size = AOP_SIZE(result) - AOP_SIZE(right);
13162 /* if unsigned or not an integral type */
13163 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13165 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13167 /* we need to extend the sign :( */
13170 /* Save one instruction of casting char to int */
13171 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13172 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13173 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13175 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13178 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13180 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13182 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13185 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13190 pic16_freeAsmop(right,NULL,ic,TRUE);
13191 pic16_freeAsmop(result,NULL,ic,TRUE);
13195 /*-----------------------------------------------------------------*/
13196 /* genDjnz - generate decrement & jump if not zero instrucion */
13197 /*-----------------------------------------------------------------*/
13198 static int genDjnz (iCode *ic, iCode *ifx)
13200 symbol *lbl, *lbl1;
13201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13206 /* if the if condition has a false label
13207 then we cannot save */
13211 /* if the minus is not of the form
13213 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13214 !IS_OP_LITERAL(IC_RIGHT(ic)))
13217 if (operandLitValue(IC_RIGHT(ic)) != 1)
13220 /* if the size of this greater than one then no
13222 if (getSize(operandType(IC_RESULT(ic))) > 1)
13225 /* otherwise we can save BIG */
13226 lbl = newiTempLabel(NULL);
13227 lbl1= newiTempLabel(NULL);
13229 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13231 if (IS_AOP_PREG(IC_RESULT(ic))) {
13232 pic16_emitcode("dec","%s",
13233 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13234 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13235 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13239 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13240 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13242 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13243 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13247 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13248 ifx->generated = 1;
13252 /*-----------------------------------------------------------------*/
13253 /* genReceive - generate code for a receive iCode */
13254 /*-----------------------------------------------------------------*/
13255 static void genReceive (iCode *ic)
13261 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13262 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13264 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13266 if (isOperandInFarSpace(IC_RESULT(ic))
13267 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13268 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13270 int size = getSize(operandType(IC_RESULT(ic)));
13271 int offset = pic16_fReturnSizePic - size;
13275 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13276 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13280 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13282 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13283 size = AOP_SIZE(IC_RESULT(ic));
13286 pic16_emitcode ("pop","acc");
13287 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13290 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13292 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13295 /* set pseudo stack pointer to where it should be - dw*/
13296 GpsuedoStkPtr = ic->parmBytes;
13298 /* setting GpsuedoStkPtr has side effects here: */
13299 assignResultValue(IC_RESULT(ic), 0);
13302 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13305 /*-----------------------------------------------------------------*/
13306 /* genDummyRead - generate code for dummy read of volatiles */
13307 /*-----------------------------------------------------------------*/
13309 genDummyRead (iCode * ic)
13315 if (op && IS_SYMOP(op)) {
13316 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13317 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13320 pic16_aopOp (op, ic, FALSE);
13321 for (i=0; i < AOP_SIZE(op); i++) {
13322 // may need to protect this from the peepholer -- this is not nice but works...
13323 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13324 pic16_mov2w (AOP(op),i);
13325 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13327 pic16_freeAsmop (op, NULL, ic, TRUE);
13329 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13333 /*-----------------------------------------------------------------*/
13334 /* genpic16Code - generate code for pic16 based controllers */
13335 /*-----------------------------------------------------------------*/
13337 * At this point, ralloc.c has gone through the iCode and attempted
13338 * to optimize in a way suitable for a PIC. Now we've got to generate
13339 * PIC instructions that correspond to the iCode.
13341 * Once the instructions are generated, we'll pass through both the
13342 * peep hole optimizer and the pCode optimizer.
13343 *-----------------------------------------------------------------*/
13345 void genpic16Code (iCode *lic)
13350 lineHead = lineCurr = NULL;
13352 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13353 pic16_addpBlock(pb);
13356 /* if debug information required */
13357 if (options.debug && currFunc) {
13359 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13364 for (ic = lic ; ic ; ic = ic->next ) {
13366 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13367 if ( cln != ic->lineno ) {
13368 if ( options.debug ) {
13369 debugFile->writeCLine (ic);
13372 if(!options.noCcodeInAsm) {
13373 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13374 printCLine(ic->filename, ic->lineno)));
13380 if(options.iCodeInAsm) {
13383 /* insert here code to print iCode as comment */
13384 l = Safe_strdup(printILine(ic));
13385 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13388 /* if the result is marked as
13389 * spilt and rematerializable or code for
13390 * this has already been generated then
13392 if (resultRemat(ic) || ic->generated )
13395 /* depending on the operation */
13414 /* IPOP happens only when trying to restore a
13415 * spilt live range, if there is an ifx statement
13416 * following this pop then the if statement might
13417 * be using some of the registers being popped which
13418 * would destroy the contents of the register so
13419 * we need to check for this condition and handle it */
13421 && ic->next->op == IFX
13422 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13423 genIfx (ic->next,ic);
13441 genEndFunction (ic);
13457 pic16_genPlus (ic) ;
13461 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13462 pic16_genMinus (ic);
13478 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13482 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13488 /* note these two are xlated by algebraic equivalence
13489 * during parsing SDCC.y */
13490 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13491 "got '>=' or '<=' shouldn't have come here");
13495 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13507 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13511 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13515 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13539 genRightShift (ic);
13542 case GET_VALUE_AT_ADDRESS:
13547 if (POINTER_SET(ic))
13574 addSet(&_G.sendSet,ic);
13577 case DUMMY_READ_VOLATILE:
13587 /* now we are ready to call the
13588 peep hole optimizer */
13589 if (!options.nopeep)
13590 peepHole (&lineHead);
13592 /* now do the actual printing */
13593 printLine (lineHead, codeOutFile);
13596 DFPRINTF((stderr,"printing pBlock\n\n"));
13597 pic16_printpBlock(stdout,pb);