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 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1293 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1294 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1296 sym->usl.spillLoc->offset, op);
1298 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1299 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300 assert (getSize(sym->type) <= 1);
1301 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1303 aop->size = getSize(sym->type);
1309 sym_link *type = operandType(op);
1311 if(IS_PTR_CONST(type))
1313 if(IS_CODEPTR(type))
1315 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1318 /* must be in a register */
1319 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1320 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1321 aop->size = sym->nRegs;
1322 for ( i = 0 ; i < sym->nRegs ;i++)
1323 aop->aopu.aop_reg[i] = sym->regs[i];
1326 /*-----------------------------------------------------------------*/
1327 /* pic16_freeAsmop - free up the asmop given to an operand */
1328 /*----------------------------------------------------------------*/
1329 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1346 /* depending on the asmop type only three cases need work AOP_RO
1347 , AOP_R1 && AOP_STK */
1349 switch (aop->type) {
1351 if (_G.fsr0Pushed ) {
1353 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1354 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1355 // pic16_emitcode ("pop","ar0");
1359 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1363 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1369 pic16_emitcode ("pop","ar0");
1373 bitVectUnSetBit(ic->rUsed,R0_IDX);
1379 pic16_emitcode ("pop","ar1");
1383 bitVectUnSetBit(ic->rUsed,R1_IDX);
1390 /* we must store the result on stack */
1391 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1392 // operands on stack are accessible via "FSR2 + index" with index
1393 // starting at 2 for arguments and growing from 0 downwards for
1394 // local variables (index == 0 is not assigned so we add one here)
1395 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1400 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1401 for(i=0;i<aop->size;i++) {
1402 /* initialise for stack access via frame pointer */
1403 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1404 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1405 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1408 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1412 for(i=0;i<aop->size;i++) {
1413 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1415 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1416 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1417 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1424 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1425 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1426 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1427 deleteSetItem( &_G.sregsAllocSet, sr );
1438 int stk = aop->aopu.aop_stk + aop->size;
1439 bitVectUnSetBit(ic->rUsed,R0_IDX);
1440 bitVectUnSetBit(ic->rUsed,R1_IDX);
1442 getFreePtr(ic,&aop,FALSE);
1444 if (options.stack10bit)
1446 /* I'm not sure what to do here yet... */
1449 "*** Warning: probably generating bad code for "
1450 "10 bit stack mode.\n");
1454 pic16_emitcode ("mov","a,_bp");
1455 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1456 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1458 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1462 pic16_emitcode("pop","acc");
1463 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1465 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1468 pic16_freeAsmop(op,NULL,ic,TRUE);
1470 pic16_emitcode("pop","ar0");
1475 pic16_emitcode("pop","ar1");
1485 /* all other cases just dealloc */
1489 OP_SYMBOL(op)->aop = NULL;
1490 /* if the symbol has a spill */
1492 SPIL_LOC(op)->aop = NULL;
1497 /*-----------------------------------------------------------------*/
1498 /* pic16_aopGet - for fetching value of the aop */
1499 /*-----------------------------------------------------------------*/
1500 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1505 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1507 /* offset is greater than size then zero */
1508 if (offset > (aop->size - 1) &&
1509 aop->type != AOP_LIT)
1512 /* depending on type */
1513 switch (aop->type) {
1517 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1518 rs = Safe_calloc(1, strlen(s)+1);
1523 /* if we need to increment it */
1524 while (offset > aop->coff)
1526 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1530 while (offset < aop->coff)
1532 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1538 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1539 return (dname ? "acc" : "a");
1541 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1542 rs = Safe_calloc (1, strlen (s) + 1);
1550 sprintf (s,"%s",aop->aopu.aop_immd);
1553 sprintf(s,"(%s >> %d)",
1558 aop->aopu.aop_immd);
1559 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1560 rs = Safe_calloc(1,strlen(s)+1);
1566 sprintf(s,"(%s + %d)",
1569 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1571 sprintf(s,"%s",aop->aopu.aop_dir);
1572 rs = Safe_calloc(1,strlen(s)+1);
1577 return aop->aopu.aop_reg[offset]->name;
1580 return aop->aopu.aop_dir;
1583 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1584 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1586 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1587 rs = Safe_strdup("WREG");
1591 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1592 rs = Safe_calloc(1,strlen(s)+1);
1597 aop->coff = offset ;
1599 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1602 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1603 aop->type = AOP_ACC;
1604 return Safe_strdup("_WREG");
1606 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1608 return aop->aopu.aop_str[offset];
1612 pCodeOp *pcop = aop->aopu.pcop;
1613 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1615 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1616 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1618 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1620 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1623 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1626 rs = Safe_calloc(1,strlen(s)+1);
1632 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1634 sprintf(s,"(%s + %d)",
1638 sprintf(s,"%s",aop->aopu.aop_dir);
1639 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1640 rs = Safe_calloc(1,strlen(s)+1);
1646 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1650 // pCodeOp *pcop = aop->aop
1655 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1656 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1657 "aopget got unsupported aop->type");
1663 /* lock has the following meaning: When allocating temporary registers
1664 * for stack variables storage, the value of the temporary register is
1665 * saved on stack. Its value is restored at the end. This procedure is
1666 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1667 * a possibility that before a call to pic16_aopOp, a temporary register
1668 * is allocated for a while and it is freed after some time, this will
1669 * mess the stack and values will not be restored properly. So use lock=1
1670 * to allocate temporary registers used internally by the programmer, and
1671 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1672 * to inform the compiler developer about a possible bug. This is an internal
1673 * feature for developing the compiler -- VR */
1675 int _TempReg_lock = 0;
1676 /*-----------------------------------------------------------------*/
1677 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popGetTempReg(int lock)
1684 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1686 // werror(W_POSSBUG2, __FILE__, __LINE__);
1689 _TempReg_lock += lock;
1699 /* this code might seem better but it does the *same* job with
1700 * the old code, it all depends on ralloc.c to get a free/unused
1704 while(i < pic16_nRegs) {
1705 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1706 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1707 if((!rr || (rr && rr->isFree))
1708 && !bitVectBitValue(cfunc->regsUsed, i)) {
1709 pcop = pic16_newpCodeOpReg( i );
1710 PCOR(pcop)->r->wasUsed = 1;
1711 PCOR(pcop)->r->isFree = 0;
1718 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1722 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1723 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1724 PCOR(pcop)->r->wasUsed=1;
1725 PCOR(pcop)->r->isFree=0;
1727 /* push value on stack */
1728 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1737 /*-----------------------------------------------------------------*/
1738 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1739 /* is not part of f, but don't save if */
1741 /*-----------------------------------------------------------------*/
1742 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1748 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1751 // werror(W_POSSBUG2, __FILE__, __LINE__);
1754 _TempReg_lock += lock;
1759 i = bitVectFirstBit(f);
1762 /* bypass registers that are used by function */
1763 if(!bitVectBitValue(f, i)) {
1765 /* bypass registers that are already allocated for stack access */
1766 if(!bitVectBitValue(v, i)) {
1768 // debugf("getting register rIdx = %d\n", i);
1769 /* ok, get the operand */
1770 pcop = pic16_newpCodeOpReg( i );
1772 /* should never by NULL */
1773 assert( pcop != NULL );
1777 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1780 PCOR(pcop)->r->wasUsed=1;
1781 PCOR(pcop)->r->isFree=0;
1787 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1789 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1790 /* already used in previous steps, break */
1797 /* caller takes care of the following */
1798 // bitVectSetBit(v, i);
1801 /* push value on stack */
1802 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1803 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1821 /*-----------------------------------------------------------------*/
1822 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1826 _TempReg_lock -= lock;
1828 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1829 PCOR(pcop)->r->isFree = 1;
1831 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1834 /*-----------------------------------------------------------------*/
1835 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1836 /*-----------------------------------------------------------------*/
1837 pCodeOp *pic16_popGetLabel(int key)
1840 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1845 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1848 /*-----------------------------------------------------------------*/
1849 /* pic16_popCopyReg - copy a pcode operator */
1850 /*-----------------------------------------------------------------*/
1851 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1855 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1856 memcpy (pcor, pc, sizeof (pCodeOpReg));
1857 pcor->r->wasUsed = 1;
1859 //pcor->pcop.type = pc->pcop.type;
1861 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1862 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1864 pcor->pcop.name = NULL;
1867 //pcor->rIdx = pc->rIdx;
1868 //pcor->r->wasUsed=1;
1869 //pcor->instance = pc->instance;
1871 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1876 /*-----------------------------------------------------------------*/
1877 /* pic16_popGetLit - asm operator to pcode operator conversion */
1878 /*-----------------------------------------------------------------*/
1879 pCodeOp *pic16_popGetLit(int lit)
1881 return pic16_newpCodeOpLit(lit);
1884 /* Allow for 12 bit literals (LFSR x, <here!>). */
1885 pCodeOp *pic16_popGetLit12(int lit)
1887 return pic16_newpCodeOpLit12(lit);
1890 /*-----------------------------------------------------------------*/
1891 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1892 /*-----------------------------------------------------------------*/
1893 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1895 return pic16_newpCodeOpLit2(lit, arg2);
1899 /*-----------------------------------------------------------------*/
1900 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1901 /*-----------------------------------------------------------------*/
1902 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1904 return pic16_newpCodeOpImmd(name, offset,index, 0);
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popGet - asm operator to pcode operator conversion */
1910 /*-----------------------------------------------------------------*/
1911 pCodeOp *pic16_popGetWithString(char *str)
1917 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1921 pcop = pic16_newpCodeOp(str,PO_STR);
1926 /*-----------------------------------------------------------------*/
1927 /* pic16_popRegFromString - */
1928 /*-----------------------------------------------------------------*/
1929 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1932 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1933 pcop->type = PO_DIR;
1935 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1936 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1941 pcop->name = Safe_calloc(1,strlen(str)+1);
1942 strcpy(pcop->name,str);
1944 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1946 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1947 // PCOR(pcop)->r->wasUsed = 1;
1949 /* make sure that register doesn't exist,
1950 * and operand isn't NULL
1951 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1952 if((PCOR(pcop)->r == NULL)
1954 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1955 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1956 // __FUNCTION__, __LINE__, str, size, offset);
1958 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1959 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1962 PCOR(pcop)->instance = offset;
1967 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1971 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1972 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1974 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1975 PCOR(pcop)->rIdx = rIdx;
1976 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1978 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1980 PCOR(pcop)->r->isFree = 0;
1981 PCOR(pcop)->r->wasUsed = 1;
1983 pcop->type = PCOR(pcop)->r->pc_type;
1988 /*---------------------------------------------------------------------------------*/
1989 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1991 /*---------------------------------------------------------------------------------*/
1992 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1997 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1999 /* comment the following check, so errors to throw up */
2000 // if(!pcop2)return NULL;
2002 temp = pic16_popGet(aop_dst, offset);
2003 pcop2->pcop2 = temp;
2010 /*--------------------------------------------------------------------------------.-*/
2011 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2012 /* VR 030601 , adapted by Hans Dorn */
2013 /*--------------------------------------------------------------------------------.-*/
2014 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2018 pcop2 = (pCodeOpReg2 *)src;
2026 /*---------------------------------------------------------------------------------*/
2027 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2028 /* movff instruction */
2029 /*---------------------------------------------------------------------------------*/
2030 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2035 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2036 pcop2->pcop2 = pic16_popCopyReg(dst);
2038 /* the pCodeOp may be already allocated */
2039 pcop2 = (pCodeOpReg2 *)(src);
2040 pcop2->pcop2 = (pCodeOp *)(dst);
2047 /*-----------------------------------------------------------------*/
2048 /* pic16_popGet - asm operator to pcode operator conversion */
2049 /*-----------------------------------------------------------------*/
2050 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2052 // char *s = buffer ;
2057 /* offset is greater than
2060 // if (offset > (aop->size - 1) &&
2061 // aop->type != AOP_LIT)
2062 // return NULL; //zero;
2064 /* depending on type */
2065 switch (aop->type) {
2070 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2071 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2077 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2078 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2079 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2080 PCOR(pcop)->r->wasUsed = 1;
2081 PCOR(pcop)->r->isFree = 0;
2083 PCOR(pcop)->instance = offset;
2084 pcop->type = PCOR(pcop)->r->pc_type;
2088 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2089 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2092 /* pCodeOp is already allocated from aopForSym */
2093 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2094 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2099 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2101 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2103 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2105 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106 PCOR(pcop)->rIdx = rIdx;
2107 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2108 PCOR(pcop)->r->wasUsed=1;
2109 PCOR(pcop)->r->isFree=0;
2111 PCOR(pcop)->instance = offset;
2112 pcop->type = PCOR(pcop)->r->pc_type;
2113 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2117 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2118 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2124 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2125 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2129 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2130 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2136 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2137 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2139 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2141 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2142 // pcop->type = PO_GPR_REGISTER;
2143 PCOR(pcop)->rIdx = rIdx;
2144 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2145 PCOR(pcop)->r->wasUsed=1;
2146 PCOR(pcop)->r->isFree=0;
2148 PCOR(pcop)->instance = offset;
2149 pcop->type = PCOR(pcop)->r->pc_type;
2151 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2152 // rs = aop->aopu.aop_reg[offset]->name;
2153 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2158 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2160 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2161 PCOR(pcop)->instance = offset;
2162 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2163 //if(PCOR(pcop)->r == NULL)
2164 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2168 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2169 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2172 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2173 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2176 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2177 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2178 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2179 pcop->type = PCOR(pcop)->r->pc_type;
2180 pcop->name = PCOR(pcop)->r->name;
2186 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2188 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2189 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2190 switch( aop->aopu.pcop->type ) {
2191 case PO_DIR: PCOR(pcop)->instance += offset; break;
2192 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2197 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2198 assert( 0 ); /* should never reach here */;
2203 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2204 "pic16_popGet got unsupported aop->type");
2207 /*-----------------------------------------------------------------*/
2208 /* pic16_aopPut - puts a string for a aop */
2209 /*-----------------------------------------------------------------*/
2210 void pic16_aopPut (asmop *aop, char *s, int offset)
2217 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2219 if (aop->size && offset > ( aop->size - 1)) {
2220 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2221 "pic16_aopPut got offset > aop->size");
2225 /* will assign value to value */
2226 /* depending on where it is ofcourse */
2227 switch (aop->type) {
2230 sprintf(d,"(%s + %d)",
2231 aop->aopu.aop_dir,offset);
2232 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2235 sprintf(d,"%s",aop->aopu.aop_dir);
2238 DEBUGpic16_emitcode(";","%d",__LINE__);
2240 pic16_emitcode("movf","%s,w",s);
2241 pic16_emitcode("movwf","%s",d);
2244 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2245 if(offset >= aop->size) {
2246 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2249 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2252 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2259 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2260 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2263 strcmp(s,"r0") == 0 ||
2264 strcmp(s,"r1") == 0 ||
2265 strcmp(s,"r2") == 0 ||
2266 strcmp(s,"r3") == 0 ||
2267 strcmp(s,"r4") == 0 ||
2268 strcmp(s,"r5") == 0 ||
2269 strcmp(s,"r6") == 0 ||
2270 strcmp(s,"r7") == 0 )
2271 pic16_emitcode("mov","%s,%s ; %d",
2272 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2276 if(strcmp(s,"W")==0 )
2277 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2279 pic16_emitcode("movwf","%s",
2280 aop->aopu.aop_reg[offset]->name);
2282 if(strcmp(s,zero)==0) {
2283 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2285 } else if(strcmp(s,"W")==0) {
2286 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2287 pcop->type = PO_GPR_REGISTER;
2289 PCOR(pcop)->rIdx = -1;
2290 PCOR(pcop)->r = NULL;
2292 DEBUGpic16_emitcode(";","%d",__LINE__);
2293 pcop->name = Safe_strdup(s);
2294 pic16_emitpcode(POC_MOVFW,pcop);
2295 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2296 } else if(strcmp(s,one)==0) {
2297 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2298 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2300 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2308 if (aop->type == AOP_DPTR2)
2314 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2315 "pic16_aopPut writting to code space");
2319 while (offset > aop->coff) {
2321 pic16_emitcode ("inc","dptr");
2324 while (offset < aop->coff) {
2326 pic16_emitcode("lcall","__decdptr");
2331 /* if not in accumulater */
2334 pic16_emitcode ("movx","@dptr,a");
2336 if (aop->type == AOP_DPTR2)
2344 while (offset > aop->coff) {
2346 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2348 while (offset < aop->coff) {
2350 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2356 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2361 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2363 if (strcmp(s,"r0") == 0 ||
2364 strcmp(s,"r1") == 0 ||
2365 strcmp(s,"r2") == 0 ||
2366 strcmp(s,"r3") == 0 ||
2367 strcmp(s,"r4") == 0 ||
2368 strcmp(s,"r5") == 0 ||
2369 strcmp(s,"r6") == 0 ||
2370 strcmp(s,"r7") == 0 ) {
2372 sprintf(buffer,"a%s",s);
2373 pic16_emitcode("mov","@%s,%s",
2374 aop->aopu.aop_ptr->name,buffer);
2376 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2381 if (strcmp(s,"a") == 0)
2382 pic16_emitcode("push","acc");
2384 pic16_emitcode("push","%s",s);
2389 /* if bit variable */
2390 if (!aop->aopu.aop_dir) {
2391 pic16_emitcode("clr","a");
2392 pic16_emitcode("rlc","a");
2395 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2398 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2401 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2403 lbl = newiTempLabel(NULL);
2405 if (strcmp(s,"a")) {
2408 pic16_emitcode("clr","c");
2409 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2410 pic16_emitcode("cpl","c");
2411 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2412 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2419 if (strcmp(aop->aopu.aop_str[offset],s))
2420 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2425 if (!offset && (strcmp(s,"acc") == 0))
2428 if (strcmp(aop->aopu.aop_str[offset],s))
2429 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2433 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2434 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2435 // "pic16_aopPut got unsupported aop->type");
2441 /*-----------------------------------------------------------------*/
2442 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2443 /*-----------------------------------------------------------------*/
2444 void pic16_mov2w (asmop *aop, int offset)
2446 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2449 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2451 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2454 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2456 if(is_LitAOp(src)) {
2457 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2458 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2460 if(pic16_sameRegsOfs(src, dst, offset))return;
2461 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2462 pic16_popGet(dst, offset)));
2466 static void pic16_movLit2f(pCodeOp *pc, int lit)
2468 if (0 == (lit & 0x00ff))
2470 pic16_emitpcode (POC_CLRF, pc);
2471 } else if (0xff == (lit & 0x00ff))
2473 pic16_emitpcode (POC_SETF, pc);
2475 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2476 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2480 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2482 if(is_LitAOp(src)) {
2483 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2484 pic16_emitpcode(POC_MOVWF, dst);
2486 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2490 void pic16_testStackOverflow(void)
2492 #define GSTACK_TEST_NAME "_gstack_test"
2494 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2499 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2500 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2501 // strcpy(sym->rname, GSTACK_TEST_NAME);
2502 checkAddSym(&externs, sym);
2507 /* push pcop into stack */
2508 void pic16_pushpCodeOp(pCodeOp *pcop)
2510 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2511 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2512 if(pic16_options.gstack)
2513 pic16_testStackOverflow();
2517 /* pop pcop from stack */
2518 void pic16_poppCodeOp(pCodeOp *pcop)
2520 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2521 if(pic16_options.gstack)
2522 pic16_testStackOverflow();
2526 /*-----------------------------------------------------------------*/
2527 /* pushw - pushes wreg to stack */
2528 /*-----------------------------------------------------------------*/
2531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2532 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2533 if(pic16_options.gstack)
2534 pic16_testStackOverflow();
2538 /*-----------------------------------------------------------------*/
2539 /* pushaop - pushes aop to stack */
2540 /*-----------------------------------------------------------------*/
2541 void pushaop(asmop *aop, int offset)
2543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2545 if(_G.resDirect)return;
2547 if(is_LitAOp(aop)) {
2548 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2549 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2551 pic16_emitpcode(POC_MOVFF,
2552 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2555 if(pic16_options.gstack)
2556 pic16_testStackOverflow();
2559 /*-----------------------------------------------------------------*/
2560 /* popaop - pops aop from stack */
2561 /*-----------------------------------------------------------------*/
2562 void popaop(asmop *aop, int offset)
2564 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2565 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2566 if(pic16_options.gstack)
2567 pic16_testStackOverflow();
2570 void popaopidx(asmop *aop, int offset, int index)
2574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2576 if(STACK_MODEL_LARGE)ofs++;
2578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2579 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2580 if(pic16_options.gstack)
2581 pic16_testStackOverflow();
2584 #if !(USE_GENERIC_SIGNED_SHIFT)
2585 /*-----------------------------------------------------------------*/
2586 /* reAdjustPreg - points a register back to where it should */
2587 /*-----------------------------------------------------------------*/
2588 static void reAdjustPreg (asmop *aop)
2592 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2594 if ((size = aop->size) <= 1)
2597 switch (aop->type) {
2601 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2605 if (aop->type == AOP_DPTR2)
2611 pic16_emitcode("lcall","__decdptr");
2614 if (aop->type == AOP_DPTR2)
2626 /*-----------------------------------------------------------------*/
2627 /* opIsGptr: returns non-zero if the passed operand is */
2628 /* a generic pointer type. */
2629 /*-----------------------------------------------------------------*/
2630 static int opIsGptr(operand *op)
2632 sym_link *type = operandType(op);
2634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2635 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2643 /*-----------------------------------------------------------------*/
2644 /* pic16_getDataSize - get the operand data size */
2645 /*-----------------------------------------------------------------*/
2646 int pic16_getDataSize(operand *op)
2648 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2651 return AOP_SIZE(op);
2653 // tsd- in the pic port, the genptr size is 1, so this code here
2654 // fails. ( in the 8051 port, the size was 4).
2657 size = AOP_SIZE(op);
2658 if (size == GPTRSIZE)
2660 sym_link *type = operandType(op);
2661 if (IS_GENPTR(type))
2663 /* generic pointer; arithmetic operations
2664 * should ignore the high byte (pointer type).
2667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2674 /*-----------------------------------------------------------------*/
2675 /* pic16_outAcc - output Acc */
2676 /*-----------------------------------------------------------------*/
2677 void pic16_outAcc(operand *result)
2680 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2681 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2684 size = pic16_getDataSize(result);
2686 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2689 /* unsigned or positive */
2691 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2696 /*-----------------------------------------------------------------*/
2697 /* pic16_outBitC - output a bit C */
2698 /* Move to result the value of Carry flag -- VR */
2699 /*-----------------------------------------------------------------*/
2700 void pic16_outBitC(operand *result)
2704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2706 /* if the result is bit */
2707 if (AOP_TYPE(result) == AOP_CRY) {
2708 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2709 pic16_aopPut(AOP(result),"c",0);
2712 i = AOP_SIZE(result);
2714 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2716 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2720 /*-----------------------------------------------------------------*/
2721 /* pic16_outBitOp - output a bit from Op */
2722 /* Move to result the value of set/clr op -- VR */
2723 /*-----------------------------------------------------------------*/
2724 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2730 /* if the result is bit */
2731 if (AOP_TYPE(result) == AOP_CRY) {
2732 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2733 pic16_aopPut(AOP(result),"c",0);
2736 i = AOP_SIZE(result);
2738 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2740 pic16_emitpcode(POC_RRCF, pcop);
2741 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2745 /*-----------------------------------------------------------------*/
2746 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2747 /*-----------------------------------------------------------------*/
2748 void pic16_toBoolean(operand *oper)
2750 int size = AOP_SIZE(oper) - 1;
2753 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2755 if ( AOP_TYPE(oper) != AOP_ACC) {
2756 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2759 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2763 /*-----------------------------------------------------------------*/
2764 /* genUminusFloat - unary minus for floating points */
2765 /*-----------------------------------------------------------------*/
2766 static void genUminusFloat(operand *op,operand *result)
2768 int size ,offset =0 ;
2771 /* for this we just need to flip the
2772 first it then copy the rest in place */
2773 size = AOP_SIZE(op);
2774 assert( size == AOP_SIZE(result) );
2777 pic16_mov2f(AOP(result), AOP(op), offset);
2781 /* toggle the MSB's highest bit */
2782 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2785 /*-----------------------------------------------------------------*/
2786 /* genUminus - unary minus code generation */
2787 /*-----------------------------------------------------------------*/
2788 static void genUminus (iCode *ic)
2791 sym_link *optype, *rtype;
2798 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2799 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2801 /* if both in bit space then special case */
2802 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2803 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2805 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2806 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2807 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2811 optype = operandType(IC_LEFT(ic));
2812 rtype = operandType(IC_RESULT(ic));
2815 /* if float then do float stuff */
2816 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2817 if(IS_FIXED(optype))
2818 debugf("implement fixed16x16 type\n", 0);
2820 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2824 /* otherwise subtract from zero by taking the 2's complement */
2825 size = AOP_SIZE(IC_LEFT(ic));
2826 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2827 label = newiTempLabel ( NULL );
2829 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2830 for (i=size-1; i > 0; i--) {
2831 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2833 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2834 for (i=1; i < size; i++) {
2835 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2836 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2839 for (i=size-1; i >= 0; i--) {
2840 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2841 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2844 for (i=0; i < size-2; i++) {
2845 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2846 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2848 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2850 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2853 pic16_emitpLabel (label->key);
2856 /* release the aops */
2857 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2858 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2862 /*-----------------------------------------------------------------*/
2863 /* saveRegisters - will look for a call and save the registers */
2864 /*-----------------------------------------------------------------*/
2865 static void saveRegisters(iCode *lic)
2872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2874 for (ic = lic ; ic ; ic = ic->next)
2875 if (ic->op == CALL || ic->op == PCALL)
2879 fprintf(stderr,"found parameter push with no function call\n");
2883 /* if the registers have been saved already then
2885 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2888 /* find the registers in use at this time
2889 and push them away to safety */
2890 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2894 if (options.useXstack) {
2895 if (bitVectBitValue(rsave,R0_IDX))
2896 pic16_emitcode("mov","b,r0");
2897 pic16_emitcode("mov","r0,%s",spname);
2898 for (i = 0 ; i < pic16_nRegs ; i++) {
2899 if (bitVectBitValue(rsave,i)) {
2901 pic16_emitcode("mov","a,b");
2903 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2904 pic16_emitcode("movx","@r0,a");
2905 pic16_emitcode("inc","r0");
2908 pic16_emitcode("mov","%s,r0",spname);
2909 if (bitVectBitValue(rsave,R0_IDX))
2910 pic16_emitcode("mov","r0,b");
2912 //for (i = 0 ; i < pic16_nRegs ; i++) {
2913 // if (bitVectBitValue(rsave,i))
2914 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2917 dtype = operandType(IC_LEFT(ic));
2918 if (currFunc && dtype &&
2919 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2920 IFFUNC_ISISR(currFunc->type) &&
2923 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2926 /*-----------------------------------------------------------------*/
2927 /* unsaveRegisters - pop the pushed registers */
2928 /*-----------------------------------------------------------------*/
2929 static void unsaveRegisters (iCode *ic)
2934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2935 /* find the registers in use at this time
2936 and push them away to safety */
2937 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2940 if (options.useXstack) {
2941 pic16_emitcode("mov","r0,%s",spname);
2942 for (i = pic16_nRegs ; i >= 0 ; i--) {
2943 if (bitVectBitValue(rsave,i)) {
2944 pic16_emitcode("dec","r0");
2945 pic16_emitcode("movx","a,@r0");
2947 pic16_emitcode("mov","b,a");
2949 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2953 pic16_emitcode("mov","%s,r0",spname);
2954 if (bitVectBitValue(rsave,R0_IDX))
2955 pic16_emitcode("mov","r0,b");
2957 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2958 // if (bitVectBitValue(rsave,i))
2959 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2966 /*-----------------------------------------------------------------*/
2968 /*-----------------------------------------------------------------*/
2969 static void pushSide(operand * oper, int size)
2972 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2974 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2975 if (AOP_TYPE(oper) != AOP_REG &&
2976 AOP_TYPE(oper) != AOP_DIR &&
2978 pic16_emitcode("mov","a,%s",l);
2979 pic16_emitcode("push","acc");
2981 pic16_emitcode("push","%s",l);
2986 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2988 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2989 pic16_emitpcode(POC_MOVFW, src);
2990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2992 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2993 src, pic16_popGet(AOP(op), offset)));
2998 /*-----------------------------------------------------------------*/
2999 /* assignResultValue - assign results to oper, rescall==1 is */
3000 /* called from genCall() or genPcall() */
3001 /*-----------------------------------------------------------------*/
3002 static void assignResultValue(operand * oper, int rescall)
3004 int size = AOP_SIZE(oper);
3008 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3009 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3012 /* assign result from a call/pcall function() */
3014 /* function results are stored in a special order,
3015 * see top of file with Function return policy, or manual */
3018 /* 8-bits, result in WREG */
3019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3022 /* 16-bits, result in PRODL:WREG */
3023 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3027 /* 24-bits, result in PRODH:PRODL:WREG */
3028 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3032 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3033 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3037 /* >32-bits, result on stack, and FSR0 points to beginning.
3038 * Fix stack when done */
3040 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3042 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3043 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3045 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3050 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3051 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3052 if(STACK_MODEL_LARGE) {
3054 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3058 int areg = 0; /* matching argument register */
3060 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3061 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3064 /* its called from genReceive (probably) -- VR */
3065 /* I hope this code will not be called from somewhere else in the future!
3066 * We manually set the pseudo stack pointer in genReceive. - dw
3068 if(!GpsuedoStkPtr && _G.useWreg) {
3069 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3071 /* The last byte in the assignment is in W */
3072 if(areg <= GpsuedoStkPtr) {
3074 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3076 // debugf("receive from WREG\n", 0);
3078 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3081 _G.stack_lat = AOP_SIZE(oper)-1;
3086 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3087 // debugf("receive from STACK\n", 0);
3094 /*-----------------------------------------------------------------*/
3095 /* genIpush - generate code for pushing this gets a little complex */
3096 /*-----------------------------------------------------------------*/
3097 static void genIpush (iCode *ic)
3099 // int size, offset=0;
3102 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3105 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3107 /* send to stack as normal */
3108 addSet(&_G.sendSet,ic);
3109 // addSetHead(&_G.sendSet,ic);
3110 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3115 int size, offset = 0 ;
3119 /* if this is not a parm push : ie. it is spill push
3120 and spill push is always done on the local stack */
3121 if (!ic->parmPush) {
3123 /* and the item is spilt then do nothing */
3124 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3127 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3128 size = AOP_SIZE(IC_LEFT(ic));
3129 /* push it on the stack */
3131 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3136 pic16_emitcode("push","%s",l);
3141 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3145 /*-----------------------------------------------------------------*/
3146 /* genIpop - recover the registers: can happen only for spilling */
3147 /*-----------------------------------------------------------------*/
3148 static void genIpop (iCode *ic)
3151 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3156 /* if the temp was not pushed then */
3157 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3160 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3161 size = AOP_SIZE(IC_LEFT(ic));
3164 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3167 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3172 /*-----------------------------------------------------------------*/
3173 /* unsaverbank - restores the resgister bank from stack */
3174 /*-----------------------------------------------------------------*/
3175 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3177 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3185 if (options.useXstack) {
3187 r = getFreePtr(ic,&aop,FALSE);
3190 pic16_emitcode("mov","%s,_spx",r->name);
3191 pic16_emitcode("movx","a,@%s",r->name);
3192 pic16_emitcode("mov","psw,a");
3193 pic16_emitcode("dec","%s",r->name);
3196 pic16_emitcode ("pop","psw");
3199 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3200 if (options.useXstack) {
3201 pic16_emitcode("movx","a,@%s",r->name);
3202 //pic16_emitcode("mov","(%s+%d),a",
3203 // regspic16[i].base,8*bank+regspic16[i].offset);
3204 pic16_emitcode("dec","%s",r->name);
3207 pic16_emitcode("pop",""); //"(%s+%d)",
3208 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3211 if (options.useXstack) {
3213 pic16_emitcode("mov","_spx,%s",r->name);
3214 pic16_freeAsmop(NULL,aop,ic,TRUE);
3220 /*-----------------------------------------------------------------*/
3221 /* saverbank - saves an entire register bank on the stack */
3222 /*-----------------------------------------------------------------*/
3223 static void saverbank (int bank, iCode *ic, bool pushPsw)
3225 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3232 if (options.useXstack) {
3235 r = getFreePtr(ic,&aop,FALSE);
3236 pic16_emitcode("mov","%s,_spx",r->name);
3240 for (i = 0 ; i < pic16_nRegs ;i++) {
3241 if (options.useXstack) {
3242 pic16_emitcode("inc","%s",r->name);
3243 //pic16_emitcode("mov","a,(%s+%d)",
3244 // regspic16[i].base,8*bank+regspic16[i].offset);
3245 pic16_emitcode("movx","@%s,a",r->name);
3247 pic16_emitcode("push","");// "(%s+%d)",
3248 //regspic16[i].base,8*bank+regspic16[i].offset);
3252 if (options.useXstack) {
3253 pic16_emitcode("mov","a,psw");
3254 pic16_emitcode("movx","@%s,a",r->name);
3255 pic16_emitcode("inc","%s",r->name);
3256 pic16_emitcode("mov","_spx,%s",r->name);
3257 pic16_freeAsmop (NULL,aop,ic,TRUE);
3260 pic16_emitcode("push","psw");
3262 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3270 static int wparamCmp(void *p1, void *p2)
3272 return (!strcmp((char *)p1, (char *)p2));
3275 int inWparamList(char *s)
3277 return isinSetWith(wparamList, s, wparamCmp);
3281 /*-----------------------------------------------------------------*/
3282 /* genCall - generates a call statement */
3283 /*-----------------------------------------------------------------*/
3284 static void genCall (iCode *ic)
3294 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3295 /* if caller saves & we have not saved then */
3296 // if (!ic->regsSaved)
3297 // saveRegisters(ic);
3299 /* initialise stackParms for IPUSH pushes */
3300 // stackParms = psuedoStkPtr;
3301 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3302 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3303 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3306 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3309 /* if send set is not empty the assign */
3312 int psuedoStkPtr=-1;
3313 int firstTimeThruLoop = 1;
3316 /* reverse sendSet if function is not reentrant */
3317 if(!IFFUNC_ISREENT(ftype))
3318 _G.sendSet = reverseSet(_G.sendSet);
3320 /* First figure how many parameters are getting passed */
3324 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3328 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329 size = AOP_SIZE(IC_LEFT(sic));
3333 /* pass the last byte through WREG */
3337 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3339 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3341 if(!firstTimeThruLoop) {
3342 /* If this is not the first time we've been through the loop
3343 * then we need to save the parameter in a temporary
3344 * register. The last byte of the last parameter is
3348 // --psuedoStkPtr; // sanity check
3352 firstTimeThruLoop=0;
3354 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3359 /* all arguments are passed via stack */
3363 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3367 // pushaop(AOP(IC_LEFT(sic)), size);
3368 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3375 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3379 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3380 pushw(); /* save last parameter to stack if functions has varargs */
3384 } else use_wreg = 0;
3386 _G.stackRegSet = _G.sendSet;
3391 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3395 /* if we need to assign a result value */
3396 if ((IS_ITEMP(IC_RESULT(ic))
3397 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3398 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3399 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3402 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3405 assignResultValue(IC_RESULT(ic), 1);
3407 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3408 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3410 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3413 if(!stackParms && ic->parmBytes) {
3414 stackParms = ic->parmBytes;
3417 stackParms -= use_wreg;
3420 if(stackParms == 1) {
3421 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3423 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3424 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3426 if(STACK_MODEL_LARGE) {
3428 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3433 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3436 /* adjust the stack for parameters if required */
3437 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3440 /* if register bank was saved then pop them */
3442 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3444 /* if we hade saved some registers then unsave them */
3445 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3446 unsaveRegisters (ic);
3452 /*-----------------------------------------------------------------*/
3453 /* genPcall - generates a call by pointer statement */
3454 /* new version, created from genCall - HJD */
3455 /*-----------------------------------------------------------------*/
3456 static void genPcall (iCode *ic)
3460 symbol *retlbl = newiTempLabel(NULL);
3461 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3465 fntype = operandType( IC_LEFT(ic) )->next;
3467 /* if send set is not empty the assign */
3470 int psuedoStkPtr=-1;
3472 /* reverse sendSet if function is not reentrant */
3473 if(!IFFUNC_ISREENT(fntype))
3474 _G.sendSet = reverseSet(_G.sendSet);
3478 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3481 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3482 size = AOP_SIZE(IC_LEFT(sic));
3485 /* all parameters are passed via stack, since WREG is clobbered
3486 * by the calling sequence */
3488 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3489 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3490 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3492 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3496 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3499 _G.stackRegSet = _G.sendSet;
3503 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3505 // push return address
3506 // push $ on return stack, then replace with retlbl
3508 /* Thanks to Thorsten Klose for pointing out that the following
3509 * snippet should be interrupt safe */
3510 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3511 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3513 pic16_emitpcodeNULLop(POC_PUSH);
3515 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3516 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3517 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3518 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3519 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3520 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3523 /* restore interrupt control register */
3524 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3525 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3527 /* make the call by writing the pointer into pc */
3528 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3529 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3531 // note: MOVFF to PCL not allowed
3532 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3533 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3536 /* return address is here: (X) */
3537 pic16_emitpLabelFORCE(retlbl->key);
3539 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3542 /* if we need assign a result value */
3543 if ((IS_ITEMP(IC_RESULT(ic))
3544 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3545 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3546 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3549 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3552 assignResultValue(IC_RESULT(ic), 1);
3554 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3555 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3557 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3560 // stackParms -= use_wreg;
3563 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3564 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3565 if(STACK_MODEL_LARGE) {
3567 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3572 /*-----------------------------------------------------------------*/
3573 /* resultRemat - result is rematerializable */
3574 /*-----------------------------------------------------------------*/
3575 static int resultRemat (iCode *ic)
3577 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3578 if (SKIP_IC(ic) || ic->op == IFX)
3581 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3582 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3583 if (sym->remat && !POINTER_SET(ic))
3590 #if defined(__BORLANDC__) || defined(_MSC_VER)
3591 #define STRCASECMP stricmp
3593 #define STRCASECMP strcasecmp
3597 /*-----------------------------------------------------------------*/
3598 /* inExcludeList - return 1 if the string is in exclude Reg list */
3599 /*-----------------------------------------------------------------*/
3600 static bool inExcludeList(char *s)
3602 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3606 if (options.excludeRegs[i] &&
3607 STRCASECMP(options.excludeRegs[i],"none") == 0)
3610 for ( i = 0 ; options.excludeRegs[i]; i++) {
3611 if (options.excludeRegs[i] &&
3612 STRCASECMP(s,options.excludeRegs[i]) == 0)
3619 /*-----------------------------------------------------------------*/
3620 /* genFunction - generated code for function entry */
3621 /*-----------------------------------------------------------------*/
3622 static void genFunction (iCode *ic)
3628 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3630 pic16_labelOffset += (max_key+4);
3635 ftype = operandType(IC_LEFT(ic));
3636 sym = OP_SYMBOL(IC_LEFT(ic));
3638 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3639 /* create an absolute section at the interrupt vector:
3640 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3645 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3647 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3648 sprintf(asymname, "ivec_%s", sym->name);
3650 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3652 /* when an interrupt is declared as naked, do not emit the special
3653 * wrapper segment at vector address. The user should take care for
3654 * this instead. -- VR */
3656 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3657 asym = newSymbol(asymname, 0);
3658 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3659 pic16_addpBlock( apb );
3661 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3662 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3663 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3664 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3665 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3667 /* mark the end of this tiny function */
3668 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3670 sprintf(asymname, "%s", sym->rname);
3676 abSym = Safe_calloc(1, sizeof(absSym));
3677 strcpy(abSym->name, asymname);
3679 switch( FUNC_INTNO(sym->type) ) {
3680 case 0: abSym->address = 0x000000; break;
3681 case 1: abSym->address = 0x000008; break;
3682 case 2: abSym->address = 0x000018; break;
3685 // fprintf(stderr, "no interrupt number is given\n");
3686 abSym->address = -1; break;
3689 /* relocate interrupt vectors if needed */
3690 if(abSym->address != -1)
3691 abSym->address += pic16_options.ivt_loc;
3693 addSet(&absSymSet, abSym);
3697 /* create the function header */
3698 pic16_emitcode(";","-----------------------------------------");
3699 pic16_emitcode(";"," function %s",sym->name);
3700 pic16_emitcode(";","-----------------------------------------");
3702 pic16_emitcode("","%s:",sym->rname);
3703 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3708 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3709 if(!strcmp(ab->name, sym->rname)) {
3710 pic16_pBlockConvert2Absolute(pb);
3716 if(IFFUNC_ISNAKED(ftype)) {
3717 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3721 /* if critical function then turn interrupts off */
3722 if (IFFUNC_ISCRITICAL(ftype)) {
3723 //pic16_emitcode("clr","ea");
3726 currFunc = sym; /* update the currFunc symbol */
3727 _G.fregsUsed = sym->regsUsed;
3728 _G.sregsAlloc = newBitVect(128);
3731 /* if this is an interrupt service routine then
3732 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3733 if (IFFUNC_ISISR(sym->type)) {
3734 _G.usefastretfie = 1; /* use shadow registers by default */
3736 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3737 if(!FUNC_ISSHADOWREGS(sym->type)) {
3738 /* do not save WREG,STATUS,BSR for high priority interrupts
3739 * because they are stored in the hardware shadow registers already */
3740 _G.usefastretfie = 0;
3741 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3742 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3743 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3746 /* these should really be optimized somehow, because not all
3747 * interrupt handlers modify them */
3748 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3749 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3750 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3751 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3753 // pic16_pBlockConvert2ISR(pb);
3756 /* emit code to setup stack frame if user enabled,
3757 * and function is not main() */
3759 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3760 if(strcmp(sym->name, "main")) {
3762 || !options.ommitFramePtr
3764 || IFFUNC_ARGS(sym->type)
3765 || FUNC_HASSTACKPARM(sym->etype)
3767 /* setup the stack frame */
3768 if(STACK_MODEL_LARGE)
3769 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3770 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3772 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3773 if(STACK_MODEL_LARGE)
3774 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3778 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3781 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3783 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3784 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3786 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3789 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3790 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3797 /* if callee-save to be used for this function
3798 * then save the registers being used in this function */
3799 // if (IFFUNC_CALLEESAVES(sym->type))
3800 if(strcmp(sym->name, "main")) {
3803 /* if any registers used */
3804 if (sym->regsUsed) {
3805 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3808 /* save the registers used */
3809 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3810 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3811 if (bitVectBitValue(sym->regsUsed,i)) {
3813 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3815 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3818 if(!pic16_regWithIdx(i)->wasUsed) {
3819 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3820 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3821 pic16_regWithIdx(i)->wasUsed = 1;
3828 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3829 for(i=0;i<sym->regsUsed->size;i++) {
3830 if(bitVectBitValue(sym->regsUsed, i)) {
3835 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3838 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3843 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3844 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3847 /*-----------------------------------------------------------------*/
3848 /* genEndFunction - generates epilogue for functions */
3849 /*-----------------------------------------------------------------*/
3850 static void genEndFunction (iCode *ic)
3852 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3856 if(IFFUNC_ISNAKED(sym->type)) {
3857 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3863 /* add code for ISCRITICAL */
3864 if(IFFUNC_ISCRITICAL(sym->type)) {
3865 /* if critical function, turn on interrupts */
3867 /* TODO: add code here -- VR */
3870 // sym->regsUsed = _G.fregsUsed;
3872 /* now we need to restore the registers */
3873 /* if any registers used */
3875 /* first restore registers that might be used for stack access */
3876 if(_G.sregsAllocSet) {
3879 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3880 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3881 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3885 if (strcmp(sym->name, "main") && sym->regsUsed) {
3888 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3889 /* restore registers used */
3890 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3891 for ( i = sym->regsUsed->size; i >= 0; i--) {
3892 if (bitVectBitValue(sym->regsUsed,i)) {
3893 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3897 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3902 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3904 if (sym->stack == 1) {
3905 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3906 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3908 // we have to add more than one...
3909 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3910 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3911 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3913 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3914 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3915 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3919 if(strcmp(sym->name, "main")) {
3921 || !options.ommitFramePtr
3923 || IFFUNC_ARGS(sym->type)
3924 || FUNC_HASSTACKPARM(sym->etype)
3926 /* restore stack frame */
3927 if(STACK_MODEL_LARGE)
3928 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3929 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3935 if (IFFUNC_ISISR(sym->type)) {
3936 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3937 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3938 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3939 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3941 if(!FUNC_ISSHADOWREGS(sym->type)) {
3942 /* do not restore interrupt vector for WREG,STATUS,BSR
3943 * for high priority interrupt, see genFunction */
3944 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3945 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3946 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3948 // _G.interruptvector = 0; /* sanity check */
3951 /* if debug then send end of function */
3952 /* if (options.debug && currFunc) */
3954 debugFile->writeEndFunction (currFunc, ic, 1);
3957 if(_G.usefastretfie)
3958 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3960 pic16_emitpcodeNULLop(POC_RETFIE);
3962 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3964 _G.usefastretfie = 0;
3968 if (IFFUNC_ISCRITICAL(sym->type)) {
3969 pic16_emitcode("setb","ea");
3972 /* if debug then send end of function */
3974 debugFile->writeEndFunction (currFunc, ic, 1);
3977 /* insert code to restore stack frame, if user enabled it
3978 * and function is not main() */
3981 pic16_emitpcodeNULLop(POC_RETURN);
3983 /* Mark the end of a function */
3984 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3988 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3990 unsigned long lit=1;
3995 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3996 if(AOP_TYPE(op) == AOP_LIT) {
3997 if(!IS_FLOAT(operandType( op ))) {
3998 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4001 unsigned long lit_int;
4005 /* take care if literal is a float */
4006 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4012 pic16_movLit2f(dest, lit);
4014 if(dest->type == PO_WREG && (offset == 0)) {
4015 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4018 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4022 /*-----------------------------------------------------------------*/
4023 /* genRet - generate code for return statement */
4024 /*-----------------------------------------------------------------*/
4025 static void genRet (iCode *ic)
4031 /* if we have no return value then
4032 * just generate the "ret" */
4037 /* we have something to return then
4038 * move the return value into place */
4039 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4040 size = AOP_SIZE(IC_LEFT(ic));
4044 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4047 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4050 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4052 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4055 /* >32-bits, setup stack and FSR0 */
4057 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4058 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4060 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4062 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4067 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4068 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4070 if(STACK_MODEL_LARGE) {
4071 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4074 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4079 /* old code, left here for reference -- VR */
4083 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4085 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4086 pic16_emitpcomment("push %s",l);
4089 DEBUGpic16_emitcode(";", "%d", __LINE__);
4090 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4091 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4093 if (strcmp(fReturn[offset],l)) {
4094 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4095 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4096 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4102 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4112 if (strcmp(fReturn[pushed],"a"))
4113 pic16_emitcode("pop",fReturn[pushed]);
4115 pic16_emitcode("pop","acc");
4121 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4124 /* generate a jump to the return label
4125 * if the next is not the return statement */
4126 if (!(ic->next && ic->next->op == LABEL
4127 && IC_LABEL(ic->next) == returnLabel)) {
4129 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4130 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4134 /*-----------------------------------------------------------------*/
4135 /* genLabel - generates a label */
4136 /*-----------------------------------------------------------------*/
4137 static void genLabel (iCode *ic)
4141 /* special case never generate */
4142 if (IC_LABEL(ic) == entryLabel)
4145 pic16_emitpLabel(IC_LABEL(ic)->key);
4146 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4149 /*-----------------------------------------------------------------*/
4150 /* genGoto - generates a goto */
4151 /*-----------------------------------------------------------------*/
4153 static void genGoto (iCode *ic)
4156 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4157 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4161 /*-----------------------------------------------------------------*/
4162 /* genMultbits :- multiplication of bits */
4163 /*-----------------------------------------------------------------*/
4164 static void genMultbits (operand *left,
4170 if(!pic16_sameRegs(AOP(result),AOP(right)))
4171 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4173 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4174 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4175 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4180 /*-----------------------------------------------------------------*/
4181 /* genMultOneByte : 8 bit multiplication & division */
4182 /*-----------------------------------------------------------------*/
4183 static void genMultOneByte (operand *left,
4189 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4190 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4192 /* (if two literals, the value is computed before) */
4193 /* if one literal, literal on the right */
4194 if (AOP_TYPE(left) == AOP_LIT){
4200 /* size is already checked in genMult == 1 */
4201 // size = AOP_SIZE(result);
4203 if (AOP_TYPE(right) == AOP_LIT){
4204 pic16_emitpcomment("multiply lit val:%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));
4209 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4210 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4211 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4212 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4215 pic16_genMult8X8_8 (left, right,result);
4218 /*-----------------------------------------------------------------*/
4219 /* genMultOneWord : 16 bit multiplication */
4220 /*-----------------------------------------------------------------*/
4221 static void genMultOneWord (operand *left,
4226 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4227 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4229 /* (if two literals, the value is computed before)
4230 * if one literal, literal on the right */
4231 if (AOP_TYPE(left) == AOP_LIT){
4237 /* size is checked already == 2 */
4238 // size = AOP_SIZE(result);
4240 if (AOP_TYPE(right) == AOP_LIT) {
4241 pic16_emitpcomment("multiply lit val:%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));
4246 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4247 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4248 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4249 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4252 pic16_genMult16X16_16(left, right,result);
4255 /*-----------------------------------------------------------------*/
4256 /* genMultOneLong : 32 bit multiplication */
4257 /*-----------------------------------------------------------------*/
4258 static void genMultOneLong (operand *left,
4263 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4264 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4266 /* (if two literals, the value is computed before)
4267 * if one literal, literal on the right */
4268 if (AOP_TYPE(left) == AOP_LIT){
4274 /* size is checked already == 4 */
4275 // size = AOP_SIZE(result);
4277 if (AOP_TYPE(right) == AOP_LIT) {
4278 pic16_emitpcomment("multiply lit val:%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));
4283 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4284 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4285 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4286 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4289 pic16_genMult32X32_32(left, right,result);
4294 /*-----------------------------------------------------------------*/
4295 /* genMult - generates code for multiplication */
4296 /*-----------------------------------------------------------------*/
4297 static void genMult (iCode *ic)
4299 operand *left = IC_LEFT(ic);
4300 operand *right = IC_RIGHT(ic);
4301 operand *result= IC_RESULT(ic);
4304 /* assign the amsops */
4305 pic16_aopOp (left,ic,FALSE);
4306 pic16_aopOp (right,ic,FALSE);
4307 pic16_aopOp (result,ic,TRUE);
4309 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4311 /* special cases first *
4313 if (AOP_TYPE(left) == AOP_CRY
4314 && AOP_TYPE(right)== AOP_CRY) {
4315 genMultbits(left,right,result);
4319 /* if both are of size == 1 */
4320 if(AOP_SIZE(left) == 1
4321 && AOP_SIZE(right) == 1) {
4322 genMultOneByte(left,right,result);
4326 /* if both are of size == 2 */
4327 if(AOP_SIZE(left) == 2
4328 && AOP_SIZE(right) == 2) {
4329 genMultOneWord(left, right, result);
4333 /* if both are of size == 4 */
4334 if(AOP_SIZE(left) == 4
4335 && AOP_SIZE(right) == 4) {
4336 genMultOneLong(left, right, result);
4340 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4343 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4344 /* should have been converted to function call */
4348 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350 pic16_freeAsmop(result,NULL,ic,TRUE);
4353 /*-----------------------------------------------------------------*/
4354 /* genDivbits :- division of bits */
4355 /*-----------------------------------------------------------------*/
4356 static void genDivbits (operand *left,
4363 /* the result must be bit */
4364 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4365 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4369 pic16_emitcode("div","ab");
4370 pic16_emitcode("rrc","a");
4371 pic16_aopPut(AOP(result),"c",0);
4374 /*-----------------------------------------------------------------*/
4375 /* genDivOneByte : 8 bit division */
4376 /*-----------------------------------------------------------------*/
4377 static void genDivOneByte (operand *left,
4381 sym_link *opetype = operandType(result);
4386 /* result = divident / divisor
4387 * - divident may be a register or a literal,
4388 * - divisor may be a register or a literal,
4389 * so there are 3 cases (literal / literal is optimized
4390 * by the front-end) to handle.
4391 * In addition we must handle signed and unsigned, which
4392 * result in 6 final different cases -- VR */
4396 size = AOP_SIZE(result) - 1;
4398 /* signed or unsigned */
4399 if (SPEC_USIGN(opetype)) {
4400 pCodeOp *pct1, /* count */
4403 symbol *label1, *label2, *label3;;
4406 /* unsigned is easy */
4408 pct1 = pic16_popGetTempReg(1);
4409 pct2 = pic16_popGetTempReg(1);
4410 pct3 = pic16_popGetTempReg(1);
4412 label1 = newiTempLabel(NULL);
4413 label2 = newiTempLabel(NULL);
4414 label3 = newiTempLabel(NULL);
4416 /* the following algorithm is extracted from divuint.c */
4418 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4419 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4421 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4423 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4425 pic16_emitpLabel(label1->key);
4428 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4432 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4436 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4438 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4439 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4441 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4442 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4443 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4445 pic16_emitpLabel( label3->key );
4446 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4447 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4451 pic16_emitpLabel(label2->key);
4452 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4453 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4454 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4456 /* result is in wreg */
4457 if(AOP_TYPE(result) != AOP_ACC)
4458 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4460 pic16_popReleaseTempReg( pct3, 1);
4461 pic16_popReleaseTempReg( pct2, 1);
4462 pic16_popReleaseTempReg( pct1, 1);
4467 /* signed is a little bit more difficult */
4469 /* save the signs of the operands */
4470 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4472 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4473 pic16_emitcode("push","acc"); /* save it on the stack */
4475 /* now sign adjust for both left & right */
4476 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4478 lbl = newiTempLabel(NULL);
4479 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4480 pic16_emitcode("cpl","a");
4481 pic16_emitcode("inc","a");
4482 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4483 pic16_emitcode("mov","b,a");
4485 /* sign adjust left side */
4486 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4489 lbl = newiTempLabel(NULL);
4490 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4491 pic16_emitcode("cpl","a");
4492 pic16_emitcode("inc","a");
4493 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4495 /* now the division */
4496 pic16_emitcode("div","ab");
4497 /* we are interested in the lower order
4499 pic16_emitcode("mov","b,a");
4500 lbl = newiTempLabel(NULL);
4501 pic16_emitcode("pop","acc");
4502 /* if there was an over flow we don't
4503 adjust the sign of the result */
4504 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4505 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4507 pic16_emitcode("clr","a");
4508 pic16_emitcode("subb","a,b");
4509 pic16_emitcode("mov","b,a");
4510 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4512 /* now we are done */
4513 pic16_aopPut(AOP(result),"b",0);
4515 pic16_emitcode("mov","c,b.7");
4516 pic16_emitcode("subb","a,acc");
4519 pic16_aopPut(AOP(result),"a",offset++);
4523 /*-----------------------------------------------------------------*/
4524 /* genDiv - generates code for division */
4525 /*-----------------------------------------------------------------*/
4526 static void genDiv (iCode *ic)
4528 operand *left = IC_LEFT(ic);
4529 operand *right = IC_RIGHT(ic);
4530 operand *result= IC_RESULT(ic);
4533 /* Division is a very lengthy algorithm, so it is better
4534 * to call support routines than inlining algorithm.
4535 * Division functions written here just in case someone
4536 * wants to inline and not use the support libraries -- VR */
4540 /* assign the amsops */
4541 pic16_aopOp (left,ic,FALSE);
4542 pic16_aopOp (right,ic,FALSE);
4543 pic16_aopOp (result,ic,TRUE);
4545 /* special cases first */
4547 if (AOP_TYPE(left) == AOP_CRY &&
4548 AOP_TYPE(right)== AOP_CRY) {
4549 genDivbits(left,right,result);
4553 /* if both are of size == 1 */
4554 if (AOP_SIZE(left) == 1 &&
4555 AOP_SIZE(right) == 1 ) {
4556 genDivOneByte(left,right,result);
4560 /* should have been converted to function call */
4563 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4564 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4565 pic16_freeAsmop(result,NULL,ic,TRUE);
4568 /*-----------------------------------------------------------------*/
4569 /* genModbits :- modulus of bits */
4570 /*-----------------------------------------------------------------*/
4571 static void genModbits (operand *left,
4579 werror(W_POSSBUG2, __FILE__, __LINE__);
4580 /* the result must be bit */
4581 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4582 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4586 pic16_emitcode("div","ab");
4587 pic16_emitcode("mov","a,b");
4588 pic16_emitcode("rrc","a");
4589 pic16_aopPut(AOP(result),"c",0);
4592 /*-----------------------------------------------------------------*/
4593 /* genModOneByte : 8 bit modulus */
4594 /*-----------------------------------------------------------------*/
4595 static void genModOneByte (operand *left,
4599 sym_link *opetype = operandType(result);
4604 werror(W_POSSBUG2, __FILE__, __LINE__);
4606 /* signed or unsigned */
4607 if (SPEC_USIGN(opetype)) {
4608 /* unsigned is easy */
4609 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4610 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4612 pic16_emitcode("div","ab");
4613 pic16_aopPut(AOP(result),"b",0);
4617 /* signed is a little bit more difficult */
4619 /* save the signs of the operands */
4620 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4623 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4624 pic16_emitcode("push","acc"); /* save it on the stack */
4626 /* now sign adjust for both left & right */
4627 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4630 lbl = newiTempLabel(NULL);
4631 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4632 pic16_emitcode("cpl","a");
4633 pic16_emitcode("inc","a");
4634 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4635 pic16_emitcode("mov","b,a");
4637 /* sign adjust left side */
4638 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4641 lbl = newiTempLabel(NULL);
4642 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4643 pic16_emitcode("cpl","a");
4644 pic16_emitcode("inc","a");
4645 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4647 /* now the multiplication */
4648 pic16_emitcode("div","ab");
4649 /* we are interested in the lower order
4651 lbl = newiTempLabel(NULL);
4652 pic16_emitcode("pop","acc");
4653 /* if there was an over flow we don't
4654 adjust the sign of the result */
4655 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4656 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4658 pic16_emitcode("clr","a");
4659 pic16_emitcode("subb","a,b");
4660 pic16_emitcode("mov","b,a");
4661 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4663 /* now we are done */
4664 pic16_aopPut(AOP(result),"b",0);
4668 /*-----------------------------------------------------------------*/
4669 /* genMod - generates code for division */
4670 /*-----------------------------------------------------------------*/
4671 static void genMod (iCode *ic)
4673 operand *left = IC_LEFT(ic);
4674 operand *right = IC_RIGHT(ic);
4675 operand *result= IC_RESULT(ic);
4679 /* assign the amsops */
4680 pic16_aopOp (left,ic,FALSE);
4681 pic16_aopOp (right,ic,FALSE);
4682 pic16_aopOp (result,ic,TRUE);
4684 /* special cases first */
4686 if (AOP_TYPE(left) == AOP_CRY &&
4687 AOP_TYPE(right)== AOP_CRY) {
4688 genModbits(left,right,result);
4692 /* if both are of size == 1 */
4693 if (AOP_SIZE(left) == 1 &&
4694 AOP_SIZE(right) == 1 ) {
4695 genModOneByte(left,right,result);
4699 /* should have been converted to function call */
4703 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4704 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705 pic16_freeAsmop(result,NULL,ic,TRUE);
4708 /*-----------------------------------------------------------------*/
4709 /* genIfxJump :- will create a jump depending on the ifx */
4710 /*-----------------------------------------------------------------*/
4712 note: May need to add parameter to indicate when a variable is in bit space.
4714 static void genIfxJump (iCode *ic, char *jval)
4718 /* if true label then we jump if condition
4720 if ( IC_TRUE(ic) ) {
4722 if(strcmp(jval,"a") == 0)
4724 else if (strcmp(jval,"c") == 0)
4727 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4728 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4731 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4732 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4736 /* false label is present */
4737 if(strcmp(jval,"a") == 0)
4739 else if (strcmp(jval,"c") == 0)
4742 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4743 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4746 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4747 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4752 /* mark the icode as generated */
4756 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4760 /* if true label then we jump if condition
4762 if ( IC_TRUE(ic) ) {
4763 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4764 pic16_emitpcode(POC_BTFSC, jop);
4766 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4767 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4770 /* false label is present */
4771 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4772 pic16_emitpcode(POC_BTFSS, jop);
4774 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4775 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4779 /* mark the icode as generated */
4786 /*-----------------------------------------------------------------*/
4788 /*-----------------------------------------------------------------*/
4789 static void genSkip(iCode *ifx,int status_bit)
4791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4795 if ( IC_TRUE(ifx) ) {
4796 switch(status_bit) {
4811 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4812 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4816 switch(status_bit) {
4830 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4831 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4838 /*-----------------------------------------------------------------*/
4840 /*-----------------------------------------------------------------*/
4841 static void genSkipc(resolvedIfx *rifx)
4843 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4853 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4854 rifx->generated = 1;
4857 #if !(USE_SIMPLE_GENCMP)
4858 /*-----------------------------------------------------------------*/
4860 /*-----------------------------------------------------------------*/
4861 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4863 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4868 if( (rifx->condition ^ invert_condition) & 1)
4873 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4874 rifx->generated = 1;
4879 /*-----------------------------------------------------------------*/
4881 /*-----------------------------------------------------------------*/
4882 static void genSkipz(iCode *ifx, int condition)
4893 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4898 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4900 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4905 #if !(USE_SIMPLE_GENCMP)
4906 /*-----------------------------------------------------------------*/
4908 /*-----------------------------------------------------------------*/
4909 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4915 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4917 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4920 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4921 rifx->generated = 1;
4926 /*-----------------------------------------------------------------*/
4927 /* genChkZeroes :- greater or less than comparison */
4928 /* For each byte in a literal that is zero, inclusive or the */
4929 /* the corresponding byte in the operand with W */
4930 /* returns true if any of the bytes are zero */
4931 /*-----------------------------------------------------------------*/
4932 static int genChkZeroes(operand *op, int lit, int size)
4939 i = (lit >> (size*8)) & 0xff;
4943 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4945 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4955 /*-----------------------------------------------------------------*/
4956 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4957 /* aop (if it's NOT a literal) or from lit (if */
4958 /* aop is a literal) */
4959 /*-----------------------------------------------------------------*/
4960 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4961 if (aop->type == AOP_LIT) {
4962 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4964 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4968 /*-----------------------------------------------------------------*/
4969 /* genCmp :- greater or less than comparison */
4970 /*-----------------------------------------------------------------*/
4972 #if USE_SIMPLE_GENCMP /* { */
4974 /* genCmp performs a left < right comparison, stores
4975 * the outcome in result (if != NULL) and generates
4976 * control flow code for the ifx (if != NULL).
4978 * This version leaves in sequences like
4979 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4980 * which should be optmized by the peephole
4981 * optimizer - RN 2005-01-01 */
4982 static void genCmp (operand *left,operand *right,
4983 operand *result, iCode *ifx, int sign)
4996 assert (left && right);
4997 assert (AOP_SIZE(left) == AOP_SIZE(right));
4999 size = AOP_SIZE(right) - 1;
5000 mask = (0x100UL << (size*8)) - 1;
5001 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5006 resolveIfx (&rIfx, ifx);
5008 /* handle for special cases */
5009 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5012 /**********************************************************************
5013 * handle bits - bit compares are promoted to int compares seemingly! *
5014 **********************************************************************/
5016 // THIS IS COMPLETELY UNTESTED!
5017 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5018 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5019 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5020 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5023 // 1 < {0,1} is false --> clear C by skipping the next instruction
5024 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5025 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5026 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5027 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5028 emitCLRC; // only skipped for left=0 && right=1
5030 goto correct_result_in_carry;
5034 /*************************************************
5035 * make sure that left is register (or the like) *
5036 *************************************************/
5037 if (!isAOP_REGlike(left)) {
5038 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5039 assert (isAOP_LIT(left));
5040 assert (isAOP_REGlike(right));
5041 // swap left and right
5042 // left < right <==> right > left <==> (right >= left + 1)
5043 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5045 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5046 // MAXVALUE < right? always false
5047 if (performedLt) emitCLRC; else emitSETC;
5048 goto correct_result_in_carry;
5051 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5052 // that's why we handled it above.
5059 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5060 } else if (isAOP_LIT(right)) {
5061 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5064 assert (isAOP_REGlike(left)); // left must be register or the like
5065 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5067 /*************************************************
5068 * special cases go here *
5069 *************************************************/
5071 if (isAOP_LIT(right)) {
5073 // unsigned comparison to a literal
5074 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5076 // unsigned left < 0? always false
5077 if (performedLt) emitCLRC; else emitSETC;
5078 goto correct_result_in_carry;
5081 // signed comparison to a literal
5082 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5083 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5084 // signed left < 0x80000000? always false
5085 if (performedLt) emitCLRC; else emitSETC;
5086 goto correct_result_in_carry;
5087 } else if (lit == 0) {
5088 // compare left < 0; set CARRY if SIGNBIT(left) is set
5089 if (performedLt) emitSETC; else emitCLRC;
5090 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5091 if (performedLt) emitCLRC; else emitSETC;
5092 goto correct_result_in_carry;
5095 } // right is literal
5097 /*************************************************
5098 * perform a general case comparison *
5099 * make sure we get CARRY==1 <==> left >= right *
5100 *************************************************/
5101 // compare most significant bytes
5102 //DEBUGpc ("comparing bytes at offset %d", size);
5104 // unsigned comparison
5105 mov2w_regOrLit (AOP(right), lit, size);
5106 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5108 // signed comparison
5109 // (add 2^n to both operands then perform an unsigned comparison)
5110 if (isAOP_LIT(right)) {
5111 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5112 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5114 if (litbyte == 0x80) {
5115 // left >= 0x80 -- always true, but more bytes to come
5116 pic16_mov2w (AOP(left), size);
5117 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5120 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5121 pic16_mov2w (AOP(left), size);
5122 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5123 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5126 /* using PRODL as a temporary register here */
5127 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5128 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5129 pic16_mov2w (AOP(left), size);
5130 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131 pic16_emitpcode (POC_MOVWF, pctemp);
5132 pic16_mov2w (AOP(right), size);
5133 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5134 pic16_emitpcode (POC_SUBFW, pctemp);
5135 //pic16_popReleaseTempReg(pctemp, 1);
5139 // compare remaining bytes (treat as unsigned case from above)
5140 templbl = newiTempLabel ( NULL );
5143 //DEBUGpc ("comparing bytes at offset %d", offs);
5144 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5145 mov2w_regOrLit (AOP(right), lit, offs);
5146 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5148 pic16_emitpLabel (templbl->key);
5149 goto result_in_carry;
5153 /****************************************************
5154 * now CARRY contains the result of the comparison: *
5155 * SUBWF sets CARRY iff *
5156 * F-W >= 0 <==> F >= W <==> !(F < W) *
5157 * (F=left, W=right) *
5158 ****************************************************/
5161 if (result && AOP_TYPE(result) != AOP_CRY) {
5162 // value will be stored
5165 // value wil only be used in the following genSkipc()
5166 rIfx.condition ^= 1;
5170 correct_result_in_carry:
5172 // assign result to variable (if neccessary)
5173 if (result && AOP_TYPE(result) != AOP_CRY) {
5174 //DEBUGpc ("assign result");
5175 size = AOP_SIZE(result);
5177 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5179 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5182 // perform conditional jump
5184 //DEBUGpc ("generate control flow");
5193 static void genCmp (operand *left,operand *right,
5194 operand *result, iCode *ifx, int sign)
5196 int size; //, offset = 0 ;
5197 unsigned long lit = 0L,i = 0;
5198 resolvedIfx rFalseIfx;
5199 // resolvedIfx rTrueIfx;
5201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5204 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5205 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5211 resolveIfx(&rFalseIfx,ifx);
5212 truelbl = newiTempLabel(NULL);
5213 size = max(AOP_SIZE(left),AOP_SIZE(right));
5215 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5219 /* if literal is on the right then swap with left */
5220 if ((AOP_TYPE(right) == AOP_LIT)) {
5221 operand *tmp = right ;
5222 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5223 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5226 lit = (lit - 1) & mask;
5229 rFalseIfx.condition ^= 1;
5232 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5233 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5237 //if(IC_TRUE(ifx) == NULL)
5238 /* if left & right are bit variables */
5239 if (AOP_TYPE(left) == AOP_CRY &&
5240 AOP_TYPE(right) == AOP_CRY ) {
5241 assert (0 && "bit variables used in genCmp");
5242 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5245 /* subtract right from left if at the
5246 end the carry flag is set then we know that
5247 left is greater than right */
5249 symbol *lbl = newiTempLabel(NULL);
5252 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5253 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5257 if(AOP_TYPE(right) == AOP_LIT) {
5259 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5261 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5268 genSkipCond(&rFalseIfx,left,size-1,7);
5270 /* no need to compare to 0...*/
5271 /* NOTE: this is a de-generate compare that most certainly
5272 * creates some dead code. */
5273 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5275 if(ifx) ifx->generated = 1;
5282 //i = (lit >> (size*8)) & 0xff;
5283 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5285 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5287 i = ((0-lit) & 0xff);
5290 /* lit is 0x7f, all signed chars are less than
5291 * this except for 0x7f itself */
5292 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5293 genSkipz2(&rFalseIfx,0);
5295 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5297 genSkipc(&rFalseIfx);
5302 genSkipz2(&rFalseIfx,1);
5304 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5305 genSkipc(&rFalseIfx);
5309 if(ifx) ifx->generated = 1;
5313 /* chars are out of the way. now do ints and longs */
5316 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5323 genSkipCond(&rFalseIfx,left,size,7);
5324 if(ifx) ifx->generated = 1;
5329 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5331 //rFalseIfx.condition ^= 1;
5332 //genSkipCond(&rFalseIfx,left,size,7);
5333 //rFalseIfx.condition ^= 1;
5335 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336 if(rFalseIfx.condition)
5337 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5342 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5346 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5348 if(rFalseIfx.condition) {
5350 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5356 genSkipc(&rFalseIfx);
5357 pic16_emitpLabel(truelbl->key);
5358 if(ifx) ifx->generated = 1;
5365 if( (lit & 0xff) == 0) {
5366 /* lower byte is zero */
5367 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5368 i = ((lit >> 8) & 0xff) ^0x80;
5369 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5370 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5371 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5372 genSkipc(&rFalseIfx);
5375 if(ifx) ifx->generated = 1;
5380 /* Special cases for signed longs */
5381 if( (lit & 0xffffff) == 0) {
5382 /* lower byte is zero */
5383 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384 i = ((lit >> 8*3) & 0xff) ^0x80;
5385 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5386 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5387 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5388 genSkipc(&rFalseIfx);
5391 if(ifx) ifx->generated = 1;
5399 if(lit & (0x80 << (size*8))) {
5400 /* lit is negative */
5401 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5403 //genSkipCond(&rFalseIfx,left,size,7);
5405 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5407 if(rFalseIfx.condition)
5408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5414 /* lit is positive */
5415 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5416 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417 if(rFalseIfx.condition)
5418 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5420 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5425 This works, but is only good for ints.
5426 It also requires a "known zero" register.
5427 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5428 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5429 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5430 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5431 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5432 genSkipc(&rFalseIfx);
5434 pic16_emitpLabel(truelbl->key);
5435 if(ifx) ifx->generated = 1;
5439 /* There are no more special cases, so perform a general compare */
5441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5446 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5448 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5450 //rFalseIfx.condition ^= 1;
5451 genSkipc(&rFalseIfx);
5453 pic16_emitpLabel(truelbl->key);
5455 if(ifx) ifx->generated = 1;
5462 /* sign is out of the way. So now do an unsigned compare */
5463 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5466 /* General case - compare to an unsigned literal on the right.*/
5468 i = (lit >> (size*8)) & 0xff;
5469 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5472 i = (lit >> (size*8)) & 0xff;
5475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5479 /* this byte of the lit is zero,
5480 *if it's not the last then OR in the variable */
5482 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487 pic16_emitpLabel(lbl->key);
5488 // pic16_emitpLabel(truelbl->key);
5489 //if(emitFinalCheck)
5490 genSkipc(&rFalseIfx);
5492 pic16_emitpLabel(truelbl->key);
5494 if(ifx) ifx->generated = 1;
5501 if(AOP_TYPE(left) == AOP_LIT) {
5502 //symbol *lbl = newiTempLabel(NULL);
5504 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5507 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5510 if((lit == 0) && (sign == 0)){
5513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5515 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5517 genSkipz2(&rFalseIfx,0);
5518 if(ifx) ifx->generated = 1;
5525 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5526 /* degenerate compare can never be true */
5527 if(rFalseIfx.condition == 0)
5528 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5530 if(ifx) ifx->generated = 1;
5535 /* signed comparisons to a literal byte */
5537 int lp1 = (lit+1) & 0xff;
5539 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5542 rFalseIfx.condition ^= 1;
5543 genSkipCond(&rFalseIfx,right,0,7);
5546 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5548 genSkipz2(&rFalseIfx,1);
5551 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5553 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5554 rFalseIfx.condition ^= 1;
5555 genSkipc(&rFalseIfx);
5559 /* unsigned comparisons to a literal byte */
5561 switch(lit & 0xff ) {
5563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564 genSkipz2(&rFalseIfx,0);
5567 rFalseIfx.condition ^= 1;
5568 genSkipCond(&rFalseIfx,right,0,7);
5572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5573 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5575 rFalseIfx.condition ^= 1;
5576 if (AOP_TYPE(result) == AOP_CRY)
5577 genSkipc(&rFalseIfx);
5579 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5580 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5586 if(ifx) ifx->generated = 1;
5587 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5593 /* Size is greater than 1 */
5601 /* this means lit = 0xffffffff, or -1 */
5604 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5605 rFalseIfx.condition ^= 1;
5606 genSkipCond(&rFalseIfx,right,size,7);
5607 if(ifx) ifx->generated = 1;
5609 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5618 if(rFalseIfx.condition) {
5619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5623 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5625 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5629 if(rFalseIfx.condition) {
5630 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5631 pic16_emitpLabel(truelbl->key);
5633 rFalseIfx.condition ^= 1;
5634 genSkipCond(&rFalseIfx,right,s,7);
5637 if(ifx) ifx->generated = 1;
5639 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5645 if((size == 1) && (0 == (lp1&0xff))) {
5646 /* lower byte of signed word is zero */
5647 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5648 i = ((lp1 >> 8) & 0xff) ^0x80;
5649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5651 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5653 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5655 if(ifx) ifx->generated = 1;
5658 rFalseIfx.condition ^= 1;
5659 genSkipc(&rFalseIfx);
5660 if(ifx) ifx->generated = 1;
5666 if(lit & (0x80 << (size*8))) {
5667 /* Lit is less than zero */
5668 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5669 //rFalseIfx.condition ^= 1;
5670 //genSkipCond(&rFalseIfx,left,size,7);
5671 //rFalseIfx.condition ^= 1;
5672 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5673 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5675 if(rFalseIfx.condition)
5676 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5678 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5682 /* Lit is greater than or equal to zero */
5683 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5684 //rFalseIfx.condition ^= 1;
5685 //genSkipCond(&rFalseIfx,right,size,7);
5686 //rFalseIfx.condition ^= 1;
5688 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5689 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5692 if(rFalseIfx.condition)
5693 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5706 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 rFalseIfx.condition ^= 1;
5709 //rFalseIfx.condition = 1;
5710 genSkipc(&rFalseIfx);
5712 pic16_emitpLabel(truelbl->key);
5714 if(ifx) ifx->generated = 1;
5717 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5724 /* compare word or long to an unsigned literal on the right.*/
5729 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5732 break; /* handled above */
5735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5737 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738 genSkipz2(&rFalseIfx,0);
5742 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5744 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5747 if(rFalseIfx.condition)
5748 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5750 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5753 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5754 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5756 rFalseIfx.condition ^= 1;
5757 genSkipc(&rFalseIfx);
5760 pic16_emitpLabel(truelbl->key);
5762 if(ifx) ifx->generated = 1;
5764 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5772 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5773 i = (lit >> (size*8)) & 0xff;
5775 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5779 i = (lit >> (size*8)) & 0xff;
5782 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5784 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5786 /* this byte of the lit is zero,
5787 * if it's not the last then OR in the variable */
5789 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794 pic16_emitpLabel(lbl->key);
5796 rFalseIfx.condition ^= 1;
5798 genSkipc(&rFalseIfx);
5802 pic16_emitpLabel(truelbl->key);
5803 if(ifx) ifx->generated = 1;
5805 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5811 /* Compare two variables */
5813 DEBUGpic16_emitcode(";sign","%d",sign);
5817 /* Sigh. thus sucks... */
5821 pctemp = pic16_popGetTempReg(1);
5822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5823 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5825 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5827 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_popReleaseTempReg(pctemp, 1);
5830 /* Signed char comparison */
5831 /* Special thanks to Nikolai Golovchenko for this snippet */
5832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5833 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5834 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5835 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5836 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5837 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5839 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5840 genSkipc(&rFalseIfx);
5842 if(ifx) ifx->generated = 1;
5844 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5852 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5857 /* The rest of the bytes of a multi-byte compare */
5861 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5864 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5865 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870 pic16_emitpLabel(lbl->key);
5872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5873 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5874 (AOP_TYPE(result) == AOP_REG)) {
5875 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5876 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5878 genSkipc(&rFalseIfx);
5880 //genSkipc(&rFalseIfx);
5881 if(ifx) ifx->generated = 1;
5884 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5892 if ((AOP_TYPE(result) != AOP_CRY)
5893 && AOP_SIZE(result)) {
5894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5896 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5898 pic16_outBitC(result);
5900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5901 /* if the result is used in the next
5902 ifx conditional branch then generate
5903 code a little differently */
5905 genIfxJump (ifx,"c");
5907 pic16_outBitC(result);
5908 /* leave the result in acc */
5913 #elif 0 /* VR version of genCmp() */ /* } else { */
5915 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5916 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5917 operand *result, int offset, int invert_op)
5921 /* check condition, > or < ?? */
5922 if(rIfx->condition != 0)invert_op ^= 1;
5924 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5926 if(!ifx)invert_op ^= 1;
5928 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5929 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5932 if(!invert_op)return POC_CPFSGT;
5933 else return POC_CPFSLT;
5936 static int compareAopfirstpass=1;
5938 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5939 operand *oper, int offset, operand *result,
5940 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5946 /* invert if there is a result to be loaded, in order to fit,
5947 * SETC/CLRC sequence */
5948 if(AOP_SIZE(result))invert_op ^= 1;
5950 // if(sign && !offset)invert_op ^= 1;
5952 // if(sign)invert_op ^= 1;
5954 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5956 if(AOP_SIZE(result) && compareAopfirstpass) {
5959 pic16_emitpcode(POC_SETF, pcop2);
5964 pic16_emitpcode(POC_CLRF, pcop2);
5970 compareAopfirstpass = 0;
5972 /* there is a bug when comparing operands with size > 1,
5973 * because higher bytes can be equal and test should be performed
5974 * to the next lower byte, current algorithm, considers operands
5975 * inequal in these cases! -- VR 20041107 */
5979 pic16_emitpcode(op, pcop);
5981 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5984 if((!sign || !offset) && AOP_SIZE(result)) {
5987 pic16_emitpcode(POC_CLRF, pcop2);
5992 pic16_emitpcode(POC_SETF, pcop2);
5997 /* don't emit final branch (offset == 0) */
6001 pic16_emitpcode(POC_RRCF, pcop2);
6003 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6006 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6007 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6008 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6010 truelbl = newiTempLabel( NULL );
6011 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6012 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6013 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6015 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016 pic16_emitpLabel(truelbl->key);
6018 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023 static void genCmp (operand *left, operand *right,
6024 operand *result, iCode *ifx, int sign)
6028 resolvedIfx rFalseIfx;
6029 symbol *falselbl, *tlbl;
6033 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6035 resolveIfx(&rFalseIfx, ifx);
6036 size = max(AOP_SIZE(left), AOP_SIZE(right));
6038 /* if left & right are bit variables */
6039 if(AOP_TYPE(left) == AOP_CRY
6040 && AOP_TYPE(right) == AOP_CRY ) {
6042 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6043 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6045 werror(W_POSSBUG2, __FILE__, __LINE__);
6049 /* if literal is on the right then swap with left */
6050 if((AOP_TYPE(right) == AOP_LIT)) {
6051 operand *tmp = right ;
6052 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6054 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6056 // lit = (lit - 1) & mask;
6059 rFalseIfx.condition ^= 1; /* reverse compare */
6061 if ((AOP_TYPE(left) == AOP_LIT)) {
6062 /* float compares are handled by support functions */
6063 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6066 /* actual comparing algorithm */
6067 // size = AOP_SIZE( right );
6069 falselbl = newiTempLabel( NULL );
6070 if(AOP_TYPE(left) == AOP_LIT) {
6071 /* compare to literal */
6072 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6075 pCodeOp *pct, *pct2;
6078 /* signed compare */
6079 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6081 /* using PRODL:PRODH as a temporary register here */
6082 pct = pic16_popCopyReg(&pic16_pc_prodl);
6083 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6084 tlbl = newiTempLabel( NULL );
6086 /* first compare signs:
6087 * a. if both are positive, compare just like unsigned
6088 * b. if both are negative, invert cmpop, compare just like unsigned
6089 * c. if different signs, determine the result directly */
6095 tlbl1 = newiTempLabel( NULL );
6096 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6100 /* literal is zero or positive:
6101 * a. if carry is zero, too, continue compare,
6102 * b. if carry is set, then continue depending on cmpop ^ condition:
6103 * 1. '<' return false (literal < variable),
6104 * 2. '>' return true (literal > variable) */
6105 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6106 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6109 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6110 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6114 /* literal is negative:
6115 * a. if carry is set, too, continue compare,
6116 * b. if carry is zero, then continue depending on cmpop ^ condition:
6117 * 1. '<' return true (literal < variable),
6118 * 2. '>' return false (literal > variable) */
6119 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6120 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6122 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6123 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6128 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6130 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6131 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6136 pic16_emitpLabel( tlbl1->key );
6139 compareAopfirstpass=1;
6140 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6141 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6142 // pic16_emitpcode(POC_MOVWF, pct);
6144 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6145 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6146 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6147 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6151 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6152 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6153 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6154 // pic16_emitpcode(POC_MOVWF, pct);
6156 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6157 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6158 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6159 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6160 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6163 if(ifx)ifx->generated = 1;
6165 if(AOP_SIZE(result)) {
6166 pic16_emitpLabel(tlbl->key);
6167 pic16_emitpLabel(falselbl->key);
6168 pic16_outBitOp( result, pct2 );
6170 pic16_emitpLabel(tlbl->key);
6174 /* unsigned compare */
6175 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6177 compareAopfirstpass=1;
6180 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6181 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6184 if(ifx)ifx->generated = 1;
6186 if(AOP_SIZE(result)) {
6187 pic16_emitpLabel(falselbl->key);
6188 pic16_outBitC( result );
6193 /* compare registers */
6194 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6198 pCodeOp *pct, *pct2;
6200 /* signed compare */
6201 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6203 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6204 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6205 tlbl = newiTempLabel( NULL );
6207 compareAopfirstpass=1;
6210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6211 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6213 pic16_emitpcode(POC_MOVWF, pct);
6215 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6216 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6217 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219 /* WREG already holds left + 0x80 */
6220 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6223 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6224 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6225 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6226 pic16_emitpcode(POC_MOVWF, pct);
6228 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6229 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6230 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6232 /* WREG already holds left + 0x80 */
6233 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6234 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6237 if(ifx)ifx->generated = 1;
6239 if(AOP_SIZE(result)) {
6240 pic16_emitpLabel(tlbl->key);
6241 pic16_emitpLabel(falselbl->key);
6242 pic16_outBitOp( result, pct2 );
6244 pic16_emitpLabel(tlbl->key);
6248 /* unsigned compare */
6249 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6251 compareAopfirstpass=1;
6254 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6255 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6259 if(ifx)ifx->generated = 1;
6260 if(AOP_SIZE(result)) {
6262 pic16_emitpLabel(falselbl->key);
6263 pic16_outBitC( result );
6274 /*-----------------------------------------------------------------*/
6275 /* genCmpGt :- greater than comparison */
6276 /*-----------------------------------------------------------------*/
6277 static void genCmpGt (iCode *ic, iCode *ifx)
6279 operand *left, *right, *result;
6280 sym_link *letype , *retype;
6286 right= IC_RIGHT(ic);
6287 result = IC_RESULT(ic);
6289 letype = getSpec(operandType(left));
6290 retype =getSpec(operandType(right));
6291 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6292 /* assign the amsops */
6293 pic16_aopOp (left,ic,FALSE);
6294 pic16_aopOp (right,ic,FALSE);
6295 pic16_aopOp (result,ic,TRUE);
6297 genCmp(right, left, result, ifx, sign);
6299 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6301 pic16_freeAsmop(result,NULL,ic,TRUE);
6304 /*-----------------------------------------------------------------*/
6305 /* genCmpLt - less than comparisons */
6306 /*-----------------------------------------------------------------*/
6307 static void genCmpLt (iCode *ic, iCode *ifx)
6309 operand *left, *right, *result;
6310 sym_link *letype , *retype;
6316 right= IC_RIGHT(ic);
6317 result = IC_RESULT(ic);
6319 letype = getSpec(operandType(left));
6320 retype =getSpec(operandType(right));
6321 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6323 /* assign the amsops */
6324 pic16_aopOp (left,ic,FALSE);
6325 pic16_aopOp (right,ic,FALSE);
6326 pic16_aopOp (result,ic,TRUE);
6328 genCmp(left, right, result, ifx, sign);
6330 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6332 pic16_freeAsmop(result,NULL,ic,TRUE);
6337 // FIXME reenable literal optimisation when the pic16 port is stable
6339 /*-----------------------------------------------------------------*/
6340 /* genc16bit2lit - compare a 16 bit value to a literal */
6341 /*-----------------------------------------------------------------*/
6342 static void genc16bit2lit(operand *op, int lit, int offset)
6346 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6347 if( (lit&0xff) == 0)
6352 switch( BYTEofLONG(lit,i)) {
6354 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6357 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6360 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6363 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6364 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6369 switch( BYTEofLONG(lit,i)) {
6371 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6375 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6379 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6382 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6384 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6393 /*-----------------------------------------------------------------*/
6394 /* gencjneshort - compare and jump if not equal */
6395 /*-----------------------------------------------------------------*/
6396 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6398 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6400 int res_offset = 0; /* the result may be a different size then left or right */
6401 int res_size = AOP_SIZE(result);
6403 symbol *lbl, *lbl_done;
6405 unsigned long lit = 0L;
6406 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6409 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6411 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6412 resolveIfx(&rIfx,ifx);
6413 lbl = newiTempLabel(NULL);
6414 lbl_done = newiTempLabel(NULL);
6417 /* if the left side is a literal or
6418 if the right is in a pointer register and left
6420 if ((AOP_TYPE(left) == AOP_LIT) ||
6421 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6426 if(AOP_TYPE(right) == AOP_LIT)
6427 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6429 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6430 preserve_result = 1;
6432 if(result && !preserve_result)
6435 for(i = 0; i < AOP_SIZE(result); i++)
6436 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6440 /* if the right side is a literal then anything goes */
6441 if (AOP_TYPE(right) == AOP_LIT &&
6442 AOP_TYPE(left) != AOP_DIR ) {
6445 genc16bit2lit(left, lit, 0);
6447 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6450 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6453 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6454 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6456 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6462 if(res_offset < res_size-1)
6470 /* if the right side is in a register or in direct space or
6471 if the left is a pointer register & right is not */
6472 else if (AOP_TYPE(right) == AOP_REG ||
6473 AOP_TYPE(right) == AOP_DIR ||
6474 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6475 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6476 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6477 int lbl_key = lbl->key;
6480 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6481 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6483 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6484 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6485 __FUNCTION__,__LINE__);
6489 /* switch(size) { */
6491 /* genc16bit2lit(left, lit, 0); */
6493 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6498 if((AOP_TYPE(left) == AOP_DIR) &&
6499 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6501 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6502 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6504 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6506 switch (lit & 0xff) {
6508 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6511 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6512 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6513 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6517 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6518 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6519 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6520 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6524 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6525 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6530 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6533 if(AOP_TYPE(result) == AOP_CRY) {
6534 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6539 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6541 /* fix me. probably need to check result size too */
6542 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6547 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6548 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6555 if(res_offset < res_size-1)
6560 } else if(AOP_TYPE(right) == AOP_REG &&
6561 AOP_TYPE(left) != AOP_DIR){
6564 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6565 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6566 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6571 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6573 if(res_offset < res_size-1)
6578 /* right is a pointer reg need both a & b */
6580 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6582 pic16_emitcode("mov","b,%s",l);
6583 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6584 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6589 if(result && preserve_result)
6592 for(i = 0; i < AOP_SIZE(result); i++)
6593 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6596 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6598 if(result && preserve_result)
6599 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6602 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6604 pic16_emitpLabel(lbl->key);
6606 if(result && preserve_result)
6609 for(i = 0; i < AOP_SIZE(result); i++)
6610 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6612 pic16_emitpLabel(lbl_done->key);
6615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6623 /*-----------------------------------------------------------------*/
6624 /* gencjne - compare and jump if not equal */
6625 /*-----------------------------------------------------------------*/
6626 static void gencjne(operand *left, operand *right, iCode *ifx)
6628 symbol *tlbl = newiTempLabel(NULL);
6630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6631 gencjneshort(left, right, lbl);
6633 pic16_emitcode("mov","a,%s",one);
6634 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6635 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6636 pic16_emitcode("clr","a");
6637 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6639 pic16_emitpLabel(lbl->key);
6640 pic16_emitpLabel(tlbl->key);
6646 /*-----------------------------------------------------------------*/
6647 /* is_LitOp - check if operand has to be treated as literal */
6648 /*-----------------------------------------------------------------*/
6649 static bool is_LitOp(operand *op)
6651 return ((AOP_TYPE(op) == AOP_LIT)
6652 || ( (AOP_TYPE(op) == AOP_PCODE)
6653 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6654 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6657 /*-----------------------------------------------------------------*/
6658 /* is_LitAOp - check if operand has to be treated as literal */
6659 /*-----------------------------------------------------------------*/
6660 static bool is_LitAOp(asmop *aop)
6662 return ((aop->type == AOP_LIT)
6663 || ( (aop->type == AOP_PCODE)
6664 && ( (aop->aopu.pcop->type == PO_LITERAL)
6665 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6670 /*-----------------------------------------------------------------*/
6671 /* genCmpEq - generates code for equal to */
6672 /*-----------------------------------------------------------------*/
6673 static void genCmpEq (iCode *ic, iCode *ifx)
6675 operand *left, *right, *result;
6676 symbol *falselbl = newiTempLabel(NULL);
6677 symbol *donelbl = newiTempLabel(NULL);
6679 int preserve_result = 0;
6680 int generate_result = 0;
6682 unsigned long lit = -1;
6686 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6687 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6688 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6690 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6692 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6694 werror(W_POSSBUG2, __FILE__, __LINE__);
6695 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6696 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6700 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6702 operand *tmp = right ;
6707 if (AOP_TYPE(right) == AOP_LIT) {
6708 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6711 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6712 preserve_result = 1;
6714 if(result && AOP_SIZE(result))
6715 generate_result = 1;
6717 if(generate_result && !preserve_result)
6719 for(i = 0; i < AOP_SIZE(result); i++)
6720 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6723 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6724 for(i=0; i < AOP_SIZE(left); i++)
6726 if(AOP_TYPE(left) != AOP_ACC)
6729 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6731 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6733 if(is_LitOp(right)) {
6734 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6735 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6738 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6740 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6745 if(generate_result && preserve_result)
6747 for(i = 0; i < AOP_SIZE(result); i++)
6748 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6752 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6754 if(generate_result && preserve_result)
6755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6757 if(ifx && IC_TRUE(ifx))
6758 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6760 if(ifx && IC_FALSE(ifx))
6761 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6763 pic16_emitpLabel(falselbl->key);
6767 if(ifx && IC_FALSE(ifx))
6768 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6770 if(generate_result && preserve_result)
6772 for(i = 0; i < AOP_SIZE(result); i++)
6773 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6776 pic16_emitpLabel(donelbl->key);
6782 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6783 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6784 pic16_freeAsmop(result,NULL,ic,TRUE);
6790 // old version kept for reference
6792 /*-----------------------------------------------------------------*/
6793 /* genCmpEq - generates code for equal to */
6794 /*-----------------------------------------------------------------*/
6795 static void genCmpEq (iCode *ic, iCode *ifx)
6797 operand *left, *right, *result;
6798 unsigned long lit = 0L;
6800 symbol *falselbl = newiTempLabel(NULL);
6803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6806 DEBUGpic16_emitcode ("; ifx is non-null","");
6808 DEBUGpic16_emitcode ("; ifx is null","");
6810 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6811 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6812 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6814 size = max(AOP_SIZE(left),AOP_SIZE(right));
6816 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6818 /* if literal, literal on the right or
6819 if the right is in a pointer register and left
6821 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6822 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6823 operand *tmp = right ;
6829 if(ifx && !AOP_SIZE(result)){
6831 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6832 /* if they are both bit variables */
6833 if (AOP_TYPE(left) == AOP_CRY &&
6834 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6835 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6836 if(AOP_TYPE(right) == AOP_LIT){
6837 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6839 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840 pic16_emitcode("cpl","c");
6841 } else if(lit == 1L) {
6842 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844 pic16_emitcode("clr","c");
6846 /* AOP_TYPE(right) == AOP_CRY */
6848 symbol *lbl = newiTempLabel(NULL);
6849 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6850 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6851 pic16_emitcode("cpl","c");
6852 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6854 /* if true label then we jump if condition
6856 tlbl = newiTempLabel(NULL);
6857 if ( IC_TRUE(ifx) ) {
6858 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6859 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6861 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6862 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6864 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6867 /* left and right are both bit variables, result is carry */
6870 resolveIfx(&rIfx,ifx);
6872 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6873 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6874 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6875 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6880 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6882 /* They're not both bit variables. Is the right a literal? */
6883 if(AOP_TYPE(right) == AOP_LIT) {
6884 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6889 switch(lit & 0xff) {
6891 if ( IC_TRUE(ifx) ) {
6892 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6896 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6897 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6901 if ( IC_TRUE(ifx) ) {
6902 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6904 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6906 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6907 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6911 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6913 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6918 /* end of size == 1 */
6922 genc16bit2lit(left,lit,offset);
6925 /* end of size == 2 */
6930 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6931 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6932 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6933 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6936 /* search for patterns that can be optimized */
6938 genc16bit2lit(left,lit,0);
6942 emitSKPZ; // if hi word unequal
6944 emitSKPNZ; // if hi word equal
6946 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6947 genc16bit2lit(left,lit,2);
6950 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6951 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6955 pic16_emitpLabel(falselbl->key);
6964 } else if(AOP_TYPE(right) == AOP_CRY ) {
6965 /* we know the left is not a bit, but that the right is */
6966 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6967 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6968 pic16_popGet(AOP(right),offset));
6969 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6971 /* if the two are equal, then W will be 0 and the Z bit is set
6972 * we could test Z now, or go ahead and check the high order bytes if
6973 * the variable we're comparing is larger than a byte. */
6976 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6978 if ( IC_TRUE(ifx) ) {
6980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6981 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6984 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6985 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6989 /* They're both variables that are larger than bits */
6992 tlbl = newiTempLabel(NULL);
6995 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6996 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6998 if ( IC_TRUE(ifx) ) {
7002 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7005 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7009 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7013 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7018 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7020 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7021 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7025 if(s>1 && IC_TRUE(ifx)) {
7026 pic16_emitpLabel(tlbl->key);
7027 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7031 /* mark the icode as generated */
7036 /* if they are both bit variables */
7037 if (AOP_TYPE(left) == AOP_CRY &&
7038 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7039 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7040 if(AOP_TYPE(right) == AOP_LIT){
7041 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7043 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044 pic16_emitcode("cpl","c");
7045 } else if(lit == 1L) {
7046 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048 pic16_emitcode("clr","c");
7050 /* AOP_TYPE(right) == AOP_CRY */
7052 symbol *lbl = newiTempLabel(NULL);
7053 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7054 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7055 pic16_emitcode("cpl","c");
7056 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7059 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7060 pic16_outBitC(result);
7064 genIfxJump (ifx,"c");
7067 /* if the result is used in an arithmetic operation
7068 then put the result in place */
7069 pic16_outBitC(result);
7072 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7073 gencjne(left,right,result,ifx);
7076 gencjne(left,right,newiTempLabel(NULL));
7078 if(IC_TRUE(ifx)->key)
7079 gencjne(left,right,IC_TRUE(ifx)->key);
7081 gencjne(left,right,IC_FALSE(ifx)->key);
7085 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7086 pic16_aopPut(AOP(result),"a",0);
7091 genIfxJump (ifx,"a");
7095 /* if the result is used in an arithmetic operation
7096 then put the result in place */
7098 if (AOP_TYPE(result) != AOP_CRY)
7099 pic16_outAcc(result);
7101 /* leave the result in acc */
7105 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7106 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7107 pic16_freeAsmop(result,NULL,ic,TRUE);
7111 /*-----------------------------------------------------------------*/
7112 /* ifxForOp - returns the icode containing the ifx for operand */
7113 /*-----------------------------------------------------------------*/
7114 static iCode *ifxForOp ( operand *op, iCode *ic )
7118 /* if true symbol then needs to be assigned */
7119 if (IS_TRUE_SYMOP(op))
7122 /* if this has register type condition and
7123 the next instruction is ifx with the same operand
7124 and live to of the operand is upto the ifx only then */
7126 && ic->next->op == IFX
7127 && IC_COND(ic->next)->key == op->key
7128 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7130 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7136 ic->next->op == IFX &&
7137 IC_COND(ic->next)->key == op->key) {
7138 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7143 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7145 ic->next->op == IFX)
7146 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7149 ic->next->op == IFX &&
7150 IC_COND(ic->next)->key == op->key) {
7151 DEBUGpic16_emitcode ("; "," key is okay");
7152 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7153 OP_SYMBOL(op)->liveTo,
7158 /* the code below is completely untested
7159 * it just allows ulong2fs.c compile -- VR */
7162 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7163 __FILE__, __FUNCTION__, __LINE__);
7165 /* if this has register type condition and
7166 the next instruction is ifx with the same operand
7167 and live to of the operand is upto the ifx only then */
7169 ic->next->op == IFX &&
7170 IC_COND(ic->next)->key == op->key &&
7171 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7175 ic->next->op == IFX &&
7176 IC_COND(ic->next)->key == op->key) {
7177 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7181 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7182 __FILE__, __FUNCTION__, __LINE__);
7184 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7189 /*-----------------------------------------------------------------*/
7190 /* genAndOp - for && operation */
7191 /*-----------------------------------------------------------------*/
7192 static void genAndOp (iCode *ic)
7194 operand *left,*right, *result;
7199 /* note here that && operations that are in an
7200 if statement are taken away by backPatchLabels
7201 only those used in arthmetic operations remain */
7202 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7203 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7204 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7206 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7209 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7210 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7212 /* if both are bit variables */
7213 /* if (AOP_TYPE(left) == AOP_CRY && */
7214 /* AOP_TYPE(right) == AOP_CRY ) { */
7215 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7216 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7217 /* pic16_outBitC(result); */
7219 /* tlbl = newiTempLabel(NULL); */
7220 /* pic16_toBoolean(left); */
7221 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7222 /* pic16_toBoolean(right); */
7223 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7224 /* pic16_outBitAcc(result); */
7227 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7228 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7229 pic16_freeAsmop(result,NULL,ic,TRUE);
7233 /*-----------------------------------------------------------------*/
7234 /* genOrOp - for || operation */
7235 /*-----------------------------------------------------------------*/
7238 modified this code, but it doesn't appear to ever get called
7241 static void genOrOp (iCode *ic)
7243 operand *left,*right, *result;
7248 /* note here that || operations that are in an
7249 if statement are taken away by backPatchLabels
7250 only those used in arthmetic operations remain */
7251 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7252 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7253 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7255 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7257 /* if both are bit variables */
7258 if (AOP_TYPE(left) == AOP_CRY &&
7259 AOP_TYPE(right) == AOP_CRY ) {
7260 pic16_emitcode("clrc","");
7261 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7262 AOP(left)->aopu.aop_dir,
7263 AOP(left)->aopu.aop_dir);
7264 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7265 AOP(right)->aopu.aop_dir,
7266 AOP(right)->aopu.aop_dir);
7267 pic16_emitcode("setc","");
7270 tlbl = newiTempLabel(NULL);
7271 pic16_toBoolean(left);
7273 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7274 pic16_toBoolean(right);
7275 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7277 pic16_outBitAcc(result);
7280 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7281 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7282 pic16_freeAsmop(result,NULL,ic,TRUE);
7285 /*-----------------------------------------------------------------*/
7286 /* isLiteralBit - test if lit == 2^n */
7287 /*-----------------------------------------------------------------*/
7288 static int isLiteralBit(unsigned long lit)
7290 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7291 0x100L,0x200L,0x400L,0x800L,
7292 0x1000L,0x2000L,0x4000L,0x8000L,
7293 0x10000L,0x20000L,0x40000L,0x80000L,
7294 0x100000L,0x200000L,0x400000L,0x800000L,
7295 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7296 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7300 for(idx = 0; idx < 32; idx++)
7306 /*-----------------------------------------------------------------*/
7307 /* continueIfTrue - */
7308 /*-----------------------------------------------------------------*/
7309 static void continueIfTrue (iCode *ic)
7313 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7317 /*-----------------------------------------------------------------*/
7319 /*-----------------------------------------------------------------*/
7320 static void jumpIfTrue (iCode *ic)
7324 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7328 /*-----------------------------------------------------------------*/
7329 /* jmpTrueOrFalse - */
7330 /*-----------------------------------------------------------------*/
7331 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7333 // ugly but optimized by peephole
7336 symbol *nlbl = newiTempLabel(NULL);
7337 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7338 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7339 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7340 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7342 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7343 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7348 /*-----------------------------------------------------------------*/
7349 /* genAnd - code for and */
7350 /*-----------------------------------------------------------------*/
7351 static void genAnd (iCode *ic, iCode *ifx)
7353 operand *left, *right, *result;
7355 unsigned long lit = 0L;
7361 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7362 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7363 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7365 resolveIfx(&rIfx,ifx);
7367 /* if left is a literal & right is not then exchange them */
7368 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7369 AOP_NEEDSACC(left)) {
7370 operand *tmp = right ;
7375 /* if result = right then exchange them */
7376 if(pic16_sameRegs(AOP(result),AOP(right))){
7377 operand *tmp = right ;
7382 /* if right is bit then exchange them */
7383 if (AOP_TYPE(right) == AOP_CRY &&
7384 AOP_TYPE(left) != AOP_CRY){
7385 operand *tmp = right ;
7389 if(AOP_TYPE(right) == AOP_LIT)
7390 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7392 size = AOP_SIZE(result);
7394 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7397 // result = bit & yy;
7398 if (AOP_TYPE(left) == AOP_CRY){
7399 // c = bit & literal;
7400 if(AOP_TYPE(right) == AOP_LIT){
7402 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7405 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7408 if(size && (AOP_TYPE(result) == AOP_CRY)){
7409 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7412 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7416 pic16_emitcode("clr","c");
7419 if (AOP_TYPE(right) == AOP_CRY){
7421 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7422 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7425 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7427 pic16_emitcode("rrc","a");
7428 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7434 pic16_outBitC(result);
7436 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7437 genIfxJump(ifx, "c");
7441 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7442 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7443 if((AOP_TYPE(right) == AOP_LIT) &&
7444 (AOP_TYPE(result) == AOP_CRY) &&
7445 (AOP_TYPE(left) != AOP_CRY)){
7446 int posbit = isLiteralBit(lit);
7450 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7453 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7459 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7462 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7466 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7467 size = AOP_SIZE(left);
7470 int bp = posbit, ofs=0;
7477 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7478 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7482 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7483 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7485 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7492 symbol *tlbl = newiTempLabel(NULL);
7493 int sizel = AOP_SIZE(left);
7499 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7501 /* patch provided by Aaron Colwell */
7502 if((posbit = isLiteralBit(bytelit)) != 0) {
7503 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7504 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7505 (posbit-1),0, PO_GPR_REGISTER));
7507 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7508 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7510 if (bytelit == 0xff) {
7511 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7512 * a peephole could optimize it out -- VR */
7513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7516 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7519 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7520 pic16_popGetLabel(tlbl->key));
7524 /* old code, left here for reference -- VR 09/2004 */
7525 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7527 if((posbit = isLiteralBit(bytelit)) != 0)
7528 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7530 if(bytelit != 0x0FFL)
7531 pic16_emitcode("anl","a,%s",
7532 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7533 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7539 // bit = left & literal
7542 pic16_emitpLabel(tlbl->key);
7544 // if(left & literal)
7547 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7550 pic16_emitpLabel(tlbl->key);
7555 pic16_outBitC(result);
7559 /* if left is same as result */
7560 if(pic16_sameRegs(AOP(result),AOP(left))){
7562 for(;size--; offset++,lit>>=8) {
7563 if(AOP_TYPE(right) == AOP_LIT){
7564 switch(lit & 0xff) {
7566 /* and'ing with 0 has clears the result */
7567 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7568 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7571 /* and'ing with 0xff is a nop when the result and left are the same */
7576 int p = pic16_my_powof2( (~lit) & 0xff );
7578 /* only one bit is set in the literal, so use a bcf instruction */
7579 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7580 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7583 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7584 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7585 if(know_W != (lit&0xff))
7586 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7588 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7593 if (AOP_TYPE(left) == AOP_ACC) {
7594 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7596 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7597 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7604 // left & result in different registers
7605 if(AOP_TYPE(result) == AOP_CRY){
7607 // if(size), result in bit
7608 // if(!size && ifx), conditional oper: if(left & right)
7609 symbol *tlbl = newiTempLabel(NULL);
7610 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7612 pic16_emitcode("setb","c");
7614 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7615 pic16_emitcode("anl","a,%s",
7616 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7617 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7622 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7623 pic16_outBitC(result);
7625 jmpTrueOrFalse(ifx, tlbl);
7627 for(;(size--);offset++) {
7629 // result = left & right
7630 if(AOP_TYPE(right) == AOP_LIT){
7631 int t = (lit >> (offset*8)) & 0x0FFL;
7634 pic16_emitcode("clrf","%s",
7635 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7636 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7639 pic16_emitcode("movf","%s,w",
7640 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7641 pic16_emitcode("movwf","%s",
7642 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7643 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7644 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7647 pic16_emitcode("movlw","0x%x",t);
7648 pic16_emitcode("andwf","%s,w",
7649 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7650 pic16_emitcode("movwf","%s",
7651 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7653 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7654 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7655 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7660 if (AOP_TYPE(left) == AOP_ACC) {
7661 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7662 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7664 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7665 pic16_emitcode("andwf","%s,w",
7666 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7667 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7668 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7670 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7671 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7677 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7678 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679 pic16_freeAsmop(result,NULL,ic,TRUE);
7682 /*-----------------------------------------------------------------*/
7683 /* genOr - code for or */
7684 /*-----------------------------------------------------------------*/
7685 static void genOr (iCode *ic, iCode *ifx)
7687 operand *left, *right, *result;
7689 unsigned long lit = 0L;
7691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7693 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7694 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7695 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7697 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7699 /* if left is a literal & right is not then exchange them */
7700 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7701 AOP_NEEDSACC(left)) {
7702 operand *tmp = right ;
7707 /* if result = right then exchange them */
7708 if(pic16_sameRegs(AOP(result),AOP(right))){
7709 operand *tmp = right ;
7714 /* if right is bit then exchange them */
7715 if (AOP_TYPE(right) == AOP_CRY &&
7716 AOP_TYPE(left) != AOP_CRY){
7717 operand *tmp = right ;
7722 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7724 if(AOP_TYPE(right) == AOP_LIT)
7725 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7727 size = AOP_SIZE(result);
7731 if (AOP_TYPE(left) == AOP_CRY){
7732 if(AOP_TYPE(right) == AOP_LIT){
7733 // c = bit & literal;
7735 // lit != 0 => result = 1
7736 if(AOP_TYPE(result) == AOP_CRY){
7738 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7739 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7740 // AOP(result)->aopu.aop_dir,
7741 // AOP(result)->aopu.aop_dir);
7743 continueIfTrue(ifx);
7747 // lit == 0 => result = left
7748 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7750 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7753 if (AOP_TYPE(right) == AOP_CRY){
7754 if(pic16_sameRegs(AOP(result),AOP(left))){
7756 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7757 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7758 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7760 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7761 AOP(result)->aopu.aop_dir,
7762 AOP(result)->aopu.aop_dir);
7763 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7764 AOP(right)->aopu.aop_dir,
7765 AOP(right)->aopu.aop_dir);
7766 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7767 AOP(result)->aopu.aop_dir,
7768 AOP(result)->aopu.aop_dir);
7770 if( AOP_TYPE(result) == AOP_ACC) {
7771 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7772 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7773 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7774 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7778 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7779 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7780 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7781 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7783 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7784 AOP(result)->aopu.aop_dir,
7785 AOP(result)->aopu.aop_dir);
7786 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7787 AOP(right)->aopu.aop_dir,
7788 AOP(right)->aopu.aop_dir);
7789 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7790 AOP(left)->aopu.aop_dir,
7791 AOP(left)->aopu.aop_dir);
7792 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7793 AOP(result)->aopu.aop_dir,
7794 AOP(result)->aopu.aop_dir);
7799 symbol *tlbl = newiTempLabel(NULL);
7800 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7803 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7804 if( AOP_TYPE(right) == AOP_ACC) {
7805 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7807 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7808 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7813 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7814 pic16_emitcode(";XXX setb","c");
7815 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7816 AOP(left)->aopu.aop_dir,tlbl->key+100);
7817 pic16_toBoolean(right);
7818 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7819 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7820 jmpTrueOrFalse(ifx, tlbl);
7824 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7831 pic16_outBitC(result);
7833 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7834 genIfxJump(ifx, "c");
7838 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7839 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7840 if((AOP_TYPE(right) == AOP_LIT) &&
7841 (AOP_TYPE(result) == AOP_CRY) &&
7842 (AOP_TYPE(left) != AOP_CRY)){
7844 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7849 continueIfTrue(ifx);
7852 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7853 // lit = 0, result = boolean(left)
7855 pic16_emitcode(";XXX setb","c");
7856 pic16_toBoolean(right);
7858 symbol *tlbl = newiTempLabel(NULL);
7859 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7861 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7863 genIfxJump (ifx,"a");
7867 pic16_outBitC(result);
7871 /* if left is same as result */
7872 if(pic16_sameRegs(AOP(result),AOP(left))){
7874 for(;size--; offset++,lit>>=8) {
7875 if(AOP_TYPE(right) == AOP_LIT){
7876 if((lit & 0xff) == 0)
7877 /* or'ing with 0 has no effect */
7880 int p = pic16_my_powof2(lit & 0xff);
7882 /* only one bit is set in the literal, so use a bsf instruction */
7883 pic16_emitpcode(POC_BSF,
7884 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7886 if(know_W != (lit & 0xff))
7887 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7888 know_W = lit & 0xff;
7889 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7894 if (AOP_TYPE(left) == AOP_ACC) {
7895 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7896 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7899 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7901 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7908 // left & result in different registers
7909 if(AOP_TYPE(result) == AOP_CRY){
7911 // if(size), result in bit
7912 // if(!size && ifx), conditional oper: if(left | right)
7913 symbol *tlbl = newiTempLabel(NULL);
7914 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7915 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7919 pic16_emitcode(";XXX setb","c");
7921 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7922 pic16_emitcode(";XXX orl","a,%s",
7923 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7929 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7930 pic16_outBitC(result);
7932 jmpTrueOrFalse(ifx, tlbl);
7933 } else for(;(size--);offset++){
7935 // result = left & right
7936 if(AOP_TYPE(right) == AOP_LIT){
7937 int t = (lit >> (offset*8)) & 0x0FFL;
7940 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7943 // pic16_emitcode("movf","%s,w",
7944 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7945 // pic16_emitcode("movwf","%s",
7946 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7950 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7953 // pic16_emitcode("movlw","0x%x",t);
7954 // pic16_emitcode("iorwf","%s,w",
7955 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7956 // pic16_emitcode("movwf","%s",
7957 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7963 // faster than result <- left, anl result,right
7964 // and better if result is SFR
7965 if (AOP_TYPE(left) == AOP_ACC) {
7966 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7967 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7969 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7970 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7972 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7973 // pic16_emitcode("iorwf","%s,w",
7974 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7977 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7982 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7983 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7984 pic16_freeAsmop(result,NULL,ic,TRUE);
7987 /*-----------------------------------------------------------------*/
7988 /* genXor - code for xclusive or */
7989 /*-----------------------------------------------------------------*/
7990 static void genXor (iCode *ic, iCode *ifx)
7992 operand *left, *right, *result;
7994 unsigned long lit = 0L;
7996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7998 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7999 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8000 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8002 /* if left is a literal & right is not ||
8003 if left needs acc & right does not */
8004 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8005 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8006 operand *tmp = right ;
8011 /* if result = right then exchange them */
8012 if(pic16_sameRegs(AOP(result),AOP(right))){
8013 operand *tmp = right ;
8018 /* if right is bit then exchange them */
8019 if (AOP_TYPE(right) == AOP_CRY &&
8020 AOP_TYPE(left) != AOP_CRY){
8021 operand *tmp = right ;
8025 if(AOP_TYPE(right) == AOP_LIT)
8026 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8028 size = AOP_SIZE(result);
8032 if (AOP_TYPE(left) == AOP_CRY){
8033 if(AOP_TYPE(right) == AOP_LIT){
8034 // c = bit & literal;
8036 // lit>>1 != 0 => result = 1
8037 if(AOP_TYPE(result) == AOP_CRY){
8039 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8040 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8042 continueIfTrue(ifx);
8045 pic16_emitcode("setb","c");
8049 // lit == 0, result = left
8050 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8052 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8054 // lit == 1, result = not(left)
8055 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8056 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8057 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8058 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8061 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8062 pic16_emitcode("cpl","c");
8069 symbol *tlbl = newiTempLabel(NULL);
8070 if (AOP_TYPE(right) == AOP_CRY){
8072 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8075 int sizer = AOP_SIZE(right);
8077 // if val>>1 != 0, result = 1
8078 pic16_emitcode("setb","c");
8080 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8082 // test the msb of the lsb
8083 pic16_emitcode("anl","a,#0xfe");
8084 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8088 pic16_emitcode("rrc","a");
8090 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8091 pic16_emitcode("cpl","c");
8092 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8097 pic16_outBitC(result);
8099 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8100 genIfxJump(ifx, "c");
8104 if(pic16_sameRegs(AOP(result),AOP(left))){
8105 /* if left is same as result */
8106 for(;size--; offset++) {
8107 if(AOP_TYPE(right) == AOP_LIT){
8108 int t = (lit >> (offset*8)) & 0x0FFL;
8112 if (IS_AOP_PREG(left)) {
8113 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8115 pic16_aopPut(AOP(result),"a",offset);
8117 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8118 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8119 pic16_emitcode("xrl","%s,%s",
8120 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8121 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124 if (AOP_TYPE(left) == AOP_ACC)
8125 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8127 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8128 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8130 if (IS_AOP_PREG(left)) {
8131 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132 pic16_aopPut(AOP(result),"a",offset);
8134 pic16_emitcode("xrl","%s,a",
8135 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8141 // left & result in different registers
8142 if(AOP_TYPE(result) == AOP_CRY){
8144 // if(size), result in bit
8145 // if(!size && ifx), conditional oper: if(left ^ right)
8146 symbol *tlbl = newiTempLabel(NULL);
8147 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8149 pic16_emitcode("setb","c");
8151 if((AOP_TYPE(right) == AOP_LIT) &&
8152 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8153 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8156 pic16_emitcode("xrl","a,%s",
8157 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8164 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8165 pic16_outBitC(result);
8167 jmpTrueOrFalse(ifx, tlbl);
8168 } else for(;(size--);offset++){
8170 // result = left & right
8171 if(AOP_TYPE(right) == AOP_LIT){
8172 int t = (lit >> (offset*8)) & 0x0FFL;
8175 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177 pic16_emitcode("movf","%s,w",
8178 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179 pic16_emitcode("movwf","%s",
8180 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8184 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8185 pic16_emitcode("comf","%s,w",
8186 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8187 pic16_emitcode("movwf","%s",
8188 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8192 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8193 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8194 pic16_emitcode("movlw","0x%x",t);
8195 pic16_emitcode("xorwf","%s,w",
8196 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8197 pic16_emitcode("movwf","%s",
8198 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8204 // faster than result <- left, anl result,right
8205 // and better if result is SFR
8206 if (AOP_TYPE(left) == AOP_ACC) {
8207 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8208 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8210 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8211 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8212 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8215 if ( AOP_TYPE(result) != AOP_ACC){
8216 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8217 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8223 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8224 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8225 pic16_freeAsmop(result,NULL,ic,TRUE);
8228 /*-----------------------------------------------------------------*/
8229 /* genInline - write the inline code out */
8230 /*-----------------------------------------------------------------*/
8231 static void genInline (iCode *ic)
8233 char *buffer, *bp, *bp1;
8235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8237 _G.inLine += (!options.asmpeep);
8239 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8240 strcpy(buffer,IC_INLINE(ic));
8242 while((bp1=strstr(bp, "\\n"))) {
8250 /* This is an experimental code for #pragma inline
8251 and is temporarily disabled for 2.5.0 release */
8259 cbuf = Safe_strdup(buffer);
8260 cblen = strlen(buffer)+1;
8261 memset(cbuf, 0, cblen);
8266 if(*bp != '%')*bp1++ = *bp++;
8272 if(i>elementsInSet(asmInlineMap))break;
8275 s = indexSet(asmInlineMap, i);
8276 DEBUGpc("searching symbol s = `%s'", s);
8277 sym = findSym(SymbolTab, NULL, s);
8280 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8282 strcat(bp1, sym->rname);
8288 if(strlen(bp1) > cblen - 16) {
8289 int i = strlen(cbuf);
8291 cbuf = realloc(cbuf, cblen);
8292 memset(cbuf+i, 0, 50);
8298 buffer = Safe_strdup( cbuf );
8305 /* emit each line as a code */
8311 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8319 /* print label, use this special format with NULL directive
8320 * to denote that the argument should not be indented with tab */
8321 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8324 /* advance to end of line (prevent splitting of comments at ':' */
8325 while (*bp && *bp != '\n') {
8333 if ((bp1 != bp) && *bp1)
8334 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8339 _G.inLine -= (!options.asmpeep);
8342 /*-----------------------------------------------------------------*/
8343 /* genRRC - rotate right with carry */
8344 /*-----------------------------------------------------------------*/
8345 static void genRRC (iCode *ic)
8347 operand *left , *result ;
8348 int size, offset = 0, same;
8350 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8352 /* rotate right with carry */
8354 result=IC_RESULT(ic);
8355 pic16_aopOp (left,ic,FALSE);
8356 pic16_aopOp (result,ic,TRUE);
8358 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8360 same = pic16_sameRegs(AOP(result),AOP(left));
8362 size = AOP_SIZE(result);
8364 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8366 /* get the lsb and put it into the carry */
8367 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8374 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8376 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8377 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8383 pic16_freeAsmop(left,NULL,ic,TRUE);
8384 pic16_freeAsmop(result,NULL,ic,TRUE);
8387 /*-----------------------------------------------------------------*/
8388 /* genRLC - generate code for rotate left with carry */
8389 /*-----------------------------------------------------------------*/
8390 static void genRLC (iCode *ic)
8392 operand *left , *result ;
8393 int size, offset = 0;
8396 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8397 /* rotate right with carry */
8399 result=IC_RESULT(ic);
8400 pic16_aopOp (left,ic,FALSE);
8401 pic16_aopOp (result,ic,TRUE);
8403 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8405 same = pic16_sameRegs(AOP(result),AOP(left));
8407 /* move it to the result */
8408 size = AOP_SIZE(result);
8410 /* get the msb and put it into the carry */
8411 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8418 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8420 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8421 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8428 pic16_freeAsmop(left,NULL,ic,TRUE);
8429 pic16_freeAsmop(result,NULL,ic,TRUE);
8433 /* gpasm can get the highest order bit with HIGH/UPPER
8434 * so the following probably is not needed -- VR */
8436 /*-----------------------------------------------------------------*/
8437 /* genGetHbit - generates code get highest order bit */
8438 /*-----------------------------------------------------------------*/
8439 static void genGetHbit (iCode *ic)
8441 operand *left, *result;
8443 result=IC_RESULT(ic);
8444 pic16_aopOp (left,ic,FALSE);
8445 pic16_aopOp (result,ic,FALSE);
8447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8448 /* get the highest order byte into a */
8449 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8450 if(AOP_TYPE(result) == AOP_CRY){
8451 pic16_emitcode("rlc","a");
8452 pic16_outBitC(result);
8455 pic16_emitcode("rl","a");
8456 pic16_emitcode("anl","a,#0x01");
8457 pic16_outAcc(result);
8461 pic16_freeAsmop(left,NULL,ic,TRUE);
8462 pic16_freeAsmop(result,NULL,ic,TRUE);
8466 /*-----------------------------------------------------------------*/
8467 /* AccRol - rotate left accumulator by known count */
8468 /*-----------------------------------------------------------------*/
8469 static void AccRol (int shCount)
8471 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8472 shCount &= 0x0007; // shCount : 0..7
8477 pic16_emitcode("rl","a");
8480 pic16_emitcode("rl","a");
8481 pic16_emitcode("rl","a");
8484 pic16_emitcode("swap","a");
8485 pic16_emitcode("rr","a");
8488 pic16_emitcode("swap","a");
8491 pic16_emitcode("swap","a");
8492 pic16_emitcode("rl","a");
8495 pic16_emitcode("rr","a");
8496 pic16_emitcode("rr","a");
8499 pic16_emitcode("rr","a");
8505 /*-----------------------------------------------------------------*/
8506 /* AccLsh - left shift accumulator by known count */
8507 /*-----------------------------------------------------------------*/
8508 static void AccLsh (int shCount, int doMask)
8510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8516 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8530 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8534 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8538 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8542 /* no masking is required in genPackBits */
8543 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8547 /*-----------------------------------------------------------------*/
8548 /* AccRsh - right shift accumulator by known count */
8549 /*-----------------------------------------------------------------*/
8550 static void AccRsh (int shCount, int andmask)
8552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8557 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8560 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8565 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8571 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8572 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8576 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8584 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8586 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8590 /*-----------------------------------------------------------------*/
8591 /* AccSRsh - signed right shift accumulator by known count */
8592 /*-----------------------------------------------------------------*/
8593 static void AccSRsh (int shCount)
8596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8599 pic16_emitcode("mov","c,acc.7");
8600 pic16_emitcode("rrc","a");
8601 } else if(shCount == 2){
8602 pic16_emitcode("mov","c,acc.7");
8603 pic16_emitcode("rrc","a");
8604 pic16_emitcode("mov","c,acc.7");
8605 pic16_emitcode("rrc","a");
8607 tlbl = newiTempLabel(NULL);
8608 /* rotate right accumulator */
8609 AccRol(8 - shCount);
8610 /* and kill the higher order bits */
8611 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8612 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8613 pic16_emitcode("orl","a,#0x%02x",
8614 (unsigned char)~SRMask[shCount]);
8615 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8621 /*-----------------------------------------------------------------*/
8622 /* shiftR1Left2Result - shift right one byte from left to result */
8623 /*-----------------------------------------------------------------*/
8624 static void shiftR1Left2ResultSigned (operand *left, int offl,
8625 operand *result, int offr,
8630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8632 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8636 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8638 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8640 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8641 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8647 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8649 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8652 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8654 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8655 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8661 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8663 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8664 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8667 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8668 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8671 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8672 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8674 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8678 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8679 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8680 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8681 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8688 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8689 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8693 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8694 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8700 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8701 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8703 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8704 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8707 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8709 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8711 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8717 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8718 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8720 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8722 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8723 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8724 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8732 /*-----------------------------------------------------------------*/
8733 /* shiftR1Left2Result - shift right one byte from left to result */
8734 /*-----------------------------------------------------------------*/
8735 static void shiftR1Left2Result (operand *left, int offl,
8736 operand *result, int offr,
8737 int shCount, int sign)
8741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8743 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8745 /* Copy the msb into the carry if signed. */
8747 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8757 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8777 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8779 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8784 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8791 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8797 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8798 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8805 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8806 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8807 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8808 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8814 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8815 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8816 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8825 /*-----------------------------------------------------------------*/
8826 /* shiftL1Left2Result - shift left one byte from left to result */
8827 /*-----------------------------------------------------------------*/
8828 static void shiftL1Left2Result (operand *left, int offl,
8829 operand *result, int offr, int shCount)
8834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8836 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8837 DEBUGpic16_emitcode ("; ***","same = %d",same);
8838 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8840 /* shift left accumulator */
8841 //AccLsh(shCount, 1); // don't comment out just yet...
8842 // pic16_aopPut(AOP(result),"a",offr);
8846 /* Shift left 1 bit position */
8847 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8849 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8851 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8852 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8857 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8858 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8859 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8863 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8864 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_RLCF, 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));
8874 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8875 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8876 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8881 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8882 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8883 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8888 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8889 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8893 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8898 /*-----------------------------------------------------------------*/
8899 /* movLeft2Result - move byte from left to result */
8900 /*-----------------------------------------------------------------*/
8901 static void movLeft2Result (operand *left, int offl,
8902 operand *result, int offr)
8905 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8906 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8907 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8909 if (*l == '@' && (IS_AOP_PREG(result))) {
8910 pic16_emitcode("mov","a,%s",l);
8911 pic16_aopPut(AOP(result),"a",offr);
8913 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919 /*-----------------------------------------------------------------*/
8920 /* shiftL2Left2Result - shift left two bytes from left to result */
8921 /*-----------------------------------------------------------------*/
8922 static void shiftL2Left2Result (operand *left, int offl,
8923 operand *result, int offr, int shCount)
8925 int same = pic16_sameRegs(AOP(result), AOP(left));
8928 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8930 if (same && (offl != offr)) { // shift bytes
8933 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8934 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8936 } else { // just treat as different later on
8949 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8962 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8963 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8964 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8976 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8980 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8981 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8983 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8984 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8987 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8988 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8990 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8991 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9001 /* note, use a mov/add for the shift since the mov has a
9002 chance of getting optimized out */
9003 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9005 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9011 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9018 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9019 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9021 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9024 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9029 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9034 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9035 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9036 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9042 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9043 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9046 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9049 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9050 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9051 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9052 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9053 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9058 /*-----------------------------------------------------------------*/
9059 /* shiftR2Left2Result - shift right two bytes from left to result */
9060 /*-----------------------------------------------------------------*/
9061 static void shiftR2Left2Result (operand *left, int offl,
9062 operand *result, int offr,
9063 int shCount, int sign)
9065 int same = pic16_sameRegs(AOP(result), AOP(left));
9067 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9069 if (same && (offl != offr)) { // shift right bytes
9072 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9073 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9075 } else { // just treat as different later on
9087 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9092 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9093 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9095 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9096 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9098 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9106 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9107 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9115 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9119 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9120 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9121 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9123 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9124 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9125 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9128 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9129 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9130 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9131 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9136 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9141 pic16_emitpcode(POC_BTFSC,
9142 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9143 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9151 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9154 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9159 pic16_emitpcode(POC_BTFSC,
9160 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9161 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9163 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9164 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9165 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9168 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9169 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9170 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9171 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9173 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9175 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9177 pic16_emitpcode(POC_BTFSC,
9178 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9179 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9181 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9182 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9189 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9190 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9191 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9192 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9195 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9197 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9202 /*-----------------------------------------------------------------*/
9203 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9204 /*-----------------------------------------------------------------*/
9205 static void shiftLLeftOrResult (operand *left, int offl,
9206 operand *result, int offr, int shCount)
9208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9210 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9211 /* shift left accumulator */
9213 /* or with result */
9214 /* back to result */
9215 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9218 /*-----------------------------------------------------------------*/
9219 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9220 /*-----------------------------------------------------------------*/
9221 static void shiftRLeftOrResult (operand *left, int offl,
9222 operand *result, int offr, int shCount)
9224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9226 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9227 /* shift right accumulator */
9229 /* or with result */
9230 /* back to result */
9231 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9234 /*-----------------------------------------------------------------*/
9235 /* genlshOne - left shift a one byte quantity by known count */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshOne (operand *result, operand *left, int shCount)
9239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9240 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9243 /*-----------------------------------------------------------------*/
9244 /* genlshTwo - left shift two bytes by known amount != 0 */
9245 /*-----------------------------------------------------------------*/
9246 static void genlshTwo (operand *result,operand *left, int shCount)
9250 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9251 size = pic16_getDataSize(result);
9253 /* if shCount >= 8 */
9259 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9261 movLeft2Result(left, LSB, result, MSB16);
9263 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9266 /* 1 <= shCount <= 7 */
9269 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9271 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9275 /*-----------------------------------------------------------------*/
9276 /* shiftLLong - shift left one long from left to result */
9277 /* offr = LSB or MSB16 */
9278 /*-----------------------------------------------------------------*/
9279 static void shiftLLong (operand *left, operand *result, int offr )
9281 int size = AOP_SIZE(result);
9282 int same = pic16_sameRegs(AOP(left),AOP(result));
9285 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9287 if (same && (offr == MSB16)) { //shift one byte
9288 for(i=size-1;i>=MSB16;i--) {
9289 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9290 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9293 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9296 if (size > LSB+offr ){
9298 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9300 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9305 if(size > MSB16+offr){
9307 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9309 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9314 if(size > MSB24+offr){
9316 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9318 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9319 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9323 if(size > MSB32+offr){
9325 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9327 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9328 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9332 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9336 /*-----------------------------------------------------------------*/
9337 /* genlshFour - shift four byte by a known amount != 0 */
9338 /*-----------------------------------------------------------------*/
9339 static void genlshFour (operand *result, operand *left, int shCount)
9343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9344 size = AOP_SIZE(result);
9346 /* if shifting more that 3 bytes */
9347 if (shCount >= 24 ) {
9350 /* lowest order of left goes to the highest
9351 order of the destination */
9352 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9354 movLeft2Result(left, LSB, result, MSB32);
9356 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9357 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9358 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9363 /* more than two bytes */
9364 else if ( shCount >= 16 ) {
9365 /* lower order two bytes goes to higher order two bytes */
9367 /* if some more remaining */
9369 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9371 movLeft2Result(left, MSB16, result, MSB32);
9372 movLeft2Result(left, LSB, result, MSB24);
9374 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9375 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9379 /* if more than 1 byte */
9380 else if ( shCount >= 8 ) {
9381 /* lower order three bytes goes to higher order three bytes */
9385 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9387 movLeft2Result(left, LSB, result, MSB16);
9389 else{ /* size = 4 */
9391 movLeft2Result(left, MSB24, result, MSB32);
9392 movLeft2Result(left, MSB16, result, MSB24);
9393 movLeft2Result(left, LSB, result, MSB16);
9394 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9396 else if(shCount == 1)
9397 shiftLLong(left, result, MSB16);
9399 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9400 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9401 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9402 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9407 /* 1 <= shCount <= 7 */
9408 else if(shCount <= 3)
9410 shiftLLong(left, result, LSB);
9411 while(--shCount >= 1)
9412 shiftLLong(result, result, LSB);
9414 /* 3 <= shCount <= 7, optimize */
9416 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9417 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9418 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9422 /*-----------------------------------------------------------------*/
9423 /* genLeftShiftLiteral - left shifting by known count */
9424 /*-----------------------------------------------------------------*/
9425 void pic16_genLeftShiftLiteral (operand *left,
9430 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9434 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9435 pic16_freeAsmop(right,NULL,ic,TRUE);
9437 pic16_aopOp(left,ic,FALSE);
9438 pic16_aopOp(result,ic,TRUE);
9440 size = getSize(operandType(result));
9443 pic16_emitcode("; shift left ","result %d, left %d",size,
9447 /* I suppose that the left size >= result size */
9450 movLeft2Result(left, size, result, size);
9454 else if(shCount >= (size * 8))
9456 pic16_aopPut(AOP(result),zero,size);
9460 genlshOne (result,left,shCount);
9465 genlshTwo (result,left,shCount);
9469 genlshFour (result,left,shCount);
9473 pic16_freeAsmop(left,NULL,ic,TRUE);
9474 pic16_freeAsmop(result,NULL,ic,TRUE);
9477 /*-----------------------------------------------------------------*
9478 * genMultiAsm - repeat assembly instruction for size of register.
9479 * if endian == 1, then the high byte (i.e base address + size of
9480 * register) is used first else the low byte is used first;
9481 *-----------------------------------------------------------------*/
9482 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9500 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9506 #if !(USE_GENERIC_SIGNED_SHIFT)
9507 /*-----------------------------------------------------------------*/
9508 /* genLeftShift - generates code for left shifting */
9509 /*-----------------------------------------------------------------*/
9510 static void genLeftShift (iCode *ic)
9512 operand *left,*right, *result;
9515 symbol *tlbl , *tlbl1;
9518 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9520 right = IC_RIGHT(ic);
9522 result = IC_RESULT(ic);
9524 pic16_aopOp(right,ic,FALSE);
9526 /* if the shift count is known then do it
9527 as efficiently as possible */
9528 if (AOP_TYPE(right) == AOP_LIT) {
9529 pic16_genLeftShiftLiteral (left,right,result,ic);
9533 /* shift count is unknown then we have to form
9534 * a loop. Get the loop count in WREG : Note: we take
9535 * only the lower order byte since shifting
9536 * more than 32 bits make no sense anyway, ( the
9537 * largest size of an object can be only 32 bits ) */
9539 pic16_aopOp(left,ic,FALSE);
9540 pic16_aopOp(result,ic,FALSE);
9542 /* now move the left to the result if they are not the
9543 * same, and if size > 1,
9544 * and if right is not same to result (!!!) -- VR */
9545 if (!pic16_sameRegs(AOP(left),AOP(result))
9546 && (AOP_SIZE(result) > 1)) {
9548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9550 size = AOP_SIZE(result);
9555 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9556 if (*l == '@' && (IS_AOP_PREG(result))) {
9558 pic16_emitcode("mov","a,%s",l);
9559 pic16_aopPut(AOP(result),"a",offset);
9563 /* we don't know if left is a literal or a register, take care -- VR */
9564 pic16_mov2f(AOP(result), AOP(left), offset);
9570 size = AOP_SIZE(result);
9572 /* if it is only one byte then */
9574 if(optimized_for_speed) {
9575 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9576 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9577 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9578 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9579 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9580 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9581 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9582 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9583 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9584 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9585 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9586 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9591 tlbl = newiTempLabel(NULL);
9594 /* this is already done, why change it? */
9595 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9596 pic16_mov2f(AOP(result), AOP(left), 0);
9600 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9601 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9602 pic16_emitpLabel(tlbl->key);
9603 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9604 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9606 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9611 if (pic16_sameRegs(AOP(left),AOP(result))) {
9613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9615 tlbl = newiTempLabel(NULL);
9616 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9617 genMultiAsm(POC_RRCF, result, size,1);
9618 pic16_emitpLabel(tlbl->key);
9619 genMultiAsm(POC_RLCF, result, size,0);
9620 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9622 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9626 //tlbl = newiTempLabel(NULL);
9628 //tlbl1 = newiTempLabel(NULL);
9630 //reAdjustPreg(AOP(result));
9632 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9633 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9634 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9636 //pic16_emitcode("add","a,acc");
9637 //pic16_aopPut(AOP(result),"a",offset++);
9639 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9641 // pic16_emitcode("rlc","a");
9642 // pic16_aopPut(AOP(result),"a",offset++);
9644 //reAdjustPreg(AOP(result));
9646 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9647 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9650 tlbl = newiTempLabel(NULL);
9651 tlbl1= newiTempLabel(NULL);
9653 size = AOP_SIZE(result);
9656 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9658 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9660 /* offset should be 0, 1 or 3 */
9662 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9664 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9666 pic16_emitpcode(POC_MOVWF, pctemp);
9669 pic16_emitpLabel(tlbl->key);
9672 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9674 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9676 pic16_emitpcode(POC_DECFSZ, pctemp);
9677 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9678 pic16_emitpLabel(tlbl1->key);
9680 pic16_popReleaseTempReg(pctemp,1);
9684 pic16_freeAsmop (right,NULL,ic,TRUE);
9685 pic16_freeAsmop(left,NULL,ic,TRUE);
9686 pic16_freeAsmop(result,NULL,ic,TRUE);
9692 #error old code (left here for reference)
9693 /*-----------------------------------------------------------------*/
9694 /* genLeftShift - generates code for left shifting */
9695 /*-----------------------------------------------------------------*/
9696 static void genLeftShift (iCode *ic)
9698 operand *left,*right, *result;
9701 symbol *tlbl , *tlbl1;
9704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9706 right = IC_RIGHT(ic);
9708 result = IC_RESULT(ic);
9710 pic16_aopOp(right,ic,FALSE);
9712 /* if the shift count is known then do it
9713 as efficiently as possible */
9714 if (AOP_TYPE(right) == AOP_LIT) {
9715 pic16_genLeftShiftLiteral (left,right,result,ic);
9719 /* shift count is unknown then we have to form
9720 a loop get the loop count in B : Note: we take
9721 only the lower order byte since shifting
9722 more that 32 bits make no sense anyway, ( the
9723 largest size of an object can be only 32 bits ) */
9726 pic16_aopOp(left,ic,FALSE);
9727 pic16_aopOp(result,ic,FALSE);
9729 /* now move the left to the result if they are not the
9731 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9732 AOP_SIZE(result) > 1) {
9734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9736 size = AOP_SIZE(result);
9739 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9740 if (*l == '@' && (IS_AOP_PREG(result))) {
9742 pic16_emitcode("mov","a,%s",l);
9743 pic16_aopPut(AOP(result),"a",offset);
9746 /* we don't know if left is a literal or a register, take care -- VR */
9747 pic16_mov2f(AOP(result), AOP(left), offset);
9753 size = AOP_SIZE(result);
9755 /* if it is only one byte then */
9757 if(optimized_for_speed) {
9758 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9759 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9760 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9761 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9763 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9764 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9765 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9766 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9767 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9768 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9769 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9772 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9774 tlbl = newiTempLabel(NULL);
9775 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9776 pic16_mov2f(AOP(result), AOP(left), 0);
9778 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9779 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9782 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9783 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9784 pic16_emitpLabel(tlbl->key);
9785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9786 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9788 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9793 if (pic16_sameRegs(AOP(left),AOP(result))) {
9795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9797 tlbl = newiTempLabel(NULL);
9798 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9799 genMultiAsm(POC_RRCF, result, size,1);
9800 pic16_emitpLabel(tlbl->key);
9801 genMultiAsm(POC_RLCF, result, size,0);
9802 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9804 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9808 //tlbl = newiTempLabel(NULL);
9810 //tlbl1 = newiTempLabel(NULL);
9812 //reAdjustPreg(AOP(result));
9814 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9815 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9816 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9818 //pic16_emitcode("add","a,acc");
9819 //pic16_aopPut(AOP(result),"a",offset++);
9821 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9823 // pic16_emitcode("rlc","a");
9824 // pic16_aopPut(AOP(result),"a",offset++);
9826 //reAdjustPreg(AOP(result));
9828 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9829 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9832 tlbl = newiTempLabel(NULL);
9833 tlbl1= newiTempLabel(NULL);
9835 size = AOP_SIZE(result);
9838 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9840 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9842 /* offset should be 0, 1 or 3 */
9844 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9846 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9848 pic16_emitpcode(POC_MOVWF, pctemp);
9851 pic16_emitpLabel(tlbl->key);
9854 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9856 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9858 pic16_emitpcode(POC_DECFSZ, pctemp);
9859 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9860 pic16_emitpLabel(tlbl1->key);
9862 pic16_popReleaseTempReg(pctemp,1);
9866 pic16_freeAsmop (right,NULL,ic,TRUE);
9867 pic16_freeAsmop(left,NULL,ic,TRUE);
9868 pic16_freeAsmop(result,NULL,ic,TRUE);
9872 /*-----------------------------------------------------------------*/
9873 /* genrshOne - right shift a one byte quantity by known count */
9874 /*-----------------------------------------------------------------*/
9875 static void genrshOne (operand *result, operand *left,
9876 int shCount, int sign)
9878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9879 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9882 /*-----------------------------------------------------------------*/
9883 /* genrshTwo - right shift two bytes by known amount != 0 */
9884 /*-----------------------------------------------------------------*/
9885 static void genrshTwo (operand *result,operand *left,
9886 int shCount, int sign)
9888 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9889 /* if shCount >= 8 */
9893 shiftR1Left2Result(left, MSB16, result, LSB,
9896 movLeft2Result(left, MSB16, result, LSB);
9898 pic16_addSign (result, 1, sign);
9901 /* 1 <= shCount <= 7 */
9903 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9906 /*-----------------------------------------------------------------*/
9907 /* shiftRLong - shift right one long from left to result */
9908 /* offl = LSB or MSB16 */
9909 /*-----------------------------------------------------------------*/
9910 static void shiftRLong (operand *left, int offl,
9911 operand *result, int sign)
9913 int size = AOP_SIZE(result);
9914 int same = pic16_sameRegs(AOP(left),AOP(result));
9916 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9918 if (same && (offl == MSB16)) { //shift one byte right
9919 for(i=MSB16;i<size;i++) {
9920 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9921 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9926 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9932 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9934 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9939 /* add sign of "a" */
9940 pic16_addSign(result, MSB32, sign);
9944 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9946 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9951 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9953 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9958 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9961 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9967 /*-----------------------------------------------------------------*/
9968 /* genrshFour - shift four byte by a known amount != 0 */
9969 /*-----------------------------------------------------------------*/
9970 static void genrshFour (operand *result, operand *left,
9971 int shCount, int sign)
9973 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9974 /* if shifting more that 3 bytes */
9975 if(shCount >= 24 ) {
9978 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9980 movLeft2Result(left, MSB32, result, LSB);
9982 pic16_addSign(result, MSB16, sign);
9984 else if(shCount >= 16){
9987 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9989 movLeft2Result(left, MSB24, result, LSB);
9990 movLeft2Result(left, MSB32, result, MSB16);
9992 pic16_addSign(result, MSB24, sign);
9994 else if(shCount >= 8){
9997 shiftRLong(left, MSB16, result, sign);
9998 else if(shCount == 0){
9999 movLeft2Result(left, MSB16, result, LSB);
10000 movLeft2Result(left, MSB24, result, MSB16);
10001 movLeft2Result(left, MSB32, result, MSB24);
10002 pic16_addSign(result, MSB32, sign);
10004 else{ //shcount >= 2
10005 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10006 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10007 /* the last shift is signed */
10008 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10009 pic16_addSign(result, MSB32, sign);
10012 else{ /* 1 <= shCount <= 7 */
10014 shiftRLong(left, LSB, result, sign);
10016 shiftRLong(result, LSB, result, sign);
10019 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10020 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10021 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10026 /*-----------------------------------------------------------------*/
10027 /* genRightShiftLiteral - right shifting by known count */
10028 /*-----------------------------------------------------------------*/
10029 static void genRightShiftLiteral (operand *left,
10035 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10036 int lsize,res_size;
10038 pic16_freeAsmop(right,NULL,ic,TRUE);
10040 pic16_aopOp(left,ic,FALSE);
10041 pic16_aopOp(result,ic,TRUE);
10043 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10046 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10050 lsize = pic16_getDataSize(left);
10051 res_size = pic16_getDataSize(result);
10052 /* test the LEFT size !!! */
10054 /* I suppose that the left size >= result size */
10056 assert (res_size <= lsize);
10057 while (res_size--) {
10058 pic16_mov2f (AOP(result), AOP(left), res_size);
10062 else if(shCount >= (lsize * 8)){
10064 if(res_size == 1) {
10065 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10067 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10068 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10073 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10074 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10075 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10082 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10087 switch (res_size) {
10089 genrshOne (result,left,shCount,sign);
10093 genrshTwo (result,left,shCount,sign);
10097 genrshFour (result,left,shCount,sign);
10105 pic16_freeAsmop(left,NULL,ic,TRUE);
10106 pic16_freeAsmop(result,NULL,ic,TRUE);
10109 #if !(USE_GENERIC_SIGNED_SHIFT)
10110 /*-----------------------------------------------------------------*/
10111 /* genSignedRightShift - right shift of signed number */
10112 /*-----------------------------------------------------------------*/
10113 static void genSignedRightShift (iCode *ic)
10115 operand *right, *left, *result;
10118 symbol *tlbl, *tlbl1 ;
10121 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10123 /* we do it the hard way put the shift count in b
10124 and loop thru preserving the sign */
10125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10127 right = IC_RIGHT(ic);
10128 left = IC_LEFT(ic);
10129 result = IC_RESULT(ic);
10131 pic16_aopOp(right,ic,FALSE);
10132 pic16_aopOp(left,ic,FALSE);
10133 pic16_aopOp(result,ic,FALSE);
10136 if ( AOP_TYPE(right) == AOP_LIT) {
10137 genRightShiftLiteral (left,right,result,ic,1);
10140 /* shift count is unknown then we have to form
10141 a loop get the loop count in B : Note: we take
10142 only the lower order byte since shifting
10143 more that 32 bits make no sense anyway, ( the
10144 largest size of an object can be only 32 bits ) */
10146 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10147 //pic16_emitcode("inc","b");
10148 //pic16_freeAsmop (right,NULL,ic,TRUE);
10149 //pic16_aopOp(left,ic,FALSE);
10150 //pic16_aopOp(result,ic,FALSE);
10152 /* now move the left to the result if they are not the
10154 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10155 AOP_SIZE(result) > 1) {
10157 size = AOP_SIZE(result);
10161 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10162 if (*l == '@' && IS_AOP_PREG(result)) {
10164 pic16_emitcode("mov","a,%s",l);
10165 pic16_aopPut(AOP(result),"a",offset);
10167 pic16_aopPut(AOP(result),l,offset);
10169 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10170 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10176 /* mov the highest order bit to OVR */
10177 tlbl = newiTempLabel(NULL);
10178 tlbl1= newiTempLabel(NULL);
10180 size = AOP_SIZE(result);
10183 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10185 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10187 /* offset should be 0, 1 or 3 */
10188 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10190 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10192 pic16_emitpcode(POC_MOVWF, pctemp);
10195 pic16_emitpLabel(tlbl->key);
10197 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10198 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10201 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10204 pic16_emitpcode(POC_DECFSZ, pctemp);
10205 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10206 pic16_emitpLabel(tlbl1->key);
10208 pic16_popReleaseTempReg(pctemp,1);
10210 size = AOP_SIZE(result);
10212 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10213 pic16_emitcode("rlc","a");
10214 pic16_emitcode("mov","ov,c");
10215 /* if it is only one byte then */
10217 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10219 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10220 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10221 pic16_emitcode("mov","c,ov");
10222 pic16_emitcode("rrc","a");
10223 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10224 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10225 pic16_aopPut(AOP(result),"a",0);
10229 reAdjustPreg(AOP(result));
10230 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10231 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10232 pic16_emitcode("mov","c,ov");
10234 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10236 pic16_emitcode("rrc","a");
10237 pic16_aopPut(AOP(result),"a",offset--);
10239 reAdjustPreg(AOP(result));
10240 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10241 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10246 pic16_freeAsmop(left,NULL,ic,TRUE);
10247 pic16_freeAsmop(result,NULL,ic,TRUE);
10248 pic16_freeAsmop(right,NULL,ic,TRUE);
10252 #if !(USE_GENERIC_SIGNED_SHIFT)
10253 #warning This implementation of genRightShift() is incomplete!
10254 /*-----------------------------------------------------------------*/
10255 /* genRightShift - generate code for right shifting */
10256 /*-----------------------------------------------------------------*/
10257 static void genRightShift (iCode *ic)
10259 operand *right, *left, *result;
10263 symbol *tlbl, *tlbl1 ;
10265 /* if signed then we do it the hard way preserve the
10266 sign bit moving it inwards */
10267 letype = getSpec(operandType(IC_LEFT(ic)));
10268 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10270 if (!SPEC_USIGN(letype)) {
10271 genSignedRightShift (ic);
10275 /* signed & unsigned types are treated the same : i.e. the
10276 signed is NOT propagated inwards : quoting from the
10277 ANSI - standard : "for E1 >> E2, is equivalent to division
10278 by 2**E2 if unsigned or if it has a non-negative value,
10279 otherwise the result is implementation defined ", MY definition
10280 is that the sign does not get propagated */
10282 right = IC_RIGHT(ic);
10283 left = IC_LEFT(ic);
10284 result = IC_RESULT(ic);
10286 pic16_aopOp(right,ic,FALSE);
10288 /* if the shift count is known then do it
10289 as efficiently as possible */
10290 if (AOP_TYPE(right) == AOP_LIT) {
10291 genRightShiftLiteral (left,right,result,ic, 0);
10295 /* shift count is unknown then we have to form
10296 a loop get the loop count in B : Note: we take
10297 only the lower order byte since shifting
10298 more that 32 bits make no sense anyway, ( the
10299 largest size of an object can be only 32 bits ) */
10301 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10302 pic16_emitcode("inc","b");
10303 pic16_aopOp(left,ic,FALSE);
10304 pic16_aopOp(result,ic,FALSE);
10306 /* now move the left to the result if they are not the
10308 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10309 AOP_SIZE(result) > 1) {
10311 size = AOP_SIZE(result);
10314 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10315 if (*l == '@' && IS_AOP_PREG(result)) {
10317 pic16_emitcode("mov","a,%s",l);
10318 pic16_aopPut(AOP(result),"a",offset);
10320 pic16_aopPut(AOP(result),l,offset);
10325 tlbl = newiTempLabel(NULL);
10326 tlbl1= newiTempLabel(NULL);
10327 size = AOP_SIZE(result);
10330 /* if it is only one byte then */
10333 tlbl = newiTempLabel(NULL);
10334 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10339 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10340 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10341 pic16_emitpLabel(tlbl->key);
10342 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10343 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10345 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10350 reAdjustPreg(AOP(result));
10351 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10352 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10355 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10357 pic16_emitcode("rrc","a");
10358 pic16_aopPut(AOP(result),"a",offset--);
10360 reAdjustPreg(AOP(result));
10362 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10363 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10366 pic16_freeAsmop(left,NULL,ic,TRUE);
10367 pic16_freeAsmop (right,NULL,ic,TRUE);
10368 pic16_freeAsmop(result,NULL,ic,TRUE);
10372 #if (USE_GENERIC_SIGNED_SHIFT)
10373 /*-----------------------------------------------------------------*/
10374 /* genGenericShift - generates code for left or right shifting */
10375 /*-----------------------------------------------------------------*/
10376 static void genGenericShift (iCode *ic, int isShiftLeft) {
10377 operand *left,*right, *result;
10379 int sign, signedCount;
10380 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10381 PIC_OPCODE pos_shift, neg_shift;
10385 right = IC_RIGHT(ic);
10386 left = IC_LEFT(ic);
10387 result = IC_RESULT(ic);
10389 pic16_aopOp(right,ic,FALSE);
10390 pic16_aopOp(left,ic,FALSE);
10391 pic16_aopOp(result,ic,TRUE);
10393 sign = !SPEC_USIGN(operandType (left));
10394 signedCount = !SPEC_USIGN(operandType (right));
10396 /* if the shift count is known then do it
10397 as efficiently as possible */
10398 if (AOP_TYPE(right) == AOP_LIT) {
10399 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10400 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10401 // we should modify right->aopu.aop_lit here!
10402 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10403 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10405 pic16_genLeftShiftLiteral (left,right,result,ic);
10407 genRightShiftLiteral (left,right,result,ic, sign);
10410 } // if (right is literal)
10412 /* shift count is unknown then we have to form a loop.
10413 * Note: we take only the lower order byte since shifting
10414 * more than 32 bits make no sense anyway, ( the
10415 * largest size of an object can be only 32 bits )
10416 * Note: we perform arithmetic shifts if the left operand is
10417 * signed and we do an (effective) right shift, i. e. we
10418 * shift in the sign bit from the left. */
10420 label_complete = newiTempLabel ( NULL );
10421 label_loop_pos = newiTempLabel ( NULL );
10422 label_loop_neg = NULL;
10423 label_negative = NULL;
10424 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10425 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10428 // additional labels needed
10429 label_loop_neg = newiTempLabel ( NULL );
10430 label_negative = newiTempLabel ( NULL );
10433 // copy source to result -- this will effectively truncate the left operand to the size of result!
10434 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10435 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10436 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10437 pic16_mov2f (AOP(result),AOP(left), offset);
10440 // if result is longer than left, fill with zeros (or sign)
10441 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10442 if (sign && AOP_SIZE(left) > 0) {
10443 // shift signed operand -- fill with sign
10444 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10445 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10446 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10447 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10451 // shift unsigned operand -- fill result with zeros
10452 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10453 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10456 } // if (size mismatch)
10458 pic16_mov2w (AOP(right), 0);
10459 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10460 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10463 // perform a shift by one (shift count is positive)
10464 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10465 // 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])
10466 pic16_emitpLabel (label_loop_pos->key);
10468 if (sign && (pos_shift == POC_RRCF)) {
10469 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10472 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10473 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10474 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10476 // perform a shift by one (shift count is positive)
10477 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10478 // 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])
10479 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10480 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10482 pic16_emitpLabel (label_loop_pos->key);
10483 if (sign && (pos_shift == POC_RRCF)) {
10484 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10487 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10488 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10489 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10490 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10494 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10496 pic16_emitpLabel (label_negative->key);
10497 // perform a shift by -1 (shift count is negative)
10498 // 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)
10500 pic16_emitpLabel (label_loop_neg->key);
10501 if (sign && (neg_shift == POC_RRCF)) {
10502 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10505 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10506 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10507 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10508 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10509 } // if (signedCount)
10511 pic16_emitpLabel (label_complete->key);
10514 pic16_freeAsmop (right,NULL,ic,TRUE);
10515 pic16_freeAsmop(left,NULL,ic,TRUE);
10516 pic16_freeAsmop(result,NULL,ic,TRUE);
10519 static void genLeftShift (iCode *ic) {
10520 genGenericShift (ic, 1);
10523 static void genRightShift (iCode *ic) {
10524 genGenericShift (ic, 0);
10529 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10530 void pic16_loadFSR0(operand *op, int lit)
10532 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10533 if (AOP_TYPE(op) == AOP_LIT) {
10534 /* handle 12 bit integers correctly */
10535 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10536 if ((val & 0x0fff) != val) {
10537 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10538 val, (val & 0x0fff) );
10541 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10543 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10546 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10547 // set up FSR0 with address of result
10548 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10549 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10553 /*----------------------------------------------------------------*/
10554 /* pic16_derefPtr - move one byte from the location ptr points to */
10555 /* to WREG (doWrite == 0) or one byte from WREG */
10556 /* to the location ptr points to (doWrite != 0) */
10557 /*----------------------------------------------------------------*/
10558 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10560 if (!IS_PTR(operandType(ptr)))
10562 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10563 else pic16_mov2w (AOP(ptr), 0);
10567 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10568 /* We might determine pointer type right here: */
10569 p_type = DCL_TYPE(operandType(ptr));
10574 if (!fsr0_setup || !*fsr0_setup)
10576 pic16_loadFSR0( ptr, 0 );
10577 if (fsr0_setup) *fsr0_setup = 1;
10580 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10582 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10586 if (AOP(ptr)->aopu.aop_reg[2]) {
10587 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10588 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10589 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10590 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10591 pic16_mov2w(AOP(ptr), 2);
10592 pic16_callGenericPointerRW(doWrite, 1);
10594 // data pointer (just 2 byte given)
10595 if (!fsr0_setup || !*fsr0_setup)
10597 pic16_loadFSR0( ptr, 0 );
10598 if (fsr0_setup) *fsr0_setup = 1;
10601 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10603 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10608 assert (0 && "invalid pointer type specified");
10613 /*-----------------------------------------------------------------*/
10614 /* genUnpackBits - generates code for unpacking bits */
10615 /*-----------------------------------------------------------------*/
10616 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10619 sym_link *etype, *letype;
10620 int blen=0, bstr=0;
10625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10626 etype = getSpec(operandType(result));
10627 letype = getSpec(operandType(left));
10629 // if(IS_BITFIELD(etype)) {
10630 blen = SPEC_BLEN(etype);
10631 bstr = SPEC_BSTR(etype);
10634 lbstr = SPEC_BSTR( letype );
10636 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10637 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10640 if((blen == 1) && (bstr < 8)
10641 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10642 /* it is a single bit, so use the appropriate bit instructions */
10643 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10645 same = pic16_sameRegs(AOP(left),AOP(result));
10646 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10647 pic16_emitpcode(POC_CLRF, op);
10649 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10650 /* workaround to reduce the extra lfsr instruction */
10651 pic16_emitpcode(POC_BTFSC,
10652 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10654 assert (PIC_IS_DATA_PTR (operandType(left)));
10655 pic16_loadFSR0 (left, 0);
10656 pic16_emitpcode(POC_BTFSC,
10657 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10660 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10661 /* unsigned bitfields result in either 0 or 1 */
10662 pic16_emitpcode(POC_INCF, op);
10664 /* signed bitfields result in either 0 or -1 */
10665 pic16_emitpcode(POC_DECF, op);
10668 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10671 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10677 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10678 // access symbol directly
10679 pic16_mov2w (AOP(left), 0);
10681 pic16_derefPtr (left, ptype, 0, NULL);
10684 /* if we have bitdisplacement then it fits */
10685 /* into this byte completely or if length is */
10686 /* less than a byte */
10687 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10689 /* shift right acc */
10692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10693 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10695 /* VR -- normally I would use the following, but since we use the hack,
10696 * to avoid the masking from AccRsh, why not mask it right now? */
10699 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10702 /* extend signed bitfields to 8 bits */
10703 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10705 assert (blen + bstr > 0);
10706 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10707 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10710 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10712 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10716 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10717 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10724 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10726 int size, offset = 0, leoffset=0 ;
10728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10729 pic16_aopOp(result, ic, TRUE);
10733 size = AOP_SIZE(result);
10734 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10738 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10739 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10740 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10745 if(AOP(left)->aopu.pcop->type == PO_DIR)
10746 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10748 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10751 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10753 // pic16_DumpOp("(result)",result);
10754 if(is_LitAOp(AOP(result))) {
10755 pic16_mov2w(AOP(left), offset); // patch 8
10756 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10758 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10759 pic16_popGet(AOP(left), offset), //patch 8
10760 pic16_popGet(AOP(result), offset)));
10768 pic16_freeAsmop(result,NULL,ic,TRUE);
10773 /*-----------------------------------------------------------------*/
10774 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10775 /*-----------------------------------------------------------------*/
10776 static void genNearPointerGet (operand *left,
10780 // asmop *aop = NULL;
10781 //regs *preg = NULL ;
10782 sym_link *rtype, *retype;
10783 sym_link *ltype, *letype;
10787 rtype = operandType(result);
10788 retype= getSpec(rtype);
10789 ltype = operandType(left);
10790 letype= getSpec(ltype);
10792 pic16_aopOp(left,ic,FALSE);
10794 // pic16_DumpOp("(left)",left);
10795 // pic16_DumpOp("(result)",result);
10797 /* if left is rematerialisable and
10798 * result is not bit variable type and
10799 * the left is pointer to data space i.e
10800 * lower 128 bytes of space */
10802 if (AOP_TYPE(left) == AOP_PCODE
10803 && !IS_BITFIELD(retype)
10804 && DCL_TYPE(ltype) == POINTER) {
10806 genDataPointerGet (left,result,ic);
10807 pic16_freeAsmop(left, NULL, ic, TRUE);
10811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10812 pic16_aopOp (result,ic,TRUE);
10814 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10817 if(IS_BITFIELD( retype )
10818 && (SPEC_BLEN(operandType(result))==1)
10822 int bitstrt, bytestrt;
10824 /* if this is bitfield of size 1, see if we are checking the value
10825 * of a single bit in an if-statement,
10826 * if yes, then don't generate usual code, but execute the
10827 * genIfx directly -- VR */
10831 /* CHECK: if next iCode is IFX
10832 * and current result operand is nextic's conditional operand
10833 * and current result operand live ranges ends at nextic's key number
10835 if((nextic->op == IFX)
10836 && (result == IC_COND(nextic))
10837 && (OP_LIVETO(result) == nextic->seq)
10838 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10840 /* everything is ok then */
10841 /* find a way to optimize the genIfx iCode */
10843 bytestrt = SPEC_BSTR(operandType(result))/8;
10844 bitstrt = SPEC_BSTR(operandType(result))%8;
10846 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10848 genIfxpCOpJump(nextic, jop);
10850 pic16_freeAsmop(left, NULL, ic, TRUE);
10851 pic16_freeAsmop(result, NULL, ic, TRUE);
10857 /* if bitfield then unpack the bits */
10858 if (IS_BITFIELD(letype))
10859 genUnpackBits (result, left, NULL, POINTER);
10861 /* we have can just get the values */
10862 int size = AOP_SIZE(result);
10865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10867 pic16_loadFSR0( left, 0 );
10871 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10872 pic16_popGet(AOP(result), offset++)));
10874 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10875 pic16_popGet(AOP(result), offset++)));
10881 /* now some housekeeping stuff */
10883 /* we had to allocate for this iCode */
10884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10885 pic16_freeAsmop(NULL,aop,ic,TRUE);
10887 /* we did not allocate which means left
10888 * already in a pointer register, then
10889 * if size > 0 && this could be used again
10890 * we have to point it back to where it
10892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10893 if (AOP_SIZE(result) > 1
10894 && !OP_SYMBOL(left)->remat
10895 && ( OP_SYMBOL(left)->liveTo > ic->seq
10897 // int size = AOP_SIZE(result) - 1;
10899 // pic16_emitcode("dec","%s",rname);
10905 pic16_freeAsmop(left,NULL,ic,TRUE);
10906 pic16_freeAsmop(result,NULL,ic,TRUE);
10909 /*-----------------------------------------------------------------*/
10910 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10911 /*-----------------------------------------------------------------*/
10912 static void genPagedPointerGet (operand *left,
10917 regs *preg = NULL ;
10919 sym_link *rtype, *retype;
10921 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10923 rtype = operandType(result);
10924 retype= getSpec(rtype);
10926 pic16_aopOp(left,ic,FALSE);
10928 /* if the value is already in a pointer register
10929 then don't need anything more */
10930 if (!AOP_INPREG(AOP(left))) {
10931 /* otherwise get a free pointer register */
10933 preg = getFreePtr(ic,&aop,FALSE);
10934 pic16_emitcode("mov","%s,%s",
10936 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10937 rname = preg->name ;
10939 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10941 pic16_freeAsmop(left,NULL,ic,TRUE);
10942 pic16_aopOp (result,ic,TRUE);
10944 /* if bitfield then unpack the bits */
10945 if (IS_BITFIELD(retype))
10946 genUnpackBits (result,left,rname,PPOINTER);
10948 /* we have can just get the values */
10949 int size = AOP_SIZE(result);
10954 pic16_emitcode("movx","a,@%s",rname);
10955 pic16_aopPut(AOP(result),"a",offset);
10960 pic16_emitcode("inc","%s",rname);
10964 /* now some housekeeping stuff */
10966 /* we had to allocate for this iCode */
10967 pic16_freeAsmop(NULL,aop,ic,TRUE);
10969 /* we did not allocate which means left
10970 already in a pointer register, then
10971 if size > 0 && this could be used again
10972 we have to point it back to where it
10974 if (AOP_SIZE(result) > 1 &&
10975 !OP_SYMBOL(left)->remat &&
10976 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10978 int size = AOP_SIZE(result) - 1;
10980 pic16_emitcode("dec","%s",rname);
10985 pic16_freeAsmop(result,NULL,ic,TRUE);
10991 /* This code is not adjusted to PIC16 and fails utterly.
10992 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10994 /*-----------------------------------------------------------------*/
10995 /* genFarPointerGet - gget value from far space */
10996 /*-----------------------------------------------------------------*/
10997 static void genFarPointerGet (operand *left,
10998 operand *result, iCode *ic)
11001 sym_link *retype = getSpec(operandType(result));
11003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11005 pic16_aopOp(left,ic,FALSE);
11007 /* if the operand is already in dptr
11008 then we do nothing else we move the value to dptr */
11009 if (AOP_TYPE(left) != AOP_STR) {
11010 /* if this is remateriazable */
11011 if (AOP_TYPE(left) == AOP_IMMD)
11012 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11013 else { /* we need to get it byte by byte */
11014 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11015 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11016 if (options.model == MODEL_FLAT24)
11018 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11022 /* so dptr know contains the address */
11023 pic16_freeAsmop(left,NULL,ic,TRUE);
11024 pic16_aopOp(result,ic,TRUE);
11026 /* if bit then unpack */
11027 if (IS_BITFIELD(retype))
11028 genUnpackBits(result,left,"dptr",FPOINTER);
11030 size = AOP_SIZE(result);
11034 pic16_emitcode("movx","a,@dptr");
11035 pic16_aopPut(AOP(result),"a",offset++);
11037 pic16_emitcode("inc","dptr");
11041 pic16_freeAsmop(result,NULL,ic,TRUE);
11046 /*-----------------------------------------------------------------*/
11047 /* genCodePointerGet - get value from code space */
11048 /*-----------------------------------------------------------------*/
11049 static void genCodePointerGet (operand *left,
11050 operand *result, iCode *ic)
11053 sym_link *retype = getSpec(operandType(result));
11055 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11057 pic16_aopOp(left,ic,FALSE);
11059 /* if the operand is already in dptr
11060 then we do nothing else we move the value to dptr */
11061 if (AOP_TYPE(left) != AOP_STR) {
11062 /* if this is remateriazable */
11063 if (AOP_TYPE(left) == AOP_IMMD)
11064 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11065 else { /* we need to get it byte by byte */
11066 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11067 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11068 if (options.model == MODEL_FLAT24)
11070 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11074 /* so dptr know contains the address */
11075 pic16_freeAsmop(left,NULL,ic,TRUE);
11076 pic16_aopOp(result,ic,FALSE);
11078 /* if bit then unpack */
11079 if (IS_BITFIELD(retype))
11080 genUnpackBits(result,left,"dptr",CPOINTER);
11082 size = AOP_SIZE(result);
11086 pic16_emitcode("clr","a");
11087 pic16_emitcode("movc","a,@a+dptr");
11088 pic16_aopPut(AOP(result),"a",offset++);
11090 pic16_emitcode("inc","dptr");
11094 pic16_freeAsmop(result,NULL,ic,TRUE);
11099 /*-----------------------------------------------------------------*/
11100 /* genGenPointerGet - gget value from generic pointer space */
11101 /*-----------------------------------------------------------------*/
11102 static void genGenPointerGet (operand *left,
11103 operand *result, iCode *ic)
11105 int size, offset, lit;
11106 sym_link *retype = getSpec(operandType(result));
11108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11109 pic16_aopOp(left,ic,FALSE);
11110 pic16_aopOp(result,ic,FALSE);
11111 size = AOP_SIZE(result);
11113 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11115 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11117 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11118 // load FSR0 from immediate
11119 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11121 // pic16_loadFSR0( left );
11126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11128 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11135 else { /* we need to get it byte by byte */
11136 // set up FSR0 with address from left
11137 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11138 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11144 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11146 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11153 /* if bit then unpack */
11154 if (IS_BITFIELD(retype))
11155 genUnpackBits(result,left,"BAD",GPOINTER);
11158 pic16_freeAsmop(left,NULL,ic,TRUE);
11159 pic16_freeAsmop(result,NULL,ic,TRUE);
11165 /*-----------------------------------------------------------------*/
11166 /* genGenPointerGet - gget value from generic pointer space */
11167 /*-----------------------------------------------------------------*/
11168 static void genGenPointerGet (operand *left,
11169 operand *result, iCode *ic)
11171 int size, offset, lit;
11172 sym_link *letype = getSpec(operandType(left));
11174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11175 pic16_aopOp(left,ic,FALSE);
11176 pic16_aopOp(result,ic,TRUE);
11177 size = AOP_SIZE(result);
11179 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11181 /* if bit then unpack */
11182 if (IS_BITFIELD(letype)) {
11183 genUnpackBits(result,left,"BAD",GPOINTER);
11187 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11189 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11190 // load FSR0 from immediate
11191 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11193 werror(W_POSSBUG2, __FILE__, __LINE__);
11198 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11200 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11207 } else { /* we need to get it byte by byte */
11209 /* set up WREG:PRODL:FSR0L with address from left */
11210 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11211 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11212 pic16_mov2w(AOP(left), 2);
11213 pic16_callGenericPointerRW(0, size);
11215 assignResultValue(result, 1);
11221 pic16_freeAsmop(left,NULL,ic,TRUE);
11222 pic16_freeAsmop(result,NULL,ic,TRUE);
11225 /*-----------------------------------------------------------------*/
11226 /* genConstPointerGet - get value from const generic pointer space */
11227 /*-----------------------------------------------------------------*/
11228 static void genConstPointerGet (operand *left,
11229 operand *result, iCode *ic)
11231 //sym_link *retype = getSpec(operandType(result));
11232 // symbol *albl = newiTempLabel(NULL); // patch 15
11233 // symbol *blbl = newiTempLabel(NULL); //
11234 // PIC_OPCODE poc; // patch 15
11238 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11239 pic16_aopOp(left,ic,FALSE);
11240 pic16_aopOp(result,ic,TRUE);
11241 size = AOP_SIZE(result);
11243 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11245 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11247 // set up table pointer
11248 if( (AOP_TYPE(left) == AOP_PCODE)
11249 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11250 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11252 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11253 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11254 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11255 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11256 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11257 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11259 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11260 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11261 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11265 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11266 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11270 pic16_freeAsmop(left,NULL,ic,TRUE);
11271 pic16_freeAsmop(result,NULL,ic,TRUE);
11275 /*-----------------------------------------------------------------*/
11276 /* genPointerGet - generate code for pointer get */
11277 /*-----------------------------------------------------------------*/
11278 static void genPointerGet (iCode *ic)
11280 operand *left, *result ;
11281 sym_link *type, *etype;
11286 left = IC_LEFT(ic);
11287 result = IC_RESULT(ic) ;
11289 /* depending on the type of pointer we need to
11290 move it to the correct pointer register */
11291 type = operandType(left);
11292 etype = getSpec(type);
11295 if (IS_PTR_CONST(type))
11297 if (IS_CODEPTR(type))
11299 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11301 /* if left is of type of pointer then it is simple */
11302 if (IS_PTR(type) && !IS_FUNC(type->next))
11303 p_type = DCL_TYPE(type);
11305 /* we have to go by the storage class */
11306 p_type = PTR_TYPE(SPEC_OCLS(etype));
11308 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11310 if (SPEC_OCLS(etype)->codesp ) {
11311 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11312 //p_type = CPOINTER ;
11314 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11315 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11316 /*p_type = FPOINTER ;*/
11318 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11319 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11320 /* p_type = PPOINTER; */
11322 if (SPEC_OCLS(etype) == idata ) {
11323 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11324 /* p_type = IPOINTER; */
11326 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11327 /* p_type = POINTER ; */
11331 /* now that we have the pointer type we assign
11332 the pointer values */
11337 genNearPointerGet (left,result,ic);
11341 genPagedPointerGet(left,result,ic);
11345 /* PICs do not support FAR pointers... */
11346 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11348 genFarPointerGet (left,result,ic);
11353 genConstPointerGet (left,result,ic);
11354 //pic16_emitcodePointerGet (left,result,ic);
11359 if (IS_PTR_CONST(type))
11360 genConstPointerGet (left,result,ic);
11363 genGenPointerGet (left,result,ic);
11367 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11368 "genPointerGet: illegal pointer type");
11373 /*-----------------------------------------------------------------*/
11374 /* genPackBits - generates code for packed bit storage */
11375 /*-----------------------------------------------------------------*/
11376 static void genPackBits (sym_link *etype , operand *result,
11378 char *rname, int p_type)
11384 int shifted_and_masked = 0;
11385 unsigned long lit = (unsigned long)-1;
11388 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11389 blen = SPEC_BLEN(etype);
11390 bstr = SPEC_BSTR(etype);
11392 retype = getSpec(operandType(right));
11394 if(AOP_TYPE(right) == AOP_LIT) {
11395 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11397 if((blen == 1) && (bstr < 8)) {
11398 /* it is a single bit, so use the appropriate bit instructions */
11400 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11402 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11403 /* workaround to reduce the extra lfsr instruction */
11405 pic16_emitpcode(POC_BSF,
11406 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11408 pic16_emitpcode(POC_BCF,
11409 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11412 if (PIC_IS_DATA_PTR(operandType(result))) {
11413 pic16_loadFSR0(result, 0);
11414 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11415 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11417 /* get old value */
11418 pic16_derefPtr (result, p_type, 0, NULL);
11419 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11420 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11421 /* write back new value */
11422 pic16_derefPtr (result, p_type, 1, NULL);
11428 /* IORLW below is more efficient */
11429 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11430 lit = (lit & ((1UL << blen) - 1)) << bstr;
11431 shifted_and_masked = 1;
11434 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11435 && IS_BITFIELD(retype)
11436 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11440 rblen = SPEC_BLEN( retype );
11441 rbstr = SPEC_BSTR( retype );
11443 if(IS_BITFIELD(etype)) {
11444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11445 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11447 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11450 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11452 if(IS_BITFIELD(etype)) {
11453 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11455 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11458 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11462 /* move right to W */
11463 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11466 /* if the bit length is less than or */
11467 /* it exactly fits a byte then */
11468 if((shCnt=SPEC_BSTR(etype))
11469 || SPEC_BLEN(etype) <= 8 ) {
11470 int fsr0_setup = 0;
11472 if (blen != 8 || bstr != 0) {
11473 // we need to combine the value with the old value
11474 if(!shifted_and_masked)
11476 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11478 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11479 SPEC_BSTR(etype), SPEC_BLEN(etype));
11481 /* shift left acc, do NOT mask the result again */
11484 /* using PRODH as a temporary register here */
11485 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11488 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11489 || IS_DIRECT(result)) {
11490 /* access symbol directly */
11491 pic16_mov2w (AOP(result), 0);
11493 /* get old value */
11494 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11497 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11498 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11499 (unsigned char)(0xff >> (8-bstr))) ));
11500 if (!shifted_and_masked) {
11501 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11503 /* We have the shifted and masked (literal) right value in `lit' */
11505 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11507 } // if (blen != 8 || bstr != 0)
11509 /* write new value back */
11510 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11511 || IS_DIRECT(result)) {
11512 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11514 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11523 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11524 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11529 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11530 rLen = SPEC_BLEN(etype)-8;
11532 /* now generate for lengths greater than one byte */
11536 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11542 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11548 pic16_emitcode("movx","@dptr,a");
11553 DEBUGpic16_emitcode(";lcall","__gptrput");
11561 pic16_mov2w(AOP(right), offset++);
11564 /* last last was not complete */
11566 /* save the byte & read byte */
11569 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11570 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11575 pic16_emitcode ("mov","b,a");
11576 pic16_emitcode("movx","a,@dptr");
11580 pic16_emitcode ("push","b");
11581 pic16_emitcode ("push","acc");
11582 pic16_emitcode ("lcall","__gptrget");
11583 pic16_emitcode ("pop","b");
11589 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11590 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11591 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11592 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11593 // pic16_emitcode ("orl","a,b");
11596 // if (p_type == GPOINTER)
11597 // pic16_emitcode("pop","b");
11602 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11603 // pic16_emitcode("mov","@%s,a",rname);
11607 pic16_emitcode("movx","@dptr,a");
11611 DEBUGpic16_emitcode(";lcall","__gptrput");
11618 // pic16_freeAsmop(right, NULL, ic, TRUE);
11621 /*-----------------------------------------------------------------*/
11622 /* genDataPointerSet - remat pointer to data space */
11623 /*-----------------------------------------------------------------*/
11624 static void genDataPointerSet(operand *right,
11628 int size, offset = 0, resoffset=0 ;
11630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11631 pic16_aopOp(right,ic,FALSE);
11633 size = AOP_SIZE(right);
11635 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11638 if ( AOP_TYPE(result) == AOP_PCODE) {
11639 fprintf(stderr,"genDataPointerSet %s, %d\n",
11640 AOP(result)->aopu.pcop->name,
11641 (AOP(result)->aopu.pcop->type == PO_DIR)?
11642 PCOR(AOP(result)->aopu.pcop)->instance:
11643 PCOI(AOP(result)->aopu.pcop)->offset);
11647 if(AOP(result)->aopu.pcop->type == PO_DIR)
11648 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11651 if (AOP_TYPE(right) == AOP_LIT) {
11654 if(!IS_FLOAT(operandType( right )))
11655 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11658 unsigned long lit_int;
11662 /* take care if literal is a float */
11663 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11664 lit = info.lit_int;
11666 lit = lit >> (8*offset);
11667 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11669 pic16_mov2w(AOP(right), offset);
11670 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11676 pic16_freeAsmop(right,NULL,ic,TRUE);
11681 /*-----------------------------------------------------------------*/
11682 /* genNearPointerSet - pic16_emitcode for near pointer put */
11683 /*-----------------------------------------------------------------*/
11684 static void genNearPointerSet (operand *right,
11690 sym_link *ptype = operandType(result);
11691 sym_link *resetype;
11693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11694 retype= getSpec(operandType(right));
11695 resetype = getSpec(operandType(result));
11697 pic16_aopOp(result,ic,FALSE);
11699 /* if the result is rematerializable &
11700 * in data space & not a bit variable */
11702 /* and result is not a bit variable */
11703 if (AOP_TYPE(result) == AOP_PCODE
11704 // && AOP_TYPE(result) == AOP_IMMD
11705 && DCL_TYPE(ptype) == POINTER
11706 && !IS_BITFIELD(retype)
11707 && !IS_BITFIELD(resetype)) {
11709 genDataPointerSet (right,result,ic);
11710 pic16_freeAsmop(result,NULL,ic,TRUE);
11714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11715 pic16_aopOp(right,ic,FALSE);
11716 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11718 /* if bitfield then unpack the bits */
11719 if (IS_BITFIELD(resetype)) {
11720 genPackBits (resetype, result, right, NULL, POINTER);
11722 /* we have can just get the values */
11723 int size = AOP_SIZE(right);
11726 pic16_loadFSR0(result, 0);
11728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11730 if (AOP_TYPE(right) == AOP_LIT) {
11731 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11733 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11735 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11737 } else { // no literal
11739 pic16_emitpcode(POC_MOVFF,
11740 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11741 pic16_popCopyReg(&pic16_pc_postinc0)));
11743 pic16_emitpcode(POC_MOVFF,
11744 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11745 pic16_popCopyReg(&pic16_pc_indf0)));
11753 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11754 /* now some housekeeping stuff */
11756 /* we had to allocate for this iCode */
11757 pic16_freeAsmop(NULL,aop,ic,TRUE);
11759 /* we did not allocate which means left
11760 * already in a pointer register, then
11761 * if size > 0 && this could be used again
11762 * we have to point it back to where it
11764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11765 if (AOP_SIZE(right) > 1
11766 && !OP_SYMBOL(result)->remat
11767 && ( OP_SYMBOL(result)->liveTo > ic->seq
11770 int size = AOP_SIZE(right) - 1;
11773 pic16_emitcode("decf","fsr0,f");
11774 //pic16_emitcode("dec","%s",rname);
11778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11781 pic16_freeAsmop(right,NULL,ic,TRUE);
11782 pic16_freeAsmop(result,NULL,ic,TRUE);
11785 /*-----------------------------------------------------------------*/
11786 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11787 /*-----------------------------------------------------------------*/
11788 static void genPagedPointerSet (operand *right,
11793 regs *preg = NULL ;
11797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11799 retype= getSpec(operandType(right));
11801 pic16_aopOp(result,ic,FALSE);
11803 /* if the value is already in a pointer register
11804 then don't need anything more */
11805 if (!AOP_INPREG(AOP(result))) {
11806 /* otherwise get a free pointer register */
11808 preg = getFreePtr(ic,&aop,FALSE);
11809 pic16_emitcode("mov","%s,%s",
11811 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11812 rname = preg->name ;
11814 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11816 pic16_freeAsmop(result,NULL,ic,TRUE);
11817 pic16_aopOp (right,ic,FALSE);
11819 /* if bitfield then unpack the bits */
11820 if (IS_BITFIELD(retype))
11821 genPackBits (retype,result,right,rname,PPOINTER);
11823 /* we have can just get the values */
11824 int size = AOP_SIZE(right);
11828 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11831 pic16_emitcode("movx","@%s,a",rname);
11834 pic16_emitcode("inc","%s",rname);
11840 /* now some housekeeping stuff */
11842 /* we had to allocate for this iCode */
11843 pic16_freeAsmop(NULL,aop,ic,TRUE);
11845 /* we did not allocate which means left
11846 already in a pointer register, then
11847 if size > 0 && this could be used again
11848 we have to point it back to where it
11850 if (AOP_SIZE(right) > 1 &&
11851 !OP_SYMBOL(result)->remat &&
11852 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11854 int size = AOP_SIZE(right) - 1;
11856 pic16_emitcode("dec","%s",rname);
11861 pic16_freeAsmop(right,NULL,ic,TRUE);
11867 /* This code is not adjusted to PIC16 and fails utterly...
11868 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11870 /*-----------------------------------------------------------------*/
11871 /* genFarPointerSet - set value from far space */
11872 /*-----------------------------------------------------------------*/
11873 static void genFarPointerSet (operand *right,
11874 operand *result, iCode *ic)
11877 sym_link *retype = getSpec(operandType(right));
11879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11880 pic16_aopOp(result,ic,FALSE);
11882 /* if the operand is already in dptr
11883 then we do nothing else we move the value to dptr */
11884 if (AOP_TYPE(result) != AOP_STR) {
11885 /* if this is remateriazable */
11886 if (AOP_TYPE(result) == AOP_IMMD)
11887 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11888 else { /* we need to get it byte by byte */
11889 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11890 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11891 if (options.model == MODEL_FLAT24)
11893 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11897 /* so dptr know contains the address */
11898 pic16_freeAsmop(result,NULL,ic,TRUE);
11899 pic16_aopOp(right,ic,FALSE);
11901 /* if bit then unpack */
11902 if (IS_BITFIELD(retype))
11903 genPackBits(retype,result,right,"dptr",FPOINTER);
11905 size = AOP_SIZE(right);
11909 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11911 pic16_emitcode("movx","@dptr,a");
11913 pic16_emitcode("inc","dptr");
11917 pic16_freeAsmop(right,NULL,ic,TRUE);
11921 /*-----------------------------------------------------------------*/
11922 /* genGenPointerSet - set value from generic pointer space */
11923 /*-----------------------------------------------------------------*/
11925 static void genGenPointerSet (operand *right,
11926 operand *result, iCode *ic)
11928 int i, size, offset, lit;
11929 sym_link *retype = getSpec(operandType(right));
11931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11933 pic16_aopOp(result,ic,FALSE);
11934 pic16_aopOp(right,ic,FALSE);
11935 size = AOP_SIZE(right);
11938 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11940 /* if the operand is already in dptr
11941 then we do nothing else we move the value to dptr */
11942 if (AOP_TYPE(result) != AOP_STR) {
11943 /* if this is remateriazable */
11944 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11945 // WARNING: anythig until "else" is untested!
11946 if (AOP_TYPE(result) == AOP_IMMD) {
11947 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11948 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11949 // load FSR0 from immediate
11950 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11954 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11956 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11962 else { /* we need to get it byte by byte */
11963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11964 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11966 // set up FSR0 with address of result
11967 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11968 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11970 /* hack hack! see if this the FSR. If so don't load W */
11971 if(AOP_TYPE(right) != AOP_ACC) {
11973 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11975 if(AOP_TYPE(right) == AOP_LIT)
11978 // note: pic16_popGet handles sign extension
11979 for(i=0;i<size;i++) {
11980 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11982 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11984 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11989 for(i=0;i<size;i++) {
11991 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11992 pic16_popCopyReg(&pic16_pc_postinc0)));
11994 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11995 pic16_popCopyReg(&pic16_pc_indf0)));
12001 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12002 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12004 } // if (AOP_TYPE(result) != AOP_IMMD)
12006 } // if (AOP_TYPE(result) != AOP_STR)
12007 /* so dptr know contains the address */
12010 /* if bit then unpack */
12011 if (IS_BITFIELD(retype))
12012 genPackBits(retype,result,right,"dptr",GPOINTER);
12014 size = AOP_SIZE(right);
12017 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12019 // set up FSR0 with address of result
12020 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12021 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12024 if (AOP_TYPE(right) == AOP_LIT) {
12025 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12027 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12029 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12031 } else { // no literal
12033 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12035 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12043 pic16_freeAsmop(right,NULL,ic,TRUE);
12044 pic16_freeAsmop(result,NULL,ic,TRUE);
12048 static void genGenPointerSet (operand *right,
12049 operand *result, iCode *ic)
12052 sym_link *retype = getSpec(operandType(result));
12054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12056 pic16_aopOp(result,ic,FALSE);
12057 pic16_aopOp(right,ic,FALSE);
12058 size = AOP_SIZE(right);
12060 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12063 /* if bit then unpack */
12064 if (IS_BITFIELD(retype)) {
12065 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12066 genPackBits(retype,result,right,"dptr",GPOINTER);
12070 size = AOP_SIZE(right);
12072 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12075 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12077 /* value of right+0 is placed on stack, which will be retrieved
12078 * by the support function thus restoring the stack. The important
12079 * thing is that there is no need to manually restore stack pointer
12081 pushaop(AOP(right), 0);
12082 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12083 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12084 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12085 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12087 /* load address to write to in WREG:FSR0H:FSR0L */
12088 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12089 pic16_popCopyReg(&pic16_pc_fsr0l)));
12090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12091 pic16_popCopyReg(&pic16_pc_prodl)));
12092 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12094 pic16_callGenericPointerRW(1, size);
12097 pic16_freeAsmop(right,NULL,ic,TRUE);
12098 pic16_freeAsmop(result,NULL,ic,TRUE);
12101 /*-----------------------------------------------------------------*/
12102 /* genPointerSet - stores the value into a pointer location */
12103 /*-----------------------------------------------------------------*/
12104 static void genPointerSet (iCode *ic)
12106 operand *right, *result ;
12107 sym_link *type, *etype;
12112 right = IC_RIGHT(ic);
12113 result = IC_RESULT(ic) ;
12115 /* depending on the type of pointer we need to
12116 move it to the correct pointer register */
12117 type = operandType(result);
12118 etype = getSpec(type);
12120 /* if left is of type of pointer then it is simple */
12121 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12122 p_type = DCL_TYPE(type);
12125 /* we have to go by the storage class */
12126 p_type = PTR_TYPE(SPEC_OCLS(etype));
12128 /* if (SPEC_OCLS(etype)->codesp ) { */
12129 /* p_type = CPOINTER ; */
12132 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12133 /* p_type = FPOINTER ; */
12135 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12136 /* p_type = PPOINTER ; */
12138 /* if (SPEC_OCLS(etype) == idata ) */
12139 /* p_type = IPOINTER ; */
12141 /* p_type = POINTER ; */
12144 /* now that we have the pointer type we assign
12145 the pointer values */
12150 genNearPointerSet (right,result,ic);
12154 genPagedPointerSet (right,result,ic);
12158 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12160 genFarPointerSet (right,result,ic);
12165 genGenPointerSet (right,result,ic);
12169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12170 "genPointerSet: illegal pointer type");
12174 /*-----------------------------------------------------------------*/
12175 /* genIfx - generate code for Ifx statement */
12176 /*-----------------------------------------------------------------*/
12177 static void genIfx (iCode *ic, iCode *popIc)
12179 operand *cond = IC_COND(ic);
12184 pic16_aopOp(cond,ic,FALSE);
12186 /* get the value into acc */
12187 if (AOP_TYPE(cond) != AOP_CRY)
12188 pic16_toBoolean(cond);
12191 /* the result is now in the accumulator */
12192 pic16_freeAsmop(cond,NULL,ic,TRUE);
12194 /* if there was something to be popped then do it */
12198 /* if the condition is a bit variable */
12199 if (isbit && IS_ITEMP(cond) &&
12201 genIfxJump(ic,"c");
12202 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12204 if (isbit && !IS_ITEMP(cond))
12205 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12207 genIfxJump(ic,"a");
12212 /*-----------------------------------------------------------------*/
12213 /* genAddrOf - generates code for address of */
12214 /*-----------------------------------------------------------------*/
12215 static void genAddrOf (iCode *ic)
12217 operand *result, *left;
12219 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12220 pCodeOp *pcop0, *pcop1, *pcop2;
12224 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12226 sym = OP_SYMBOL( IC_LEFT(ic) );
12229 /* get address of symbol on stack */
12230 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12232 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12233 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12236 // operands on stack are accessible via "FSR2 + index" with index
12237 // starting at 2 for arguments and growing from 0 downwards for
12238 // local variables (index == 0 is not assigned so we add one here)
12240 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12243 assert (soffs < 0);
12247 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12248 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12249 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12250 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12251 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12252 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12253 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12259 // if(pic16_debug_verbose) {
12260 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12261 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12264 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12265 size = AOP_SIZE(IC_RESULT(ic));
12267 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12268 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12269 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12272 pic16_emitpcode(POC_MOVLW, pcop0);
12273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12274 pic16_emitpcode(POC_MOVLW, pcop1);
12275 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12276 pic16_emitpcode(POC_MOVLW, pcop2);
12277 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12280 pic16_emitpcode(POC_MOVLW, pcop0);
12281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12282 pic16_emitpcode(POC_MOVLW, pcop1);
12283 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12285 pic16_emitpcode(POC_MOVLW, pcop0);
12286 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12289 pic16_freeAsmop(left, NULL, ic, FALSE);
12291 pic16_freeAsmop(result,NULL,ic,TRUE);
12296 /*-----------------------------------------------------------------*/
12297 /* genFarFarAssign - assignment when both are in far space */
12298 /*-----------------------------------------------------------------*/
12299 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12301 int size = AOP_SIZE(right);
12304 /* first push the right side on to the stack */
12306 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12308 pic16_emitcode ("push","acc");
12311 pic16_freeAsmop(right,NULL,ic,FALSE);
12312 /* now assign DPTR to result */
12313 pic16_aopOp(result,ic,FALSE);
12314 size = AOP_SIZE(result);
12316 pic16_emitcode ("pop","acc");
12317 pic16_aopPut(AOP(result),"a",--offset);
12319 pic16_freeAsmop(result,NULL,ic,FALSE);
12324 /*-----------------------------------------------------------------*/
12325 /* genAssign - generate code for assignment */
12326 /*-----------------------------------------------------------------*/
12327 static void genAssign (iCode *ic)
12329 operand *result, *right;
12330 sym_link *restype, *rtype;
12331 int size, offset,know_W;
12332 unsigned long lit = 0L;
12334 result = IC_RESULT(ic);
12335 right = IC_RIGHT(ic) ;
12339 /* if they are the same */
12340 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12343 /* reversed order operands are aopOp'ed so that result operand
12344 * is effective in case right is a stack symbol. This maneauver
12345 * allows to use the _G.resDirect flag later */
12346 pic16_aopOp(result,ic,TRUE);
12347 pic16_aopOp(right,ic,FALSE);
12349 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12351 /* if they are the same registers */
12352 if (pic16_sameRegs(AOP(right),AOP(result)))
12355 /* if the result is a bit */
12356 if (AOP_TYPE(result) == AOP_CRY) {
12357 /* if the right size is a literal then
12358 we know what the value is */
12359 if (AOP_TYPE(right) == AOP_LIT) {
12361 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12362 pic16_popGet(AOP(result),0));
12364 if (((int) operandLitValue(right)))
12365 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12366 AOP(result)->aopu.aop_dir,
12367 AOP(result)->aopu.aop_dir);
12369 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12370 AOP(result)->aopu.aop_dir,
12371 AOP(result)->aopu.aop_dir);
12376 /* the right is also a bit variable */
12377 if (AOP_TYPE(right) == AOP_CRY) {
12378 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12379 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12380 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12385 /* we need to or */
12386 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12387 pic16_toBoolean(right);
12389 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12390 //pic16_aopPut(AOP(result),"a",0);
12394 /* bit variables done */
12396 size = AOP_SIZE(result);
12399 /* bit variables done */
12401 size = AOP_SIZE(result);
12402 restype = operandType(result);
12403 rtype = operandType(right);
12406 if(AOP_TYPE(right) == AOP_LIT) {
12407 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12409 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12411 /* patch tag for literals that are cast to pointers */
12412 if (IS_CODEPTR(restype)) {
12413 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12414 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12416 if (IS_GENPTR(restype))
12418 if (IS_CODEPTR(rtype)) {
12419 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12420 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12421 } else if (PIC_IS_DATA_PTR(rtype)) {
12422 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12423 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12424 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12425 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12426 } else if (IS_PTR(rtype)) {
12427 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12428 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12434 unsigned long lit_int;
12439 if(IS_FIXED16X16(operandType(right))) {
12440 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12442 /* take care if literal is a float */
12443 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12444 lit = info.lit_int;
12449 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12450 // sizeof(unsigned long int), sizeof(float));
12453 if (AOP_TYPE(right) == AOP_REG) {
12454 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12456 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12461 /* when do we have to read the program memory?
12462 * - if right itself is a symbol in code space
12463 * (we don't care what it points to if it's a pointer)
12464 * - AND right is not a function (we would want its address)
12466 if(AOP_TYPE(right) != AOP_LIT
12467 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12468 && !IS_FUNC(OP_SYM_TYPE(right))
12469 && !IS_ITEMP(right)) {
12471 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12472 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12474 // set up table pointer
12475 if(is_LitOp(right)) {
12476 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12477 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12478 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12479 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12480 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12481 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12482 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12484 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12485 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12486 pic16_popCopyReg(&pic16_pc_tblptrl)));
12487 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12488 pic16_popCopyReg(&pic16_pc_tblptrh)));
12489 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12490 pic16_popCopyReg(&pic16_pc_tblptru)));
12493 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12494 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12496 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12497 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12498 pic16_popGet(AOP(result),offset)));
12502 /* FIXME: for pointers we need to extend differently (according
12503 * to pointer type DATA/CODE/EEPROM/... :*/
12504 size = getSize(OP_SYM_TYPE(right));
12505 if(AOP_SIZE(result) > size) {
12506 size = AOP_SIZE(result) - size;
12508 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12516 /* VR - What is this?! */
12517 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12518 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12520 if(aopIdx(AOP(result),0) == 4) {
12521 /* this is a workaround to save value of right into wreg too,
12522 * value of wreg is going to be used later */
12523 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12524 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12525 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12529 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12535 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12536 if(AOP_TYPE(right) == AOP_LIT) {
12538 if(know_W != (lit&0xff))
12539 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12541 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12543 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12547 } else if (AOP_TYPE(right) == AOP_CRY) {
12548 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12550 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12551 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12552 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12554 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12555 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12556 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12560 if(!_G.resDirect) { /* use this aopForSym feature */
12561 if(AOP_TYPE(result) == AOP_ACC) {
12562 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12564 if(AOP_TYPE(right) == AOP_ACC) {
12565 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12567 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12576 pic16_freeAsmop (right,NULL,ic,FALSE);
12577 pic16_freeAsmop (result,NULL,ic,TRUE);
12580 /*-----------------------------------------------------------------*/
12581 /* genJumpTab - generates code for jump table */
12582 /*-----------------------------------------------------------------*/
12583 static void genJumpTab (iCode *ic)
12588 pCodeOp *jt_offs_hi;
12593 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12594 /* get the condition into accumulator */
12595 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12597 /* multiply by three */
12598 pic16_emitcode("add","a,acc");
12599 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12601 jtab = newiTempLabel(NULL);
12602 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12603 pic16_emitcode("jmp","@a+dptr");
12604 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12607 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12608 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12610 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12611 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12612 pic16_emitpLabel(jtab->key);
12616 jt_offs = pic16_popGetTempReg(0);
12617 jt_offs_hi = pic16_popGetTempReg(1);
12618 jt_label = pic16_popGetLabel (jtab->key);
12619 //fprintf (stderr, "Creating jump table...\n");
12621 // calculate offset into jump table (idx * sizeof (GOTO))
12622 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12623 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12624 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12625 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12626 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12627 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12628 pic16_emitpcode(POC_MOVWF , jt_offs);
12630 // prepare PCLATx (set to first entry in jump table)
12631 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12632 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12633 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12634 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12635 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12637 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12638 pic16_emitpcode(POC_ADDWF , jt_offs);
12639 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12640 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12642 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12644 // release temporaries and prepare jump into table (new PCL --> WREG)
12645 pic16_emitpcode(POC_MOVFW , jt_offs);
12646 pic16_popReleaseTempReg (jt_offs_hi, 1);
12647 pic16_popReleaseTempReg (jt_offs, 0);
12649 // jump into the table
12650 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12652 pic16_emitpLabelFORCE(jtab->key);
12655 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12656 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12658 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12659 /* now generate the jump labels */
12660 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12661 jtab = setNextItem(IC_JTLABELS(ic))) {
12662 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12666 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12670 /*-----------------------------------------------------------------*/
12671 /* genMixedOperation - gen code for operators between mixed types */
12672 /*-----------------------------------------------------------------*/
12674 TSD - Written for the PIC port - but this unfortunately is buggy.
12675 This routine is good in that it is able to efficiently promote
12676 types to different (larger) sizes. Unfortunately, the temporary
12677 variables that are optimized out by this routine are sometimes
12678 used in other places. So until I know how to really parse the
12679 iCode tree, I'm going to not be using this routine :(.
12681 static int genMixedOperation (iCode *ic)
12684 operand *result = IC_RESULT(ic);
12685 sym_link *ctype = operandType(IC_LEFT(ic));
12686 operand *right = IC_RIGHT(ic);
12692 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12694 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12700 nextright = IC_RIGHT(nextic);
12701 nextleft = IC_LEFT(nextic);
12702 nextresult = IC_RESULT(nextic);
12704 pic16_aopOp(right,ic,FALSE);
12705 pic16_aopOp(result,ic,FALSE);
12706 pic16_aopOp(nextright, nextic, FALSE);
12707 pic16_aopOp(nextleft, nextic, FALSE);
12708 pic16_aopOp(nextresult, nextic, FALSE);
12710 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12712 operand *t = right;
12716 pic16_emitcode(";remove right +","");
12718 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12720 operand *t = right;
12724 pic16_emitcode(";remove left +","");
12728 big = AOP_SIZE(nextleft);
12729 small = AOP_SIZE(nextright);
12731 switch(nextic->op) {
12734 pic16_emitcode(";optimize a +","");
12735 /* if unsigned or not an integral type */
12736 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12737 pic16_emitcode(";add a bit to something","");
12740 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12742 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12743 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12744 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12746 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12754 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12755 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12756 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12759 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12761 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12762 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12763 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12764 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12768 pic16_emitcode("rlf","known_zero,w");
12775 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12776 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12777 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12779 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12789 pic16_freeAsmop(right,NULL,ic,TRUE);
12790 pic16_freeAsmop(result,NULL,ic,TRUE);
12791 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12792 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12794 nextic->generated = 1;
12801 /*-----------------------------------------------------------------*/
12802 /* genCast - gen code for casting */
12803 /*-----------------------------------------------------------------*/
12804 static void genCast (iCode *ic)
12806 operand *result = IC_RESULT(ic);
12807 sym_link *ctype = operandType(IC_LEFT(ic));
12808 sym_link *rtype = operandType(IC_RIGHT(ic));
12809 sym_link *restype = operandType(IC_RESULT(ic));
12810 operand *right = IC_RIGHT(ic);
12816 /* if they are equivalent then do nothing */
12817 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12820 pic16_aopOp(result,ic,FALSE);
12821 pic16_aopOp(right,ic,FALSE) ;
12823 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12826 /* if the result is a bit */
12827 if (AOP_TYPE(result) == AOP_CRY) {
12829 /* if the right size is a literal then
12830 * we know what the value is */
12831 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12833 if (AOP_TYPE(right) == AOP_LIT) {
12834 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12835 pic16_popGet(AOP(result),0));
12837 if (((int) operandLitValue(right)))
12838 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12839 AOP(result)->aopu.aop_dir,
12840 AOP(result)->aopu.aop_dir);
12842 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12843 AOP(result)->aopu.aop_dir,
12844 AOP(result)->aopu.aop_dir);
12848 /* the right is also a bit variable */
12849 if (AOP_TYPE(right) == AOP_CRY) {
12851 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12853 pic16_emitcode("clrc","");
12854 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12855 AOP(right)->aopu.aop_dir,
12856 AOP(right)->aopu.aop_dir);
12857 pic16_aopPut(AOP(result),"c",0);
12861 /* we need to or */
12862 if (AOP_TYPE(right) == AOP_REG) {
12863 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12864 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12865 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12867 pic16_toBoolean(right);
12868 pic16_aopPut(AOP(result),"a",0);
12872 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12875 size = AOP_SIZE(result);
12877 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12880 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12881 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12884 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12889 if(IS_BITFIELD(getSpec(restype))
12890 && IS_BITFIELD(getSpec(rtype))) {
12891 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12894 /* port from pic14 to cope with generic pointers */
12895 if (PIC_IS_TAGGED(restype))
12897 operand *result = IC_RESULT(ic);
12898 //operand *left = IC_LEFT(ic);
12899 operand *right = IC_RIGHT(ic);
12902 /* copy common part */
12903 int max, size = AOP_SIZE(result);
12904 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12905 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12910 pic16_mov2w (AOP(right), size);
12911 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12914 /* upcast into generic pointer type? */
12915 if (IS_GENPTR(restype)
12916 && !PIC_IS_TAGGED(rtype)
12917 && (AOP_SIZE(result) > max))
12919 /* determine appropriate tag for right */
12920 if (PIC_IS_DATA_PTR(rtype))
12921 tag = GPTR_TAG_DATA;
12922 else if (IS_CODEPTR(rtype))
12923 tag = GPTR_TAG_CODE;
12924 else if (PIC_IS_DATA_PTR(ctype)) {
12925 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12926 tag = GPTR_TAG_DATA;
12927 } else if (IS_CODEPTR(ctype)) {
12928 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12929 tag = GPTR_TAG_CODE;
12930 } else if (IS_PTR(rtype)) {
12931 PERFORM_ONCE(weirdcast,
12932 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12934 tag = GPTR_TAG_DATA;
12936 PERFORM_ONCE(weirdcast,
12937 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12939 tag = GPTR_TAG_DATA;
12942 assert (AOP_SIZE(result) == 3);
12943 /* zero-extend address... */
12944 for (size = max; size < AOP_SIZE(result)-1; size++)
12945 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12946 /* ...and add tag */
12947 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12948 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12949 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12950 for (size = max; size < AOP_SIZE(result)-1; size++)
12951 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12952 /* add __code tag */
12953 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12954 } else if (AOP_SIZE(result) > max) {
12955 /* extend non-pointers */
12956 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12957 pic16_addSign(result, max, 0);
12962 /* if they are the same size : or less */
12963 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12965 /* if they are in the same place */
12966 if (pic16_sameRegs(AOP(right),AOP(result)))
12969 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12971 if (IS_PTR_CONST(rtype))
12973 if (IS_CODEPTR(rtype))
12975 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12978 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12980 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12982 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12985 if(AOP_TYPE(right) == AOP_IMMD) {
12986 pCodeOp *pcop0, *pcop1, *pcop2;
12987 symbol *sym = OP_SYMBOL( right );
12989 size = AOP_SIZE(result);
12991 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12993 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12995 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12998 pic16_emitpcode(POC_MOVLW, pcop0);
12999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13000 pic16_emitpcode(POC_MOVLW, pcop1);
13001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13002 pic16_emitpcode(POC_MOVLW, pcop2);
13003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13006 pic16_emitpcode(POC_MOVLW, pcop0);
13007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13008 pic16_emitpcode(POC_MOVLW, pcop1);
13009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13011 pic16_emitpcode(POC_MOVLW, pcop0);
13012 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13016 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13017 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13018 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13019 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13021 if(AOP_SIZE(result) <2)
13022 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13024 /* if they in different places then copy */
13025 size = AOP_SIZE(result);
13028 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13029 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13036 /* if the result is of type pointer */
13037 if (IS_PTR(ctype)) {
13039 sym_link *type = operandType(right);
13040 sym_link *etype = getSpec(type);
13042 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13044 /* pointer to generic pointer */
13045 if (IS_GENPTR(ctype)) {
13049 p_type = DCL_TYPE(type);
13051 /* we have to go by the storage class */
13052 p_type = PTR_TYPE(SPEC_OCLS(etype));
13054 /* if (SPEC_OCLS(etype)->codesp ) */
13055 /* p_type = CPOINTER ; */
13057 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13058 /* p_type = FPOINTER ; */
13060 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13061 /* p_type = PPOINTER; */
13063 /* if (SPEC_OCLS(etype) == idata ) */
13064 /* p_type = IPOINTER ; */
13066 /* p_type = POINTER ; */
13069 /* the first two bytes are known */
13070 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13071 size = GPTRSIZE - 1;
13074 if(offset < AOP_SIZE(right)) {
13075 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13076 pic16_mov2f(AOP(result), AOP(right), offset);
13078 if ((AOP_TYPE(right) == AOP_PCODE) &&
13079 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13080 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13081 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13084 pic16_aopPut(AOP(result),
13085 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13090 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13093 /* the last byte depending on type */
13098 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13102 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13106 pic16_emitcode(";BUG!? ","%d",__LINE__);
13111 if (GPTRSIZE > AOP_SIZE(right)) {
13112 // assume __data pointer... THIS MIGHT BE WRONG!
13113 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13115 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13120 /* this should never happen */
13121 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13122 "got unknown pointer type");
13125 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13131 /* just copy the pointers */
13132 size = AOP_SIZE(result);
13135 pic16_aopPut(AOP(result),
13136 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13145 /* so we now know that the size of destination is greater
13146 than the size of the source.
13147 Now, if the next iCode is an operator then we might be
13148 able to optimize the operation without performing a cast.
13150 if(genMixedOperation(ic))
13153 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13155 /* we move to result for the size of source */
13156 size = AOP_SIZE(right);
13161 pic16_mov2f(AOP(result), AOP(right), offset);
13165 /* now depending on the sign of the destination */
13166 size = AOP_SIZE(result) - AOP_SIZE(right);
13167 /* if unsigned or not an integral type */
13168 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13170 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13172 /* we need to extend the sign :( */
13175 /* Save one instruction of casting char to int */
13176 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13177 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13178 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13180 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13183 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13185 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13187 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13190 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13195 pic16_freeAsmop(right,NULL,ic,TRUE);
13196 pic16_freeAsmop(result,NULL,ic,TRUE);
13200 /*-----------------------------------------------------------------*/
13201 /* genDjnz - generate decrement & jump if not zero instrucion */
13202 /*-----------------------------------------------------------------*/
13203 static int genDjnz (iCode *ic, iCode *ifx)
13205 symbol *lbl, *lbl1;
13206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13211 /* if the if condition has a false label
13212 then we cannot save */
13216 /* if the minus is not of the form
13218 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13219 !IS_OP_LITERAL(IC_RIGHT(ic)))
13222 if (operandLitValue(IC_RIGHT(ic)) != 1)
13225 /* if the size of this greater than one then no
13227 if (getSize(operandType(IC_RESULT(ic))) > 1)
13230 /* otherwise we can save BIG */
13231 lbl = newiTempLabel(NULL);
13232 lbl1= newiTempLabel(NULL);
13234 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13236 if (IS_AOP_PREG(IC_RESULT(ic))) {
13237 pic16_emitcode("dec","%s",
13238 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13239 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13240 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13244 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13245 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13247 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13248 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13252 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13253 ifx->generated = 1;
13257 /*-----------------------------------------------------------------*/
13258 /* genReceive - generate code for a receive iCode */
13259 /*-----------------------------------------------------------------*/
13260 static void genReceive (iCode *ic)
13266 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13267 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13269 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13271 if (isOperandInFarSpace(IC_RESULT(ic))
13272 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13273 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13275 int size = getSize(operandType(IC_RESULT(ic)));
13276 int offset = pic16_fReturnSizePic - size;
13280 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13281 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13285 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13287 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13288 size = AOP_SIZE(IC_RESULT(ic));
13291 pic16_emitcode ("pop","acc");
13292 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13295 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13297 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13300 /* set pseudo stack pointer to where it should be - dw*/
13301 GpsuedoStkPtr = ic->parmBytes;
13303 /* setting GpsuedoStkPtr has side effects here: */
13304 assignResultValue(IC_RESULT(ic), 0);
13307 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13310 /*-----------------------------------------------------------------*/
13311 /* genDummyRead - generate code for dummy read of volatiles */
13312 /*-----------------------------------------------------------------*/
13314 genDummyRead (iCode * ic)
13320 if (op && IS_SYMOP(op)) {
13321 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13322 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13325 pic16_aopOp (op, ic, FALSE);
13326 for (i=0; i < AOP_SIZE(op); i++) {
13327 // may need to protect this from the peepholer -- this is not nice but works...
13328 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13329 pic16_mov2w (AOP(op),i);
13330 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13332 pic16_freeAsmop (op, NULL, ic, TRUE);
13334 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13338 /*-----------------------------------------------------------------*/
13339 /* genpic16Code - generate code for pic16 based controllers */
13340 /*-----------------------------------------------------------------*/
13342 * At this point, ralloc.c has gone through the iCode and attempted
13343 * to optimize in a way suitable for a PIC. Now we've got to generate
13344 * PIC instructions that correspond to the iCode.
13346 * Once the instructions are generated, we'll pass through both the
13347 * peep hole optimizer and the pCode optimizer.
13348 *-----------------------------------------------------------------*/
13350 void genpic16Code (iCode *lic)
13355 lineHead = lineCurr = NULL;
13357 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13358 pic16_addpBlock(pb);
13361 /* if debug information required */
13362 if (options.debug && currFunc) {
13364 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13369 for (ic = lic ; ic ; ic = ic->next ) {
13371 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13372 if ( cln != ic->lineno ) {
13373 if ( options.debug ) {
13374 debugFile->writeCLine (ic);
13377 if(!options.noCcodeInAsm) {
13378 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13379 printCLine(ic->filename, ic->lineno)));
13385 if(options.iCodeInAsm) {
13388 /* insert here code to print iCode as comment */
13389 l = Safe_strdup(printILine(ic));
13390 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13393 /* if the result is marked as
13394 * spilt and rematerializable or code for
13395 * this has already been generated then
13397 if (resultRemat(ic) || ic->generated )
13400 /* depending on the operation */
13419 /* IPOP happens only when trying to restore a
13420 * spilt live range, if there is an ifx statement
13421 * following this pop then the if statement might
13422 * be using some of the registers being popped which
13423 * would destroy the contents of the register so
13424 * we need to check for this condition and handle it */
13426 && ic->next->op == IFX
13427 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13428 genIfx (ic->next,ic);
13446 genEndFunction (ic);
13462 pic16_genPlus (ic) ;
13466 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13467 pic16_genMinus (ic);
13483 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13487 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13493 /* note these two are xlated by algebraic equivalence
13494 * during parsing SDCC.y */
13495 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13496 "got '>=' or '<=' shouldn't have come here");
13500 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13512 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13516 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13520 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13544 genRightShift (ic);
13547 case GET_VALUE_AT_ADDRESS:
13552 if (POINTER_SET(ic))
13579 addSet(&_G.sendSet,ic);
13582 case DUMMY_READ_VOLATILE:
13592 /* now we are ready to call the
13593 peep hole optimizer */
13594 if (!options.nopeep)
13595 peepHole (&lineHead);
13597 /* now do the actual printing */
13598 printLine (lineHead, codeOutFile);
13601 DFPRINTF((stderr,"printing pBlock\n\n"));
13602 pic16_printpBlock(stdout,pb);