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 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1294 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1296 sym->usl.spillLoc->offset, op);
1297 } else if (getSize(sym->type) <= 1) {
1298 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1299 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300 assert (getSize(sym->type) <= 1);
1301 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1304 /* We need some kind of dummy area for getSize(sym->type) byte,
1305 * use WREG for all storage locations.
1306 * XXX: This only works if we are implementing a `dummy read',
1307 * the stored value will not be retrievable...
1308 * See #1503234 for a case requiring this. */
1309 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1310 aop->size = getSize(sym->type);
1311 for ( i = 0 ; i < aop->size ;i++)
1312 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1314 aop->size = getSize(sym->type);
1320 sym_link *type = operandType(op);
1322 if(IS_PTR_CONST(type))
1324 if(IS_CODEPTR(type))
1326 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1329 /* must be in a register */
1330 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1331 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1332 aop->size = sym->nRegs;
1333 for ( i = 0 ; i < sym->nRegs ;i++)
1334 aop->aopu.aop_reg[i] = sym->regs[i];
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_freeAsmop - free up the asmop given to an operand */
1339 /*----------------------------------------------------------------*/
1340 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1357 /* depending on the asmop type only three cases need work AOP_RO
1358 , AOP_R1 && AOP_STK */
1360 switch (aop->type) {
1362 if (_G.fsr0Pushed ) {
1364 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1365 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1366 // pic16_emitcode ("pop","ar0");
1370 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1374 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1380 pic16_emitcode ("pop","ar0");
1384 bitVectUnSetBit(ic->rUsed,R0_IDX);
1390 pic16_emitcode ("pop","ar1");
1394 bitVectUnSetBit(ic->rUsed,R1_IDX);
1401 /* we must store the result on stack */
1402 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1403 // operands on stack are accessible via "FSR2 + index" with index
1404 // starting at 2 for arguments and growing from 0 downwards for
1405 // local variables (index == 0 is not assigned so we add one here)
1406 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1411 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1412 for(i=0;i<aop->size;i++) {
1413 /* initialise for stack access via frame pointer */
1414 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1415 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1416 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1419 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1423 for(i=0;i<aop->size;i++) {
1424 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1426 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1427 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1428 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1435 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1436 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1437 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1438 deleteSetItem( &_G.sregsAllocSet, sr );
1449 int stk = aop->aopu.aop_stk + aop->size;
1450 bitVectUnSetBit(ic->rUsed,R0_IDX);
1451 bitVectUnSetBit(ic->rUsed,R1_IDX);
1453 getFreePtr(ic,&aop,FALSE);
1455 if (options.stack10bit)
1457 /* I'm not sure what to do here yet... */
1460 "*** Warning: probably generating bad code for "
1461 "10 bit stack mode.\n");
1465 pic16_emitcode ("mov","a,_bp");
1466 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1467 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1469 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1473 pic16_emitcode("pop","acc");
1474 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1476 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1479 pic16_freeAsmop(op,NULL,ic,TRUE);
1481 pic16_emitcode("pop","ar0");
1486 pic16_emitcode("pop","ar1");
1496 /* all other cases just dealloc */
1500 OP_SYMBOL(op)->aop = NULL;
1501 /* if the symbol has a spill */
1503 SPIL_LOC(op)->aop = NULL;
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_aopGet - for fetching value of the aop */
1510 /*-----------------------------------------------------------------*/
1511 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1516 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1518 /* offset is greater than size then zero */
1519 if (offset > (aop->size - 1) &&
1520 aop->type != AOP_LIT)
1523 /* depending on type */
1524 switch (aop->type) {
1528 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1529 rs = Safe_calloc(1, strlen(s)+1);
1534 /* if we need to increment it */
1535 while (offset > aop->coff)
1537 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1541 while (offset < aop->coff)
1543 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1549 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1550 return (dname ? "acc" : "a");
1552 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1553 rs = Safe_calloc (1, strlen (s) + 1);
1561 sprintf (s,"%s",aop->aopu.aop_immd);
1564 sprintf(s,"(%s >> %d)",
1569 aop->aopu.aop_immd);
1570 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1571 rs = Safe_calloc(1,strlen(s)+1);
1577 sprintf(s,"(%s + %d)",
1580 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1582 sprintf(s,"%s",aop->aopu.aop_dir);
1583 rs = Safe_calloc(1,strlen(s)+1);
1588 return aop->aopu.aop_reg[offset]->name;
1591 return aop->aopu.aop_dir;
1594 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1595 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1597 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1598 rs = Safe_strdup("WREG");
1602 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1603 rs = Safe_calloc(1,strlen(s)+1);
1608 aop->coff = offset ;
1610 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1613 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1614 aop->type = AOP_ACC;
1615 return Safe_strdup("_WREG");
1617 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1619 return aop->aopu.aop_str[offset];
1623 pCodeOp *pcop = aop->aopu.pcop;
1624 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1626 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1627 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1629 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1631 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1634 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1637 rs = Safe_calloc(1,strlen(s)+1);
1643 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1645 sprintf(s,"(%s + %d)",
1649 sprintf(s,"%s",aop->aopu.aop_dir);
1650 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651 rs = Safe_calloc(1,strlen(s)+1);
1657 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1661 // pCodeOp *pcop = aop->aop
1666 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1667 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1668 "aopget got unsupported aop->type");
1674 /* lock has the following meaning: When allocating temporary registers
1675 * for stack variables storage, the value of the temporary register is
1676 * saved on stack. Its value is restored at the end. This procedure is
1677 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1678 * a possibility that before a call to pic16_aopOp, a temporary register
1679 * is allocated for a while and it is freed after some time, this will
1680 * mess the stack and values will not be restored properly. So use lock=1
1681 * to allocate temporary registers used internally by the programmer, and
1682 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1683 * to inform the compiler developer about a possible bug. This is an internal
1684 * feature for developing the compiler -- VR */
1686 int _TempReg_lock = 0;
1687 /*-----------------------------------------------------------------*/
1688 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1689 /*-----------------------------------------------------------------*/
1690 pCodeOp *pic16_popGetTempReg(int lock)
1695 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1697 // werror(W_POSSBUG2, __FILE__, __LINE__);
1700 _TempReg_lock += lock;
1710 /* this code might seem better but it does the *same* job with
1711 * the old code, it all depends on ralloc.c to get a free/unused
1715 while(i < pic16_nRegs) {
1716 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1717 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1718 if((!rr || (rr && rr->isFree))
1719 && !bitVectBitValue(cfunc->regsUsed, i)) {
1720 pcop = pic16_newpCodeOpReg( i );
1721 PCOR(pcop)->r->wasUsed = 1;
1722 PCOR(pcop)->r->isFree = 0;
1729 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1733 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1734 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1735 PCOR(pcop)->r->wasUsed=1;
1736 PCOR(pcop)->r->isFree=0;
1738 /* push value on stack */
1739 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1750 /* is not part of f, but don't save if */
1752 /*-----------------------------------------------------------------*/
1753 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1759 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1762 // werror(W_POSSBUG2, __FILE__, __LINE__);
1765 _TempReg_lock += lock;
1770 i = bitVectFirstBit(f);
1773 /* bypass registers that are used by function */
1774 if(!bitVectBitValue(f, i)) {
1776 /* bypass registers that are already allocated for stack access */
1777 if(!bitVectBitValue(v, i)) {
1779 // debugf("getting register rIdx = %d\n", i);
1780 /* ok, get the operand */
1781 pcop = pic16_newpCodeOpReg( i );
1783 /* should never by NULL */
1784 assert( pcop != NULL );
1788 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1791 PCOR(pcop)->r->wasUsed=1;
1792 PCOR(pcop)->r->isFree=0;
1798 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1800 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1801 /* already used in previous steps, break */
1808 /* caller takes care of the following */
1809 // bitVectSetBit(v, i);
1812 /* push value on stack */
1813 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1814 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1832 /*-----------------------------------------------------------------*/
1833 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1837 _TempReg_lock -= lock;
1839 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1840 PCOR(pcop)->r->isFree = 1;
1842 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1845 /*-----------------------------------------------------------------*/
1846 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1847 /*-----------------------------------------------------------------*/
1848 pCodeOp *pic16_popGetLabel(int key)
1851 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1856 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1859 /*-----------------------------------------------------------------*/
1860 /* pic16_popCopyReg - copy a pcode operator */
1861 /*-----------------------------------------------------------------*/
1862 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1866 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1867 memcpy (pcor, pc, sizeof (pCodeOpReg));
1868 pcor->r->wasUsed = 1;
1870 //pcor->pcop.type = pc->pcop.type;
1872 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1873 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1875 pcor->pcop.name = NULL;
1878 //pcor->rIdx = pc->rIdx;
1879 //pcor->r->wasUsed=1;
1880 //pcor->instance = pc->instance;
1882 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetLit - asm operator to pcode operator conversion */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetLit(int lit)
1892 return pic16_newpCodeOpLit(lit);
1895 /* Allow for 12 bit literals (LFSR x, <here!>). */
1896 pCodeOp *pic16_popGetLit12(int lit)
1898 return pic16_newpCodeOpLit12(lit);
1901 /*-----------------------------------------------------------------*/
1902 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1903 /*-----------------------------------------------------------------*/
1904 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1906 return pic16_newpCodeOpLit2(lit, arg2);
1910 /*-----------------------------------------------------------------*/
1911 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1912 /*-----------------------------------------------------------------*/
1913 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1915 return pic16_newpCodeOpImmd(name, offset,index, 0);
1919 /*-----------------------------------------------------------------*/
1920 /* pic16_popGet - asm operator to pcode operator conversion */
1921 /*-----------------------------------------------------------------*/
1922 pCodeOp *pic16_popGetWithString(char *str)
1928 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1932 pcop = pic16_newpCodeOp(str,PO_STR);
1937 /*-----------------------------------------------------------------*/
1938 /* pic16_popRegFromString - */
1939 /*-----------------------------------------------------------------*/
1940 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1943 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1944 pcop->type = PO_DIR;
1946 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1947 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1952 pcop->name = Safe_calloc(1,strlen(str)+1);
1953 strcpy(pcop->name,str);
1955 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1957 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1958 // PCOR(pcop)->r->wasUsed = 1;
1960 /* make sure that register doesn't exist,
1961 * and operand isn't NULL
1962 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1963 if((PCOR(pcop)->r == NULL)
1965 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1966 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1967 // __FUNCTION__, __LINE__, str, size, offset);
1969 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1970 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1973 PCOR(pcop)->instance = offset;
1978 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1982 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1983 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1985 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1986 PCOR(pcop)->rIdx = rIdx;
1987 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1989 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1991 PCOR(pcop)->r->isFree = 0;
1992 PCOR(pcop)->r->wasUsed = 1;
1994 pcop->type = PCOR(pcop)->r->pc_type;
1999 /*---------------------------------------------------------------------------------*/
2000 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2002 /*---------------------------------------------------------------------------------*/
2003 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2005 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2006 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2012 /*--------------------------------------------------------------------------------.-*/
2013 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2014 /* VR 030601 , adapted by Hans Dorn */
2015 /*--------------------------------------------------------------------------------.-*/
2016 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2019 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2023 /*---------------------------------------------------------------------------------*/
2024 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2025 /* movff instruction */
2026 /*---------------------------------------------------------------------------------*/
2027 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2029 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2030 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2036 /*-----------------------------------------------------------------*/
2037 /* pic16_popGet - asm operator to pcode operator conversion */
2038 /*-----------------------------------------------------------------*/
2039 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2041 // char *s = buffer ;
2047 /* offset is greater than size then zero */
2049 // if (offset > (aop->size - 1) &&
2050 // aop->type != AOP_LIT)
2051 // return NULL; //zero;
2053 /* depending on type */
2054 switch (aop->type) {
2059 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2060 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2066 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2067 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2068 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2069 PCOR(pcop)->r->wasUsed = 1;
2070 PCOR(pcop)->r->isFree = 0;
2072 PCOR(pcop)->instance = offset;
2073 pcop->type = PCOR(pcop)->r->pc_type;
2077 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2078 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2081 /* pCodeOp is already allocated from aopForSym */
2082 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2083 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2088 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2090 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2092 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2094 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2095 PCOR(pcop)->rIdx = rIdx;
2096 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2097 PCOR(pcop)->r->wasUsed=1;
2098 PCOR(pcop)->r->isFree=0;
2100 PCOR(pcop)->instance = offset;
2101 pcop->type = PCOR(pcop)->r->pc_type;
2102 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2106 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2107 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2113 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2114 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2118 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2119 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2126 // debugf2("aop = %p\toffset = %d\n", aop, offset);
2127 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
2128 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2130 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2132 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2133 // pcop->type = PO_GPR_REGISTER;
2134 PCOR(pcop)->rIdx = rIdx;
2135 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2136 PCOR(pcop)->r->wasUsed=1;
2137 PCOR(pcop)->r->isFree=0;
2139 PCOR(pcop)->instance = offset;
2140 pcop->type = PCOR(pcop)->r->pc_type;
2142 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2143 // rs = aop->aopu.aop_reg[offset]->name;
2144 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2149 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2151 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2152 PCOR(pcop)->instance = offset;
2153 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2154 //if(PCOR(pcop)->r == NULL)
2155 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2159 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2160 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2163 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2164 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2167 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2168 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2169 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2170 pcop->type = PCOR(pcop)->r->pc_type;
2171 pcop->name = PCOR(pcop)->r->name;
2177 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2179 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2180 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2181 switch( aop->aopu.pcop->type ) {
2182 case PO_DIR: PCOR(pcop)->instance += offset; break;
2183 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2188 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2189 assert( 0 ); /* should never reach here */;
2194 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2195 "pic16_popGet got unsupported aop->type");
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_aopPut - puts a string for a aop */
2200 /*-----------------------------------------------------------------*/
2201 void pic16_aopPut (asmop *aop, char *s, int offset)
2208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2210 if (aop->size && offset > ( aop->size - 1)) {
2211 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2212 "pic16_aopPut got offset > aop->size");
2216 /* will assign value to value */
2217 /* depending on where it is ofcourse */
2218 switch (aop->type) {
2221 sprintf(d,"(%s + %d)",
2222 aop->aopu.aop_dir,offset);
2223 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2226 sprintf(d,"%s",aop->aopu.aop_dir);
2229 DEBUGpic16_emitcode(";","%d",__LINE__);
2231 pic16_emitcode("movf","%s,w",s);
2232 pic16_emitcode("movwf","%s",d);
2235 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2236 if(offset >= aop->size) {
2237 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2240 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2243 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2250 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2251 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2254 strcmp(s,"r0") == 0 ||
2255 strcmp(s,"r1") == 0 ||
2256 strcmp(s,"r2") == 0 ||
2257 strcmp(s,"r3") == 0 ||
2258 strcmp(s,"r4") == 0 ||
2259 strcmp(s,"r5") == 0 ||
2260 strcmp(s,"r6") == 0 ||
2261 strcmp(s,"r7") == 0 )
2262 pic16_emitcode("mov","%s,%s ; %d",
2263 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2267 if(strcmp(s,"W")==0 )
2268 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2270 pic16_emitcode("movwf","%s",
2271 aop->aopu.aop_reg[offset]->name);
2273 if(strcmp(s,zero)==0) {
2274 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2276 } else if(strcmp(s,"W")==0) {
2277 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2278 pcop->type = PO_GPR_REGISTER;
2280 PCOR(pcop)->rIdx = -1;
2281 PCOR(pcop)->r = NULL;
2283 DEBUGpic16_emitcode(";","%d",__LINE__);
2284 pcop->name = Safe_strdup(s);
2285 pic16_emitpcode(POC_MOVFW,pcop);
2286 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2287 } else if(strcmp(s,one)==0) {
2288 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2289 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2291 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2299 if (aop->type == AOP_DPTR2)
2305 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2306 "pic16_aopPut writting to code space");
2310 while (offset > aop->coff) {
2312 pic16_emitcode ("inc","dptr");
2315 while (offset < aop->coff) {
2317 pic16_emitcode("lcall","__decdptr");
2322 /* if not in accumulater */
2325 pic16_emitcode ("movx","@dptr,a");
2327 if (aop->type == AOP_DPTR2)
2335 while (offset > aop->coff) {
2337 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2339 while (offset < aop->coff) {
2341 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2347 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2352 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2354 if (strcmp(s,"r0") == 0 ||
2355 strcmp(s,"r1") == 0 ||
2356 strcmp(s,"r2") == 0 ||
2357 strcmp(s,"r3") == 0 ||
2358 strcmp(s,"r4") == 0 ||
2359 strcmp(s,"r5") == 0 ||
2360 strcmp(s,"r6") == 0 ||
2361 strcmp(s,"r7") == 0 ) {
2363 sprintf(buffer,"a%s",s);
2364 pic16_emitcode("mov","@%s,%s",
2365 aop->aopu.aop_ptr->name,buffer);
2367 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2372 if (strcmp(s,"a") == 0)
2373 pic16_emitcode("push","acc");
2375 pic16_emitcode("push","%s",s);
2380 /* if bit variable */
2381 if (!aop->aopu.aop_dir) {
2382 pic16_emitcode("clr","a");
2383 pic16_emitcode("rlc","a");
2386 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2389 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2392 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2394 lbl = newiTempLabel(NULL);
2396 if (strcmp(s,"a")) {
2399 pic16_emitcode("clr","c");
2400 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2401 pic16_emitcode("cpl","c");
2402 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2403 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2410 if (strcmp(aop->aopu.aop_str[offset],s))
2411 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2416 if (!offset && (strcmp(s,"acc") == 0))
2419 if (strcmp(aop->aopu.aop_str[offset],s))
2420 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2424 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2425 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2426 // "pic16_aopPut got unsupported aop->type");
2432 /*-----------------------------------------------------------------*/
2433 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2434 /*-----------------------------------------------------------------*/
2435 void pic16_mov2w (asmop *aop, int offset)
2437 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2440 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2442 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2445 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2447 if(is_LitAOp(src)) {
2448 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2449 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2451 if(pic16_sameRegsOfs(src, dst, offset))return;
2452 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2453 pic16_popGet(dst, offset)));
2457 static void pic16_movLit2f(pCodeOp *pc, int lit)
2459 if (0 == (lit & 0x00ff))
2461 pic16_emitpcode (POC_CLRF, pc);
2462 } else if (0xff == (lit & 0x00ff))
2464 pic16_emitpcode (POC_SETF, pc);
2466 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2467 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2471 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2473 if(is_LitAOp(src)) {
2474 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2475 pic16_emitpcode(POC_MOVWF, dst);
2477 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2481 void pic16_testStackOverflow(void)
2483 #define GSTACK_TEST_NAME "_gstack_test"
2485 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2490 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2491 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2492 // strcpy(sym->rname, GSTACK_TEST_NAME);
2493 checkAddSym(&externs, sym);
2498 /* push pcop into stack */
2499 void pic16_pushpCodeOp(pCodeOp *pcop)
2501 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2503 if(pic16_options.gstack)
2504 pic16_testStackOverflow();
2508 /* pop pcop from stack */
2509 void pic16_poppCodeOp(pCodeOp *pcop)
2511 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2512 if(pic16_options.gstack)
2513 pic16_testStackOverflow();
2517 /*-----------------------------------------------------------------*/
2518 /* pushw - pushes wreg to stack */
2519 /*-----------------------------------------------------------------*/
2522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2523 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2524 if(pic16_options.gstack)
2525 pic16_testStackOverflow();
2529 /*-----------------------------------------------------------------*/
2530 /* pushaop - pushes aop to stack */
2531 /*-----------------------------------------------------------------*/
2532 void pushaop(asmop *aop, int offset)
2534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2536 if(_G.resDirect)return;
2538 if(is_LitAOp(aop)) {
2539 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2540 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2542 pic16_emitpcode(POC_MOVFF,
2543 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2546 if(pic16_options.gstack)
2547 pic16_testStackOverflow();
2550 /*-----------------------------------------------------------------*/
2551 /* popaop - pops aop from stack */
2552 /*-----------------------------------------------------------------*/
2553 void popaop(asmop *aop, int offset)
2555 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2556 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2557 if(pic16_options.gstack)
2558 pic16_testStackOverflow();
2561 void popaopidx(asmop *aop, int offset, int index)
2565 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2567 if(STACK_MODEL_LARGE)ofs++;
2569 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2570 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2571 if(pic16_options.gstack)
2572 pic16_testStackOverflow();
2575 #if !(USE_GENERIC_SIGNED_SHIFT)
2576 /*-----------------------------------------------------------------*/
2577 /* reAdjustPreg - points a register back to where it should */
2578 /*-----------------------------------------------------------------*/
2579 static void reAdjustPreg (asmop *aop)
2583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2585 if ((size = aop->size) <= 1)
2588 switch (aop->type) {
2592 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2596 if (aop->type == AOP_DPTR2)
2602 pic16_emitcode("lcall","__decdptr");
2605 if (aop->type == AOP_DPTR2)
2617 /*-----------------------------------------------------------------*/
2618 /* opIsGptr: returns non-zero if the passed operand is */
2619 /* a generic pointer type. */
2620 /*-----------------------------------------------------------------*/
2621 static int opIsGptr(operand *op)
2623 sym_link *type = operandType(op);
2625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2626 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2634 /*-----------------------------------------------------------------*/
2635 /* pic16_getDataSize - get the operand data size */
2636 /*-----------------------------------------------------------------*/
2637 int pic16_getDataSize(operand *op)
2639 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2642 return AOP_SIZE(op);
2644 // tsd- in the pic port, the genptr size is 1, so this code here
2645 // fails. ( in the 8051 port, the size was 4).
2648 size = AOP_SIZE(op);
2649 if (size == GPTRSIZE)
2651 sym_link *type = operandType(op);
2652 if (IS_GENPTR(type))
2654 /* generic pointer; arithmetic operations
2655 * should ignore the high byte (pointer type).
2658 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2665 /*-----------------------------------------------------------------*/
2666 /* pic16_outAcc - output Acc */
2667 /*-----------------------------------------------------------------*/
2668 void pic16_outAcc(operand *result)
2671 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2672 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2675 size = pic16_getDataSize(result);
2677 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2680 /* unsigned or positive */
2682 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2687 /*-----------------------------------------------------------------*/
2688 /* pic16_outBitC - output a bit C */
2689 /* Move to result the value of Carry flag -- VR */
2690 /*-----------------------------------------------------------------*/
2691 void pic16_outBitC(operand *result)
2695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2697 /* if the result is bit */
2698 if (AOP_TYPE(result) == AOP_CRY) {
2699 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2700 pic16_aopPut(AOP(result),"c",0);
2703 i = AOP_SIZE(result);
2705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2707 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2711 /*-----------------------------------------------------------------*/
2712 /* pic16_outBitOp - output a bit from Op */
2713 /* Move to result the value of set/clr op -- VR */
2714 /*-----------------------------------------------------------------*/
2715 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2721 /* if the result is bit */
2722 if (AOP_TYPE(result) == AOP_CRY) {
2723 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2724 pic16_aopPut(AOP(result),"c",0);
2727 i = AOP_SIZE(result);
2729 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2731 pic16_emitpcode(POC_RRCF, pcop);
2732 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2736 /*-----------------------------------------------------------------*/
2737 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2738 /*-----------------------------------------------------------------*/
2739 void pic16_toBoolean(operand *oper)
2741 int size = AOP_SIZE(oper) - 1;
2744 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2746 if ( AOP_TYPE(oper) != AOP_ACC) {
2747 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2750 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2754 /*-----------------------------------------------------------------*/
2755 /* genUminusFloat - unary minus for floating points */
2756 /*-----------------------------------------------------------------*/
2757 static void genUminusFloat(operand *op,operand *result)
2759 int size ,offset =0 ;
2762 /* for this we just need to flip the
2763 first it then copy the rest in place */
2764 size = AOP_SIZE(op);
2765 assert( size == AOP_SIZE(result) );
2768 pic16_mov2f(AOP(result), AOP(op), offset);
2772 /* toggle the MSB's highest bit */
2773 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2776 /*-----------------------------------------------------------------*/
2777 /* genUminus - unary minus code generation */
2778 /*-----------------------------------------------------------------*/
2779 static void genUminus (iCode *ic)
2782 sym_link *optype, *rtype;
2789 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2790 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2792 /* if both in bit space then special case */
2793 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2794 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2796 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2797 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2798 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2802 optype = operandType(IC_LEFT(ic));
2803 rtype = operandType(IC_RESULT(ic));
2806 /* if float then do float stuff */
2807 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2808 if(IS_FIXED(optype))
2809 debugf("implement fixed16x16 type\n", 0);
2811 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2815 /* otherwise subtract from zero by taking the 2's complement */
2816 size = AOP_SIZE(IC_LEFT(ic));
2817 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2818 label = newiTempLabel ( NULL );
2820 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2821 for (i=size-1; i > 0; i--) {
2822 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2824 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2825 for (i=1; i < size; i++) {
2826 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2827 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2830 for (i=size-1; i >= 0; i--) {
2831 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2832 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2835 for (i=0; i < size-2; i++) {
2836 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2837 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2839 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2841 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2844 pic16_emitpLabel (label->key);
2847 /* release the aops */
2848 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2849 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2853 /*-----------------------------------------------------------------*/
2854 /* saveRegisters - will look for a call and save the registers */
2855 /*-----------------------------------------------------------------*/
2856 static void saveRegisters(iCode *lic)
2863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2865 for (ic = lic ; ic ; ic = ic->next)
2866 if (ic->op == CALL || ic->op == PCALL)
2870 fprintf(stderr,"found parameter push with no function call\n");
2874 /* if the registers have been saved already then
2876 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2879 /* find the registers in use at this time
2880 and push them away to safety */
2881 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2885 if (options.useXstack) {
2886 if (bitVectBitValue(rsave,R0_IDX))
2887 pic16_emitcode("mov","b,r0");
2888 pic16_emitcode("mov","r0,%s",spname);
2889 for (i = 0 ; i < pic16_nRegs ; i++) {
2890 if (bitVectBitValue(rsave,i)) {
2892 pic16_emitcode("mov","a,b");
2894 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2895 pic16_emitcode("movx","@r0,a");
2896 pic16_emitcode("inc","r0");
2899 pic16_emitcode("mov","%s,r0",spname);
2900 if (bitVectBitValue(rsave,R0_IDX))
2901 pic16_emitcode("mov","r0,b");
2903 //for (i = 0 ; i < pic16_nRegs ; i++) {
2904 // if (bitVectBitValue(rsave,i))
2905 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2908 dtype = operandType(IC_LEFT(ic));
2909 if (currFunc && dtype &&
2910 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2911 IFFUNC_ISISR(currFunc->type) &&
2914 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2917 /*-----------------------------------------------------------------*/
2918 /* unsaveRegisters - pop the pushed registers */
2919 /*-----------------------------------------------------------------*/
2920 static void unsaveRegisters (iCode *ic)
2925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2926 /* find the registers in use at this time
2927 and push them away to safety */
2928 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2931 if (options.useXstack) {
2932 pic16_emitcode("mov","r0,%s",spname);
2933 for (i = pic16_nRegs ; i >= 0 ; i--) {
2934 if (bitVectBitValue(rsave,i)) {
2935 pic16_emitcode("dec","r0");
2936 pic16_emitcode("movx","a,@r0");
2938 pic16_emitcode("mov","b,a");
2940 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2944 pic16_emitcode("mov","%s,r0",spname);
2945 if (bitVectBitValue(rsave,R0_IDX))
2946 pic16_emitcode("mov","r0,b");
2948 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2949 // if (bitVectBitValue(rsave,i))
2950 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2957 /*-----------------------------------------------------------------*/
2959 /*-----------------------------------------------------------------*/
2960 static void pushSide(operand * oper, int size)
2963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2965 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2966 if (AOP_TYPE(oper) != AOP_REG &&
2967 AOP_TYPE(oper) != AOP_DIR &&
2969 pic16_emitcode("mov","a,%s",l);
2970 pic16_emitcode("push","acc");
2972 pic16_emitcode("push","%s",l);
2977 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2979 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2980 pic16_emitpcode(POC_MOVFW, src);
2981 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2983 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2984 src, pic16_popGet(AOP(op), offset)));
2989 /*-----------------------------------------------------------------*/
2990 /* assignResultValue - assign results to oper, rescall==1 is */
2991 /* called from genCall() or genPcall() */
2992 /*-----------------------------------------------------------------*/
2993 static void assignResultValue(operand * oper, int rescall)
2995 int size = AOP_SIZE(oper);
2999 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3000 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3003 /* assign result from a call/pcall function() */
3005 /* function results are stored in a special order,
3006 * see top of file with Function return policy, or manual */
3009 /* 8-bits, result in WREG */
3010 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3013 /* 16-bits, result in PRODL:WREG */
3014 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3018 /* 24-bits, result in PRODH:PRODL:WREG */
3019 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3023 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3024 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3028 /* >32-bits, result on stack, and FSR0 points to beginning.
3029 * Fix stack when done */
3031 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3033 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3034 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3036 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3041 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3042 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3043 if(STACK_MODEL_LARGE) {
3045 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3049 int areg = 0; /* matching argument register */
3051 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3052 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3055 /* its called from genReceive (probably) -- VR */
3056 /* I hope this code will not be called from somewhere else in the future!
3057 * We manually set the pseudo stack pointer in genReceive. - dw
3059 if(!GpsuedoStkPtr && _G.useWreg) {
3060 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3062 /* The last byte in the assignment is in W */
3063 if(areg <= GpsuedoStkPtr) {
3065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3067 // debugf("receive from WREG\n", 0);
3069 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3072 _G.stack_lat = AOP_SIZE(oper)-1;
3077 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3078 // debugf("receive from STACK\n", 0);
3085 /*-----------------------------------------------------------------*/
3086 /* genIpush - generate code for pushing this gets a little complex */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpush (iCode *ic)
3090 // int size, offset=0;
3093 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3096 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3098 /* send to stack as normal */
3099 addSet(&_G.sendSet,ic);
3100 // addSetHead(&_G.sendSet,ic);
3101 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3106 int size, offset = 0 ;
3110 /* if this is not a parm push : ie. it is spill push
3111 and spill push is always done on the local stack */
3112 if (!ic->parmPush) {
3114 /* and the item is spilt then do nothing */
3115 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3118 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3119 size = AOP_SIZE(IC_LEFT(ic));
3120 /* push it on the stack */
3122 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3127 pic16_emitcode("push","%s",l);
3132 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3136 /*-----------------------------------------------------------------*/
3137 /* genIpop - recover the registers: can happen only for spilling */
3138 /*-----------------------------------------------------------------*/
3139 static void genIpop (iCode *ic)
3142 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3147 /* if the temp was not pushed then */
3148 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3151 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3152 size = AOP_SIZE(IC_LEFT(ic));
3155 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3158 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3163 /*-----------------------------------------------------------------*/
3164 /* unsaverbank - restores the resgister bank from stack */
3165 /*-----------------------------------------------------------------*/
3166 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3168 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3176 if (options.useXstack) {
3178 r = getFreePtr(ic,&aop,FALSE);
3181 pic16_emitcode("mov","%s,_spx",r->name);
3182 pic16_emitcode("movx","a,@%s",r->name);
3183 pic16_emitcode("mov","psw,a");
3184 pic16_emitcode("dec","%s",r->name);
3187 pic16_emitcode ("pop","psw");
3190 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3191 if (options.useXstack) {
3192 pic16_emitcode("movx","a,@%s",r->name);
3193 //pic16_emitcode("mov","(%s+%d),a",
3194 // regspic16[i].base,8*bank+regspic16[i].offset);
3195 pic16_emitcode("dec","%s",r->name);
3198 pic16_emitcode("pop",""); //"(%s+%d)",
3199 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3202 if (options.useXstack) {
3204 pic16_emitcode("mov","_spx,%s",r->name);
3205 pic16_freeAsmop(NULL,aop,ic,TRUE);
3211 /*-----------------------------------------------------------------*/
3212 /* saverbank - saves an entire register bank on the stack */
3213 /*-----------------------------------------------------------------*/
3214 static void saverbank (int bank, iCode *ic, bool pushPsw)
3216 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3223 if (options.useXstack) {
3226 r = getFreePtr(ic,&aop,FALSE);
3227 pic16_emitcode("mov","%s,_spx",r->name);
3231 for (i = 0 ; i < pic16_nRegs ;i++) {
3232 if (options.useXstack) {
3233 pic16_emitcode("inc","%s",r->name);
3234 //pic16_emitcode("mov","a,(%s+%d)",
3235 // regspic16[i].base,8*bank+regspic16[i].offset);
3236 pic16_emitcode("movx","@%s,a",r->name);
3238 pic16_emitcode("push","");// "(%s+%d)",
3239 //regspic16[i].base,8*bank+regspic16[i].offset);
3243 if (options.useXstack) {
3244 pic16_emitcode("mov","a,psw");
3245 pic16_emitcode("movx","@%s,a",r->name);
3246 pic16_emitcode("inc","%s",r->name);
3247 pic16_emitcode("mov","_spx,%s",r->name);
3248 pic16_freeAsmop (NULL,aop,ic,TRUE);
3251 pic16_emitcode("push","psw");
3253 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3261 static int wparamCmp(void *p1, void *p2)
3263 return (!strcmp((char *)p1, (char *)p2));
3266 int inWparamList(char *s)
3268 return isinSetWith(wparamList, s, wparamCmp);
3272 /*-----------------------------------------------------------------*/
3273 /* genCall - generates a call statement */
3274 /*-----------------------------------------------------------------*/
3275 static void genCall (iCode *ic)
3285 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3286 /* if caller saves & we have not saved then */
3287 // if (!ic->regsSaved)
3288 // saveRegisters(ic);
3290 /* initialise stackParms for IPUSH pushes */
3291 // stackParms = psuedoStkPtr;
3292 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3293 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3294 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3297 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3300 /* if send set is not empty the assign */
3303 int psuedoStkPtr=-1;
3304 int firstTimeThruLoop = 1;
3307 /* reverse sendSet if function is not reentrant */
3308 if(!IFFUNC_ISREENT(ftype))
3309 _G.sendSet = reverseSet(_G.sendSet);
3311 /* First figure how many parameters are getting passed */
3315 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3319 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3320 size = AOP_SIZE(IC_LEFT(sic));
3324 /* pass the last byte through WREG */
3328 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3329 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3330 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3332 if(!firstTimeThruLoop) {
3333 /* If this is not the first time we've been through the loop
3334 * then we need to save the parameter in a temporary
3335 * register. The last byte of the last parameter is
3339 // --psuedoStkPtr; // sanity check
3343 firstTimeThruLoop=0;
3345 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3350 /* all arguments are passed via stack */
3354 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3355 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3356 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3358 // pushaop(AOP(IC_LEFT(sic)), size);
3359 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3366 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3370 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3371 pushw(); /* save last parameter to stack if functions has varargs */
3375 } else use_wreg = 0;
3377 _G.stackRegSet = _G.sendSet;
3382 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3386 /* if we need to assign a result value */
3387 if ((IS_ITEMP(IC_RESULT(ic))
3388 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3389 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3390 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3393 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3396 assignResultValue(IC_RESULT(ic), 1);
3398 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3399 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3401 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3404 if(!stackParms && ic->parmBytes) {
3405 stackParms = ic->parmBytes;
3408 stackParms -= use_wreg;
3411 if(stackParms == 1) {
3412 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3414 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3415 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3417 if(STACK_MODEL_LARGE) {
3419 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3424 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3427 /* adjust the stack for parameters if required */
3428 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3431 /* if register bank was saved then pop them */
3433 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3435 /* if we hade saved some registers then unsave them */
3436 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3437 unsaveRegisters (ic);
3443 /*-----------------------------------------------------------------*/
3444 /* genPcall - generates a call by pointer statement */
3445 /* new version, created from genCall - HJD */
3446 /*-----------------------------------------------------------------*/
3447 static void genPcall (iCode *ic)
3451 symbol *retlbl = newiTempLabel(NULL);
3452 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3456 fntype = operandType( IC_LEFT(ic) )->next;
3458 /* if send set is not empty the assign */
3461 int psuedoStkPtr=-1;
3463 /* reverse sendSet if function is not reentrant */
3464 if(!IFFUNC_ISREENT(fntype))
3465 _G.sendSet = reverseSet(_G.sendSet);
3469 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3472 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3473 size = AOP_SIZE(IC_LEFT(sic));
3476 /* all parameters are passed via stack, since WREG is clobbered
3477 * by the calling sequence */
3479 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3480 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3481 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3483 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3487 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3490 _G.stackRegSet = _G.sendSet;
3494 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3496 // push return address
3497 // push $ on return stack, then replace with retlbl
3499 /* Thanks to Thorsten Klose for pointing out that the following
3500 * snippet should be interrupt safe */
3501 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3502 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3504 pic16_emitpcodeNULLop(POC_PUSH);
3506 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3507 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3508 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3509 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3510 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3511 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3514 /* restore interrupt control register */
3515 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3516 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3518 /* make the call by writing the pointer into pc */
3519 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3520 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3522 // note: MOVFF to PCL not allowed
3523 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3524 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3527 /* return address is here: (X) */
3528 pic16_emitpLabelFORCE(retlbl->key);
3530 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3533 /* if we need assign a result value */
3534 if ((IS_ITEMP(IC_RESULT(ic))
3535 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3536 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3537 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3540 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3543 assignResultValue(IC_RESULT(ic), 1);
3545 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3546 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3548 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3551 // stackParms -= use_wreg;
3554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3555 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3556 if(STACK_MODEL_LARGE) {
3558 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3563 /*-----------------------------------------------------------------*/
3564 /* resultRemat - result is rematerializable */
3565 /*-----------------------------------------------------------------*/
3566 static int resultRemat (iCode *ic)
3568 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3569 if (SKIP_IC(ic) || ic->op == IFX)
3572 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3573 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3574 if (sym->remat && !POINTER_SET(ic))
3581 #if defined(__BORLANDC__) || defined(_MSC_VER)
3582 #define STRCASECMP stricmp
3584 #define STRCASECMP strcasecmp
3588 /*-----------------------------------------------------------------*/
3589 /* inExcludeList - return 1 if the string is in exclude Reg list */
3590 /*-----------------------------------------------------------------*/
3591 static bool inExcludeList(char *s)
3593 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3597 if (options.excludeRegs[i] &&
3598 STRCASECMP(options.excludeRegs[i],"none") == 0)
3601 for ( i = 0 ; options.excludeRegs[i]; i++) {
3602 if (options.excludeRegs[i] &&
3603 STRCASECMP(s,options.excludeRegs[i]) == 0)
3610 /*-----------------------------------------------------------------*/
3611 /* genFunction - generated code for function entry */
3612 /*-----------------------------------------------------------------*/
3613 static void genFunction (iCode *ic)
3619 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3621 pic16_labelOffset += (max_key+4);
3626 ftype = operandType(IC_LEFT(ic));
3627 sym = OP_SYMBOL(IC_LEFT(ic));
3629 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3630 /* create an absolute section at the interrupt vector:
3631 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3636 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3638 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3639 sprintf(asymname, "ivec_%s", sym->name);
3641 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3643 /* when an interrupt is declared as naked, do not emit the special
3644 * wrapper segment at vector address. The user should take care for
3645 * this instead. -- VR */
3647 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3648 asym = newSymbol(asymname, 0);
3649 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3650 pic16_addpBlock( apb );
3652 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3653 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3654 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3655 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3656 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3658 /* mark the end of this tiny function */
3659 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3661 sprintf(asymname, "%s", sym->rname);
3667 abSym = Safe_calloc(1, sizeof(absSym));
3668 strcpy(abSym->name, asymname);
3670 switch( FUNC_INTNO(sym->type) ) {
3671 case 0: abSym->address = 0x000000; break;
3672 case 1: abSym->address = 0x000008; break;
3673 case 2: abSym->address = 0x000018; break;
3676 // fprintf(stderr, "no interrupt number is given\n");
3677 abSym->address = -1; break;
3680 /* relocate interrupt vectors if needed */
3681 if(abSym->address != -1)
3682 abSym->address += pic16_options.ivt_loc;
3684 addSet(&absSymSet, abSym);
3688 /* create the function header */
3689 pic16_emitcode(";","-----------------------------------------");
3690 pic16_emitcode(";"," function %s",sym->name);
3691 pic16_emitcode(";","-----------------------------------------");
3693 pic16_emitcode("","%s:",sym->rname);
3694 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3699 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3700 if(!strcmp(ab->name, sym->rname)) {
3701 pic16_pBlockConvert2Absolute(pb);
3707 if(IFFUNC_ISNAKED(ftype)) {
3708 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3712 /* if critical function then turn interrupts off */
3713 if (IFFUNC_ISCRITICAL(ftype)) {
3714 //pic16_emitcode("clr","ea");
3717 currFunc = sym; /* update the currFunc symbol */
3718 _G.fregsUsed = sym->regsUsed;
3719 _G.sregsAlloc = newBitVect(128);
3722 /* if this is an interrupt service routine then
3723 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3724 if (IFFUNC_ISISR(sym->type)) {
3725 _G.usefastretfie = 1; /* use shadow registers by default */
3727 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3728 if(!FUNC_ISSHADOWREGS(sym->type)) {
3729 /* do not save WREG,STATUS,BSR for high priority interrupts
3730 * because they are stored in the hardware shadow registers already */
3731 _G.usefastretfie = 0;
3732 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3733 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3734 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3737 /* these should really be optimized somehow, because not all
3738 * interrupt handlers modify them */
3739 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3740 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3741 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3742 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3744 // pic16_pBlockConvert2ISR(pb);
3747 /* emit code to setup stack frame if user enabled,
3748 * and function is not main() */
3750 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3751 if(strcmp(sym->name, "main")) {
3753 || !options.ommitFramePtr
3755 || IFFUNC_ARGS(sym->type)
3756 || FUNC_HASSTACKPARM(sym->etype)
3758 /* setup the stack frame */
3759 if(STACK_MODEL_LARGE)
3760 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3761 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3763 if(STACK_MODEL_LARGE)
3764 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3765 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3769 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3772 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3774 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3775 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3777 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3780 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3781 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3788 /* if callee-save to be used for this function
3789 * then save the registers being used in this function */
3790 // if (IFFUNC_CALLEESAVES(sym->type))
3791 if(strcmp(sym->name, "main")) {
3794 /* if any registers used */
3795 if (sym->regsUsed) {
3796 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3799 /* save the registers used */
3800 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3801 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3802 if (bitVectBitValue(sym->regsUsed,i)) {
3804 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3806 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3809 if(!pic16_regWithIdx(i)->wasUsed) {
3810 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3811 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3812 pic16_regWithIdx(i)->wasUsed = 1;
3819 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3820 for(i=0;i<sym->regsUsed->size;i++) {
3821 if(bitVectBitValue(sym->regsUsed, i)) {
3826 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3829 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3834 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3835 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3838 /*-----------------------------------------------------------------*/
3839 /* genEndFunction - generates epilogue for functions */
3840 /*-----------------------------------------------------------------*/
3841 static void genEndFunction (iCode *ic)
3843 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3847 if(IFFUNC_ISNAKED(sym->type)) {
3848 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3854 /* add code for ISCRITICAL */
3855 if(IFFUNC_ISCRITICAL(sym->type)) {
3856 /* if critical function, turn on interrupts */
3858 /* TODO: add code here -- VR */
3861 // sym->regsUsed = _G.fregsUsed;
3863 /* now we need to restore the registers */
3864 /* if any registers used */
3866 /* first restore registers that might be used for stack access */
3867 if(_G.sregsAllocSet) {
3870 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3871 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3872 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3876 if (strcmp(sym->name, "main") && sym->regsUsed) {
3879 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3880 /* restore registers used */
3881 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3882 for ( i = sym->regsUsed->size; i >= 0; i--) {
3883 if (bitVectBitValue(sym->regsUsed,i)) {
3884 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3888 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3893 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3895 if (sym->stack == 1) {
3896 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3897 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3899 // we have to add more than one...
3900 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3901 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3902 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3904 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3905 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3906 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3910 if(strcmp(sym->name, "main")) {
3912 || !options.ommitFramePtr
3914 || IFFUNC_ARGS(sym->type)
3915 || FUNC_HASSTACKPARM(sym->etype)
3917 /* restore stack frame */
3918 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3919 if(STACK_MODEL_LARGE)
3920 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3926 if (IFFUNC_ISISR(sym->type)) {
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3928 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3929 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3930 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3932 if(!FUNC_ISSHADOWREGS(sym->type)) {
3933 /* do not restore interrupt vector for WREG,STATUS,BSR
3934 * for high priority interrupt, see genFunction */
3935 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3936 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3937 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3939 // _G.interruptvector = 0; /* sanity check */
3942 /* if debug then send end of function */
3943 /* if (options.debug && currFunc) */
3945 debugFile->writeEndFunction (currFunc, ic, 1);
3948 if(_G.usefastretfie)
3949 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3951 pic16_emitpcodeNULLop(POC_RETFIE);
3953 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3955 _G.usefastretfie = 0;
3959 if (IFFUNC_ISCRITICAL(sym->type)) {
3960 pic16_emitcode("setb","ea");
3963 /* if debug then send end of function */
3965 debugFile->writeEndFunction (currFunc, ic, 1);
3968 /* insert code to restore stack frame, if user enabled it
3969 * and function is not main() */
3972 pic16_emitpcodeNULLop(POC_RETURN);
3974 /* Mark the end of a function */
3975 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3979 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3981 unsigned long lit=1;
3986 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3987 if(AOP_TYPE(op) == AOP_LIT) {
3988 if(!IS_FLOAT(operandType( op ))) {
3989 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3992 unsigned long lit_int;
3996 /* take care if literal is a float */
3997 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4002 if (AOP_TYPE(op) == AOP_LIT) {
4003 /* FIXME: broken for
4004 * char __at(0x456) foo;
4006 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4007 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4008 } else if (AOP_TYPE(op) == AOP_PCODE
4009 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4010 /* char *s= "aaa"; return s; */
4011 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4012 * that the generic pointer is interpreted correctly
4013 * as referring to __code space, but this is fragile! */
4014 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4015 /* XXX: should check that dest != WREG */
4016 pic16_emitpcode(POC_MOVWF, dest);
4018 if(dest->type == PO_WREG && (offset == 0)) {
4019 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4026 /*-----------------------------------------------------------------*/
4027 /* genRet - generate code for return statement */
4028 /*-----------------------------------------------------------------*/
4029 static void genRet (iCode *ic)
4035 /* if we have no return value then
4036 * just generate the "ret" */
4041 /* we have something to return then
4042 * move the return value into place */
4043 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4044 size = AOP_SIZE(IC_LEFT(ic));
4048 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4051 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4054 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4056 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4059 /* >32-bits, setup stack and FSR0 */
4061 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4062 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4064 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4066 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4071 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4074 if(STACK_MODEL_LARGE) {
4075 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4076 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4078 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4083 /* old code, left here for reference -- VR */
4087 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4089 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4090 pic16_emitpcomment("push %s",l);
4093 DEBUGpic16_emitcode(";", "%d", __LINE__);
4094 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4095 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4097 if (strcmp(fReturn[offset],l)) {
4098 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4099 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4100 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4102 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4106 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4116 if (strcmp(fReturn[pushed],"a"))
4117 pic16_emitcode("pop",fReturn[pushed]);
4119 pic16_emitcode("pop","acc");
4125 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4128 /* generate a jump to the return label
4129 * if the next is not the return statement */
4130 if (!(ic->next && ic->next->op == LABEL
4131 && IC_LABEL(ic->next) == returnLabel)) {
4133 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4134 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4138 /*-----------------------------------------------------------------*/
4139 /* genLabel - generates a label */
4140 /*-----------------------------------------------------------------*/
4141 static void genLabel (iCode *ic)
4145 /* special case never generate */
4146 if (IC_LABEL(ic) == entryLabel)
4149 pic16_emitpLabel(IC_LABEL(ic)->key);
4150 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a goto */
4155 /*-----------------------------------------------------------------*/
4157 static void genGoto (iCode *ic)
4160 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4161 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4165 /*-----------------------------------------------------------------*/
4166 /* genMultbits :- multiplication of bits */
4167 /*-----------------------------------------------------------------*/
4168 static void genMultbits (operand *left,
4174 if(!pic16_sameRegs(AOP(result),AOP(right)))
4175 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4177 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4178 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4179 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneByte : 8 bit multiplication & division */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneByte (operand *left,
4193 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4194 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4196 /* (if two literals, the value is computed before) */
4197 /* if one literal, literal on the right */
4198 if (AOP_TYPE(left) == AOP_LIT){
4204 /* size is already checked in genMult == 1 */
4205 // size = AOP_SIZE(result);
4207 if (AOP_TYPE(right) == AOP_LIT){
4208 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4209 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4211 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4214 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4215 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4216 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4219 pic16_genMult8X8_8 (left, right,result);
4222 /*-----------------------------------------------------------------*/
4223 /* genMultOneWord : 16 bit multiplication */
4224 /*-----------------------------------------------------------------*/
4225 static void genMultOneWord (operand *left,
4230 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4231 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4233 /* (if two literals, the value is computed before)
4234 * if one literal, literal on the right */
4235 if (AOP_TYPE(left) == AOP_LIT){
4241 /* size is checked already == 2 */
4242 // size = AOP_SIZE(result);
4244 if (AOP_TYPE(right) == AOP_LIT) {
4245 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4246 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4247 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4248 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4250 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4251 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4252 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4253 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4256 pic16_genMult16X16_16(left, right,result);
4259 /*-----------------------------------------------------------------*/
4260 /* genMultOneLong : 32 bit multiplication */
4261 /*-----------------------------------------------------------------*/
4262 static void genMultOneLong (operand *left,
4267 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4268 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4270 /* (if two literals, the value is computed before)
4271 * if one literal, literal on the right */
4272 if (AOP_TYPE(left) == AOP_LIT){
4278 /* size is checked already == 4 */
4279 // size = AOP_SIZE(result);
4281 if (AOP_TYPE(right) == AOP_LIT) {
4282 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4283 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4284 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4285 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4287 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4288 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4289 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4290 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4293 pic16_genMult32X32_32(left, right,result);
4298 /*-----------------------------------------------------------------*/
4299 /* genMult - generates code for multiplication */
4300 /*-----------------------------------------------------------------*/
4301 static void genMult (iCode *ic)
4303 operand *left = IC_LEFT(ic);
4304 operand *right = IC_RIGHT(ic);
4305 operand *result= IC_RESULT(ic);
4308 /* assign the amsops */
4309 pic16_aopOp (left,ic,FALSE);
4310 pic16_aopOp (right,ic,FALSE);
4311 pic16_aopOp (result,ic,TRUE);
4313 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4315 /* special cases first *
4317 if (AOP_TYPE(left) == AOP_CRY
4318 && AOP_TYPE(right)== AOP_CRY) {
4319 genMultbits(left,right,result);
4323 /* if both are of size == 1 */
4324 if(AOP_SIZE(left) == 1
4325 && AOP_SIZE(right) == 1) {
4326 genMultOneByte(left,right,result);
4330 /* if both are of size == 2 */
4331 if(AOP_SIZE(left) == 2
4332 && AOP_SIZE(right) == 2) {
4333 genMultOneWord(left, right, result);
4337 /* if both are of size == 4 */
4338 if(AOP_SIZE(left) == 4
4339 && AOP_SIZE(right) == 4) {
4340 genMultOneLong(left, right, result);
4344 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4347 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4348 /* should have been converted to function call */
4352 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354 pic16_freeAsmop(result,NULL,ic,TRUE);
4357 /*-----------------------------------------------------------------*/
4358 /* genDivbits :- division of bits */
4359 /*-----------------------------------------------------------------*/
4360 static void genDivbits (operand *left,
4367 /* the result must be bit */
4368 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4369 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4373 pic16_emitcode("div","ab");
4374 pic16_emitcode("rrc","a");
4375 pic16_aopPut(AOP(result),"c",0);
4378 /*-----------------------------------------------------------------*/
4379 /* genDivOneByte : 8 bit division */
4380 /*-----------------------------------------------------------------*/
4381 static void genDivOneByte (operand *left,
4385 sym_link *opetype = operandType(result);
4390 /* result = divident / divisor
4391 * - divident may be a register or a literal,
4392 * - divisor may be a register or a literal,
4393 * so there are 3 cases (literal / literal is optimized
4394 * by the front-end) to handle.
4395 * In addition we must handle signed and unsigned, which
4396 * result in 6 final different cases -- VR */
4400 size = AOP_SIZE(result) - 1;
4402 /* signed or unsigned */
4403 if (SPEC_USIGN(opetype)) {
4404 pCodeOp *pct1, /* count */
4407 symbol *label1, *label2, *label3;;
4410 /* unsigned is easy */
4412 pct1 = pic16_popGetTempReg(1);
4413 pct2 = pic16_popGetTempReg(1);
4414 pct3 = pic16_popGetTempReg(1);
4416 label1 = newiTempLabel(NULL);
4417 label2 = newiTempLabel(NULL);
4418 label3 = newiTempLabel(NULL);
4420 /* the following algorithm is extracted from divuint.c */
4422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4423 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4425 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4427 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4429 pic16_emitpLabel(label1->key);
4432 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4436 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4440 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4442 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4443 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4445 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4446 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4447 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4449 pic16_emitpLabel( label3->key );
4450 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4451 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4455 pic16_emitpLabel(label2->key);
4456 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4457 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4458 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4460 /* result is in wreg */
4461 if(AOP_TYPE(result) != AOP_ACC)
4462 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4464 pic16_popReleaseTempReg( pct3, 1);
4465 pic16_popReleaseTempReg( pct2, 1);
4466 pic16_popReleaseTempReg( pct1, 1);
4471 /* signed is a little bit more difficult */
4473 /* save the signs of the operands */
4474 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4476 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4477 pic16_emitcode("push","acc"); /* save it on the stack */
4479 /* now sign adjust for both left & right */
4480 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4482 lbl = newiTempLabel(NULL);
4483 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4484 pic16_emitcode("cpl","a");
4485 pic16_emitcode("inc","a");
4486 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4487 pic16_emitcode("mov","b,a");
4489 /* sign adjust left side */
4490 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4493 lbl = newiTempLabel(NULL);
4494 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4495 pic16_emitcode("cpl","a");
4496 pic16_emitcode("inc","a");
4497 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4499 /* now the division */
4500 pic16_emitcode("div","ab");
4501 /* we are interested in the lower order
4503 pic16_emitcode("mov","b,a");
4504 lbl = newiTempLabel(NULL);
4505 pic16_emitcode("pop","acc");
4506 /* if there was an over flow we don't
4507 adjust the sign of the result */
4508 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4509 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4511 pic16_emitcode("clr","a");
4512 pic16_emitcode("subb","a,b");
4513 pic16_emitcode("mov","b,a");
4514 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4516 /* now we are done */
4517 pic16_aopPut(AOP(result),"b",0);
4519 pic16_emitcode("mov","c,b.7");
4520 pic16_emitcode("subb","a,acc");
4523 pic16_aopPut(AOP(result),"a",offset++);
4527 /*-----------------------------------------------------------------*/
4528 /* genDiv - generates code for division */
4529 /*-----------------------------------------------------------------*/
4530 static void genDiv (iCode *ic)
4532 operand *left = IC_LEFT(ic);
4533 operand *right = IC_RIGHT(ic);
4534 operand *result= IC_RESULT(ic);
4537 /* Division is a very lengthy algorithm, so it is better
4538 * to call support routines than inlining algorithm.
4539 * Division functions written here just in case someone
4540 * wants to inline and not use the support libraries -- VR */
4544 /* assign the amsops */
4545 pic16_aopOp (left,ic,FALSE);
4546 pic16_aopOp (right,ic,FALSE);
4547 pic16_aopOp (result,ic,TRUE);
4549 /* special cases first */
4551 if (AOP_TYPE(left) == AOP_CRY &&
4552 AOP_TYPE(right)== AOP_CRY) {
4553 genDivbits(left,right,result);
4557 /* if both are of size == 1 */
4558 if (AOP_SIZE(left) == 1 &&
4559 AOP_SIZE(right) == 1 ) {
4560 genDivOneByte(left,right,result);
4564 /* should have been converted to function call */
4567 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4568 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569 pic16_freeAsmop(result,NULL,ic,TRUE);
4572 /*-----------------------------------------------------------------*/
4573 /* genModbits :- modulus of bits */
4574 /*-----------------------------------------------------------------*/
4575 static void genModbits (operand *left,
4583 werror(W_POSSBUG2, __FILE__, __LINE__);
4584 /* the result must be bit */
4585 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4586 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4590 pic16_emitcode("div","ab");
4591 pic16_emitcode("mov","a,b");
4592 pic16_emitcode("rrc","a");
4593 pic16_aopPut(AOP(result),"c",0);
4596 /*-----------------------------------------------------------------*/
4597 /* genModOneByte : 8 bit modulus */
4598 /*-----------------------------------------------------------------*/
4599 static void genModOneByte (operand *left,
4603 sym_link *opetype = operandType(result);
4608 werror(W_POSSBUG2, __FILE__, __LINE__);
4610 /* signed or unsigned */
4611 if (SPEC_USIGN(opetype)) {
4612 /* unsigned is easy */
4613 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4614 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4616 pic16_emitcode("div","ab");
4617 pic16_aopPut(AOP(result),"b",0);
4621 /* signed is a little bit more difficult */
4623 /* save the signs of the operands */
4624 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4627 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4628 pic16_emitcode("push","acc"); /* save it on the stack */
4630 /* now sign adjust for both left & right */
4631 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4634 lbl = newiTempLabel(NULL);
4635 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4636 pic16_emitcode("cpl","a");
4637 pic16_emitcode("inc","a");
4638 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4639 pic16_emitcode("mov","b,a");
4641 /* sign adjust left side */
4642 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4645 lbl = newiTempLabel(NULL);
4646 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4647 pic16_emitcode("cpl","a");
4648 pic16_emitcode("inc","a");
4649 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4651 /* now the multiplication */
4652 pic16_emitcode("div","ab");
4653 /* we are interested in the lower order
4655 lbl = newiTempLabel(NULL);
4656 pic16_emitcode("pop","acc");
4657 /* if there was an over flow we don't
4658 adjust the sign of the result */
4659 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4660 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4662 pic16_emitcode("clr","a");
4663 pic16_emitcode("subb","a,b");
4664 pic16_emitcode("mov","b,a");
4665 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4667 /* now we are done */
4668 pic16_aopPut(AOP(result),"b",0);
4672 /*-----------------------------------------------------------------*/
4673 /* genMod - generates code for division */
4674 /*-----------------------------------------------------------------*/
4675 static void genMod (iCode *ic)
4677 operand *left = IC_LEFT(ic);
4678 operand *right = IC_RIGHT(ic);
4679 operand *result= IC_RESULT(ic);
4683 /* assign the amsops */
4684 pic16_aopOp (left,ic,FALSE);
4685 pic16_aopOp (right,ic,FALSE);
4686 pic16_aopOp (result,ic,TRUE);
4688 /* special cases first */
4690 if (AOP_TYPE(left) == AOP_CRY &&
4691 AOP_TYPE(right)== AOP_CRY) {
4692 genModbits(left,right,result);
4696 /* if both are of size == 1 */
4697 if (AOP_SIZE(left) == 1 &&
4698 AOP_SIZE(right) == 1 ) {
4699 genModOneByte(left,right,result);
4703 /* should have been converted to function call */
4707 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4708 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709 pic16_freeAsmop(result,NULL,ic,TRUE);
4712 /*-----------------------------------------------------------------*/
4713 /* genIfxJump :- will create a jump depending on the ifx */
4714 /*-----------------------------------------------------------------*/
4716 note: May need to add parameter to indicate when a variable is in bit space.
4718 static void genIfxJump (iCode *ic, char *jval)
4722 /* if true label then we jump if condition
4724 if ( IC_TRUE(ic) ) {
4726 if(strcmp(jval,"a") == 0)
4728 else if (strcmp(jval,"c") == 0)
4731 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4732 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4736 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4740 /* false label is present */
4741 if(strcmp(jval,"a") == 0)
4743 else if (strcmp(jval,"c") == 0)
4746 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4747 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4751 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4756 /* mark the icode as generated */
4760 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4764 /* if true label then we jump if condition
4766 if ( IC_TRUE(ic) ) {
4767 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4768 pic16_emitpcode(POC_BTFSC, jop);
4770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4771 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4774 /* false label is present */
4775 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4776 pic16_emitpcode(POC_BTFSS, jop);
4778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4779 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4783 /* mark the icode as generated */
4790 /*-----------------------------------------------------------------*/
4792 /*-----------------------------------------------------------------*/
4793 static void genSkip(iCode *ifx,int status_bit)
4795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4799 if ( IC_TRUE(ifx) ) {
4800 switch(status_bit) {
4815 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4816 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4820 switch(status_bit) {
4834 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4835 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4842 /*-----------------------------------------------------------------*/
4844 /*-----------------------------------------------------------------*/
4845 static void genSkipc(resolvedIfx *rifx)
4847 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4857 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4858 rifx->generated = 1;
4861 #if !(USE_SIMPLE_GENCMP)
4862 /*-----------------------------------------------------------------*/
4864 /*-----------------------------------------------------------------*/
4865 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4867 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4872 if( (rifx->condition ^ invert_condition) & 1)
4877 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4878 rifx->generated = 1;
4883 /*-----------------------------------------------------------------*/
4885 /*-----------------------------------------------------------------*/
4886 static void genSkipz(iCode *ifx, int condition)
4897 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4902 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4904 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4909 #if !(USE_SIMPLE_GENCMP)
4910 /*-----------------------------------------------------------------*/
4912 /*-----------------------------------------------------------------*/
4913 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4919 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4921 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4925 rifx->generated = 1;
4930 /*-----------------------------------------------------------------*/
4931 /* genChkZeroes :- greater or less than comparison */
4932 /* For each byte in a literal that is zero, inclusive or the */
4933 /* the corresponding byte in the operand with W */
4934 /* returns true if any of the bytes are zero */
4935 /*-----------------------------------------------------------------*/
4936 static int genChkZeroes(operand *op, int lit, int size)
4943 i = (lit >> (size*8)) & 0xff;
4947 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4949 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4959 /*-----------------------------------------------------------------*/
4960 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4961 /* aop (if it's NOT a literal) or from lit (if */
4962 /* aop is a literal) */
4963 /*-----------------------------------------------------------------*/
4964 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4965 if (aop->type == AOP_LIT) {
4966 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4968 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4972 /*-----------------------------------------------------------------*/
4973 /* genCmp :- greater or less than comparison */
4974 /*-----------------------------------------------------------------*/
4976 #if USE_SIMPLE_GENCMP /* { */
4978 /* genCmp performs a left < right comparison, stores
4979 * the outcome in result (if != NULL) and generates
4980 * control flow code for the ifx (if != NULL).
4982 * This version leaves in sequences like
4983 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4984 * which should be optmized by the peephole
4985 * optimizer - RN 2005-01-01 */
4986 static void genCmp (operand *left,operand *right,
4987 operand *result, iCode *ifx, int sign)
5000 assert (left && right);
5001 assert (AOP_SIZE(left) == AOP_SIZE(right));
5003 size = AOP_SIZE(right) - 1;
5004 mask = (0x100UL << (size*8)) - 1;
5005 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5010 resolveIfx (&rIfx, ifx);
5012 /* handle for special cases */
5013 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5016 /**********************************************************************
5017 * handle bits - bit compares are promoted to int compares seemingly! *
5018 **********************************************************************/
5020 // THIS IS COMPLETELY UNTESTED!
5021 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5022 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5023 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5024 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5027 // 1 < {0,1} is false --> clear C by skipping the next instruction
5028 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5029 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5030 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5031 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5032 emitCLRC; // only skipped for left=0 && right=1
5034 goto correct_result_in_carry;
5038 /*************************************************
5039 * make sure that left is register (or the like) *
5040 *************************************************/
5041 if (!isAOP_REGlike(left)) {
5042 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5043 assert (isAOP_LIT(left));
5044 assert (isAOP_REGlike(right));
5045 // swap left and right
5046 // left < right <==> right > left <==> (right >= left + 1)
5047 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5049 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5050 // MAXVALUE < right? always false
5051 if (performedLt) emitCLRC; else emitSETC;
5052 goto correct_result_in_carry;
5055 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5056 // that's why we handled it above.
5063 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5064 } else if (isAOP_LIT(right)) {
5065 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5068 assert (isAOP_REGlike(left)); // left must be register or the like
5069 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5071 /*************************************************
5072 * special cases go here *
5073 *************************************************/
5075 if (isAOP_LIT(right)) {
5077 // unsigned comparison to a literal
5078 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5080 // unsigned left < 0? always false
5081 if (performedLt) emitCLRC; else emitSETC;
5082 goto correct_result_in_carry;
5085 // signed comparison to a literal
5086 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5087 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5088 // signed left < 0x80000000? always false
5089 if (performedLt) emitCLRC; else emitSETC;
5090 goto correct_result_in_carry;
5091 } else if (lit == 0) {
5092 // compare left < 0; set CARRY if SIGNBIT(left) is set
5093 if (performedLt) emitSETC; else emitCLRC;
5094 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5095 if (performedLt) emitCLRC; else emitSETC;
5096 goto correct_result_in_carry;
5099 } // right is literal
5101 /*************************************************
5102 * perform a general case comparison *
5103 * make sure we get CARRY==1 <==> left >= right *
5104 *************************************************/
5105 // compare most significant bytes
5106 //DEBUGpc ("comparing bytes at offset %d", size);
5108 // unsigned comparison
5109 mov2w_regOrLit (AOP(right), lit, size);
5110 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5112 // signed comparison
5113 // (add 2^n to both operands then perform an unsigned comparison)
5114 if (isAOP_LIT(right)) {
5115 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5116 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5118 if (litbyte == 0x80) {
5119 // left >= 0x80 -- always true, but more bytes to come
5120 pic16_mov2w (AOP(left), size);
5121 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5124 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5125 pic16_mov2w (AOP(left), size);
5126 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5130 /* using PRODL as a temporary register here */
5131 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133 pic16_mov2w (AOP(left), size);
5134 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135 pic16_emitpcode (POC_MOVWF, pctemp);
5136 pic16_mov2w (AOP(right), size);
5137 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138 pic16_emitpcode (POC_SUBFW, pctemp);
5139 //pic16_popReleaseTempReg(pctemp, 1);
5143 // compare remaining bytes (treat as unsigned case from above)
5144 templbl = newiTempLabel ( NULL );
5147 //DEBUGpc ("comparing bytes at offset %d", offs);
5148 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149 mov2w_regOrLit (AOP(right), lit, offs);
5150 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5152 pic16_emitpLabel (templbl->key);
5153 goto result_in_carry;
5157 /****************************************************
5158 * now CARRY contains the result of the comparison: *
5159 * SUBWF sets CARRY iff *
5160 * F-W >= 0 <==> F >= W <==> !(F < W) *
5161 * (F=left, W=right) *
5162 ****************************************************/
5165 if (result && AOP_TYPE(result) != AOP_CRY) {
5166 // value will be stored
5169 // value wil only be used in the following genSkipc()
5170 rIfx.condition ^= 1;
5174 correct_result_in_carry:
5176 // assign result to variable (if neccessary)
5177 if (result && AOP_TYPE(result) != AOP_CRY) {
5178 //DEBUGpc ("assign result");
5179 size = AOP_SIZE(result);
5181 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5183 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5186 // perform conditional jump
5188 //DEBUGpc ("generate control flow");
5197 static void genCmp (operand *left,operand *right,
5198 operand *result, iCode *ifx, int sign)
5200 int size; //, offset = 0 ;
5201 unsigned long lit = 0L,i = 0;
5202 resolvedIfx rFalseIfx;
5203 // resolvedIfx rTrueIfx;
5205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5208 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5215 resolveIfx(&rFalseIfx,ifx);
5216 truelbl = newiTempLabel(NULL);
5217 size = max(AOP_SIZE(left),AOP_SIZE(right));
5219 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5223 /* if literal is on the right then swap with left */
5224 if ((AOP_TYPE(right) == AOP_LIT)) {
5225 operand *tmp = right ;
5226 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5230 lit = (lit - 1) & mask;
5233 rFalseIfx.condition ^= 1;
5236 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5241 //if(IC_TRUE(ifx) == NULL)
5242 /* if left & right are bit variables */
5243 if (AOP_TYPE(left) == AOP_CRY &&
5244 AOP_TYPE(right) == AOP_CRY ) {
5245 assert (0 && "bit variables used in genCmp");
5246 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5249 /* subtract right from left if at the
5250 end the carry flag is set then we know that
5251 left is greater than right */
5253 symbol *lbl = newiTempLabel(NULL);
5256 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5261 if(AOP_TYPE(right) == AOP_LIT) {
5263 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5265 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5272 genSkipCond(&rFalseIfx,left,size-1,7);
5274 /* no need to compare to 0...*/
5275 /* NOTE: this is a de-generate compare that most certainly
5276 * creates some dead code. */
5277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5279 if(ifx) ifx->generated = 1;
5286 //i = (lit >> (size*8)) & 0xff;
5287 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5289 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291 i = ((0-lit) & 0xff);
5294 /* lit is 0x7f, all signed chars are less than
5295 * this except for 0x7f itself */
5296 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297 genSkipz2(&rFalseIfx,0);
5299 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301 genSkipc(&rFalseIfx);
5306 genSkipz2(&rFalseIfx,1);
5308 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309 genSkipc(&rFalseIfx);
5313 if(ifx) ifx->generated = 1;
5317 /* chars are out of the way. now do ints and longs */
5320 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5327 genSkipCond(&rFalseIfx,left,size,7);
5328 if(ifx) ifx->generated = 1;
5333 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5335 //rFalseIfx.condition ^= 1;
5336 //genSkipCond(&rFalseIfx,left,size,7);
5337 //rFalseIfx.condition ^= 1;
5339 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340 if(rFalseIfx.condition)
5341 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5343 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5350 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5352 if(rFalseIfx.condition) {
5354 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5360 genSkipc(&rFalseIfx);
5361 pic16_emitpLabel(truelbl->key);
5362 if(ifx) ifx->generated = 1;
5369 if( (lit & 0xff) == 0) {
5370 /* lower byte is zero */
5371 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372 i = ((lit >> 8) & 0xff) ^0x80;
5373 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376 genSkipc(&rFalseIfx);
5379 if(ifx) ifx->generated = 1;
5384 /* Special cases for signed longs */
5385 if( (lit & 0xffffff) == 0) {
5386 /* lower byte is zero */
5387 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388 i = ((lit >> 8*3) & 0xff) ^0x80;
5389 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392 genSkipc(&rFalseIfx);
5395 if(ifx) ifx->generated = 1;
5403 if(lit & (0x80 << (size*8))) {
5404 /* lit is negative */
5405 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5407 //genSkipCond(&rFalseIfx,left,size,7);
5409 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5411 if(rFalseIfx.condition)
5412 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5414 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5418 /* lit is positive */
5419 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421 if(rFalseIfx.condition)
5422 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5424 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5429 This works, but is only good for ints.
5430 It also requires a "known zero" register.
5431 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5434 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436 genSkipc(&rFalseIfx);
5438 pic16_emitpLabel(truelbl->key);
5439 if(ifx) ifx->generated = 1;
5443 /* There are no more special cases, so perform a general compare */
5445 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5450 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5452 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5454 //rFalseIfx.condition ^= 1;
5455 genSkipc(&rFalseIfx);
5457 pic16_emitpLabel(truelbl->key);
5459 if(ifx) ifx->generated = 1;
5466 /* sign is out of the way. So now do an unsigned compare */
5467 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5470 /* General case - compare to an unsigned literal on the right.*/
5472 i = (lit >> (size*8)) & 0xff;
5473 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5476 i = (lit >> (size*8)) & 0xff;
5479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5481 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5483 /* this byte of the lit is zero,
5484 *if it's not the last then OR in the variable */
5486 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5491 pic16_emitpLabel(lbl->key);
5492 // pic16_emitpLabel(truelbl->key);
5493 //if(emitFinalCheck)
5494 genSkipc(&rFalseIfx);
5496 pic16_emitpLabel(truelbl->key);
5498 if(ifx) ifx->generated = 1;
5505 if(AOP_TYPE(left) == AOP_LIT) {
5506 //symbol *lbl = newiTempLabel(NULL);
5508 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5511 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5514 if((lit == 0) && (sign == 0)){
5517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5519 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5521 genSkipz2(&rFalseIfx,0);
5522 if(ifx) ifx->generated = 1;
5529 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530 /* degenerate compare can never be true */
5531 if(rFalseIfx.condition == 0)
5532 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5534 if(ifx) ifx->generated = 1;
5539 /* signed comparisons to a literal byte */
5541 int lp1 = (lit+1) & 0xff;
5543 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5546 rFalseIfx.condition ^= 1;
5547 genSkipCond(&rFalseIfx,right,0,7);
5550 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552 genSkipz2(&rFalseIfx,1);
5555 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558 rFalseIfx.condition ^= 1;
5559 genSkipc(&rFalseIfx);
5563 /* unsigned comparisons to a literal byte */
5565 switch(lit & 0xff ) {
5567 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568 genSkipz2(&rFalseIfx,0);
5571 rFalseIfx.condition ^= 1;
5572 genSkipCond(&rFalseIfx,right,0,7);
5576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5579 rFalseIfx.condition ^= 1;
5580 if (AOP_TYPE(result) == AOP_CRY)
5581 genSkipc(&rFalseIfx);
5583 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5590 if(ifx) ifx->generated = 1;
5591 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5597 /* Size is greater than 1 */
5605 /* this means lit = 0xffffffff, or -1 */
5608 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609 rFalseIfx.condition ^= 1;
5610 genSkipCond(&rFalseIfx,right,size,7);
5611 if(ifx) ifx->generated = 1;
5613 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5622 if(rFalseIfx.condition) {
5623 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5627 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5629 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5633 if(rFalseIfx.condition) {
5634 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5635 pic16_emitpLabel(truelbl->key);
5637 rFalseIfx.condition ^= 1;
5638 genSkipCond(&rFalseIfx,right,s,7);
5641 if(ifx) ifx->generated = 1;
5643 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649 if((size == 1) && (0 == (lp1&0xff))) {
5650 /* lower byte of signed word is zero */
5651 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5652 i = ((lp1 >> 8) & 0xff) ^0x80;
5653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5657 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5659 if(ifx) ifx->generated = 1;
5662 rFalseIfx.condition ^= 1;
5663 genSkipc(&rFalseIfx);
5664 if(ifx) ifx->generated = 1;
5670 if(lit & (0x80 << (size*8))) {
5671 /* Lit is less than zero */
5672 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5673 //rFalseIfx.condition ^= 1;
5674 //genSkipCond(&rFalseIfx,left,size,7);
5675 //rFalseIfx.condition ^= 1;
5676 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5679 if(rFalseIfx.condition)
5680 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5682 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5686 /* Lit is greater than or equal to zero */
5687 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5688 //rFalseIfx.condition ^= 1;
5689 //genSkipCond(&rFalseIfx,right,size,7);
5690 //rFalseIfx.condition ^= 1;
5692 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5695 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696 if(rFalseIfx.condition)
5697 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5699 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5710 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5712 rFalseIfx.condition ^= 1;
5713 //rFalseIfx.condition = 1;
5714 genSkipc(&rFalseIfx);
5716 pic16_emitpLabel(truelbl->key);
5718 if(ifx) ifx->generated = 1;
5721 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5728 /* compare word or long to an unsigned literal on the right.*/
5733 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5736 break; /* handled above */
5739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742 genSkipz2(&rFalseIfx,0);
5746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5748 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5751 if(rFalseIfx.condition)
5752 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5754 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5757 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5760 rFalseIfx.condition ^= 1;
5761 genSkipc(&rFalseIfx);
5764 pic16_emitpLabel(truelbl->key);
5766 if(ifx) ifx->generated = 1;
5768 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777 i = (lit >> (size*8)) & 0xff;
5779 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5783 i = (lit >> (size*8)) & 0xff;
5786 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5788 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5790 /* this byte of the lit is zero,
5791 * if it's not the last then OR in the variable */
5793 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5798 pic16_emitpLabel(lbl->key);
5800 rFalseIfx.condition ^= 1;
5802 genSkipc(&rFalseIfx);
5806 pic16_emitpLabel(truelbl->key);
5807 if(ifx) ifx->generated = 1;
5809 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5815 /* Compare two variables */
5817 DEBUGpic16_emitcode(";sign","%d",sign);
5821 /* Sigh. thus sucks... */
5825 pctemp = pic16_popGetTempReg(1);
5826 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832 pic16_popReleaseTempReg(pctemp, 1);
5834 /* Signed char comparison */
5835 /* Special thanks to Nikolai Golovchenko for this snippet */
5836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5839 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5844 genSkipc(&rFalseIfx);
5846 if(ifx) ifx->generated = 1;
5848 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5856 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5861 /* The rest of the bytes of a multi-byte compare */
5865 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5868 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5874 pic16_emitpLabel(lbl->key);
5876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5877 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5878 (AOP_TYPE(result) == AOP_REG)) {
5879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5882 genSkipc(&rFalseIfx);
5884 //genSkipc(&rFalseIfx);
5885 if(ifx) ifx->generated = 1;
5888 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5896 if ((AOP_TYPE(result) != AOP_CRY)
5897 && AOP_SIZE(result)) {
5898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5900 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5902 pic16_outBitC(result);
5904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5905 /* if the result is used in the next
5906 ifx conditional branch then generate
5907 code a little differently */
5909 genIfxJump (ifx,"c");
5911 pic16_outBitC(result);
5912 /* leave the result in acc */
5917 #elif 0 /* VR version of genCmp() */ /* } else { */
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921 operand *result, int offset, int invert_op)
5925 /* check condition, > or < ?? */
5926 if(rIfx->condition != 0)invert_op ^= 1;
5928 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5930 if(!ifx)invert_op ^= 1;
5932 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5936 if(!invert_op)return POC_CPFSGT;
5937 else return POC_CPFSLT;
5940 static int compareAopfirstpass=1;
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943 operand *oper, int offset, operand *result,
5944 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5950 /* invert if there is a result to be loaded, in order to fit,
5951 * SETC/CLRC sequence */
5952 if(AOP_SIZE(result))invert_op ^= 1;
5954 // if(sign && !offset)invert_op ^= 1;
5956 // if(sign)invert_op ^= 1;
5958 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5960 if(AOP_SIZE(result) && compareAopfirstpass) {
5963 pic16_emitpcode(POC_SETF, pcop2);
5968 pic16_emitpcode(POC_CLRF, pcop2);
5974 compareAopfirstpass = 0;
5976 /* there is a bug when comparing operands with size > 1,
5977 * because higher bytes can be equal and test should be performed
5978 * to the next lower byte, current algorithm, considers operands
5979 * inequal in these cases! -- VR 20041107 */
5983 pic16_emitpcode(op, pcop);
5985 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5988 if((!sign || !offset) && AOP_SIZE(result)) {
5991 pic16_emitpcode(POC_CLRF, pcop2);
5996 pic16_emitpcode(POC_SETF, pcop2);
6001 /* don't emit final branch (offset == 0) */
6005 pic16_emitpcode(POC_RRCF, pcop2);
6007 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6010 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6014 truelbl = newiTempLabel( NULL );
6015 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6019 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020 pic16_emitpLabel(truelbl->key);
6022 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6027 static void genCmp (operand *left, operand *right,
6028 operand *result, iCode *ifx, int sign)
6032 resolvedIfx rFalseIfx;
6033 symbol *falselbl, *tlbl;
6037 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6039 resolveIfx(&rFalseIfx, ifx);
6040 size = max(AOP_SIZE(left), AOP_SIZE(right));
6042 /* if left & right are bit variables */
6043 if(AOP_TYPE(left) == AOP_CRY
6044 && AOP_TYPE(right) == AOP_CRY ) {
6046 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6049 werror(W_POSSBUG2, __FILE__, __LINE__);
6053 /* if literal is on the right then swap with left */
6054 if((AOP_TYPE(right) == AOP_LIT)) {
6055 operand *tmp = right ;
6056 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6058 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6060 // lit = (lit - 1) & mask;
6063 rFalseIfx.condition ^= 1; /* reverse compare */
6065 if ((AOP_TYPE(left) == AOP_LIT)) {
6066 /* float compares are handled by support functions */
6067 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6070 /* actual comparing algorithm */
6071 // size = AOP_SIZE( right );
6073 falselbl = newiTempLabel( NULL );
6074 if(AOP_TYPE(left) == AOP_LIT) {
6075 /* compare to literal */
6076 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6079 pCodeOp *pct, *pct2;
6082 /* signed compare */
6083 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6085 /* using PRODL:PRODH as a temporary register here */
6086 pct = pic16_popCopyReg(&pic16_pc_prodl);
6087 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6088 tlbl = newiTempLabel( NULL );
6090 /* first compare signs:
6091 * a. if both are positive, compare just like unsigned
6092 * b. if both are negative, invert cmpop, compare just like unsigned
6093 * c. if different signs, determine the result directly */
6099 tlbl1 = newiTempLabel( NULL );
6100 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6104 /* literal is zero or positive:
6105 * a. if carry is zero, too, continue compare,
6106 * b. if carry is set, then continue depending on cmpop ^ condition:
6107 * 1. '<' return false (literal < variable),
6108 * 2. '>' return true (literal > variable) */
6109 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6110 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6113 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6118 /* literal is negative:
6119 * a. if carry is set, too, continue compare,
6120 * b. if carry is zero, then continue depending on cmpop ^ condition:
6121 * 1. '<' return true (literal < variable),
6122 * 2. '>' return false (literal > variable) */
6123 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6124 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6126 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6132 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6134 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6135 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6140 pic16_emitpLabel( tlbl1->key );
6143 compareAopfirstpass=1;
6144 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6145 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 // pic16_emitpcode(POC_MOVWF, pct);
6148 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6150 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6155 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6156 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6157 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6158 // pic16_emitpcode(POC_MOVWF, pct);
6160 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6161 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6162 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6163 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6167 if(ifx)ifx->generated = 1;
6169 if(AOP_SIZE(result)) {
6170 pic16_emitpLabel(tlbl->key);
6171 pic16_emitpLabel(falselbl->key);
6172 pic16_outBitOp( result, pct2 );
6174 pic16_emitpLabel(tlbl->key);
6178 /* unsigned compare */
6179 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6181 compareAopfirstpass=1;
6184 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6185 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6188 if(ifx)ifx->generated = 1;
6190 if(AOP_SIZE(result)) {
6191 pic16_emitpLabel(falselbl->key);
6192 pic16_outBitC( result );
6197 /* compare registers */
6198 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6202 pCodeOp *pct, *pct2;
6204 /* signed compare */
6205 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6207 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6208 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6209 tlbl = newiTempLabel( NULL );
6211 compareAopfirstpass=1;
6214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6215 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217 pic16_emitpcode(POC_MOVWF, pct);
6219 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6220 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6221 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6223 /* WREG already holds left + 0x80 */
6224 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6227 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6228 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230 pic16_emitpcode(POC_MOVWF, pct);
6232 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6233 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6234 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6236 /* WREG already holds left + 0x80 */
6237 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6238 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6241 if(ifx)ifx->generated = 1;
6243 if(AOP_SIZE(result)) {
6244 pic16_emitpLabel(tlbl->key);
6245 pic16_emitpLabel(falselbl->key);
6246 pic16_outBitOp( result, pct2 );
6248 pic16_emitpLabel(tlbl->key);
6252 /* unsigned compare */
6253 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6255 compareAopfirstpass=1;
6258 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6259 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6263 if(ifx)ifx->generated = 1;
6264 if(AOP_SIZE(result)) {
6266 pic16_emitpLabel(falselbl->key);
6267 pic16_outBitC( result );
6278 /*-----------------------------------------------------------------*/
6279 /* genCmpGt :- greater than comparison */
6280 /*-----------------------------------------------------------------*/
6281 static void genCmpGt (iCode *ic, iCode *ifx)
6283 operand *left, *right, *result;
6284 sym_link *letype , *retype;
6290 right= IC_RIGHT(ic);
6291 result = IC_RESULT(ic);
6293 letype = getSpec(operandType(left));
6294 retype =getSpec(operandType(right));
6295 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6296 /* assign the amsops */
6297 pic16_aopOp (left,ic,FALSE);
6298 pic16_aopOp (right,ic,FALSE);
6299 pic16_aopOp (result,ic,TRUE);
6301 genCmp(right, left, result, ifx, sign);
6303 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6305 pic16_freeAsmop(result,NULL,ic,TRUE);
6308 /*-----------------------------------------------------------------*/
6309 /* genCmpLt - less than comparisons */
6310 /*-----------------------------------------------------------------*/
6311 static void genCmpLt (iCode *ic, iCode *ifx)
6313 operand *left, *right, *result;
6314 sym_link *letype , *retype;
6320 right= IC_RIGHT(ic);
6321 result = IC_RESULT(ic);
6323 letype = getSpec(operandType(left));
6324 retype =getSpec(operandType(right));
6325 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6327 /* assign the amsops */
6328 pic16_aopOp (left,ic,FALSE);
6329 pic16_aopOp (right,ic,FALSE);
6330 pic16_aopOp (result,ic,TRUE);
6332 genCmp(left, right, result, ifx, sign);
6334 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6336 pic16_freeAsmop(result,NULL,ic,TRUE);
6341 // FIXME reenable literal optimisation when the pic16 port is stable
6343 /*-----------------------------------------------------------------*/
6344 /* genc16bit2lit - compare a 16 bit value to a literal */
6345 /*-----------------------------------------------------------------*/
6346 static void genc16bit2lit(operand *op, int lit, int offset)
6350 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6351 if( (lit&0xff) == 0)
6356 switch( BYTEofLONG(lit,i)) {
6358 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6364 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6367 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6368 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6373 switch( BYTEofLONG(lit,i)) {
6375 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6379 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6383 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6386 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6388 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6397 /*-----------------------------------------------------------------*/
6398 /* gencjneshort - compare and jump if not equal */
6399 /*-----------------------------------------------------------------*/
6400 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6402 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6404 int res_offset = 0; /* the result may be a different size then left or right */
6405 int res_size = AOP_SIZE(result);
6407 symbol *lbl, *lbl_done;
6409 unsigned long lit = 0L;
6410 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6412 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6413 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6415 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6416 resolveIfx(&rIfx,ifx);
6417 lbl = newiTempLabel(NULL);
6418 lbl_done = newiTempLabel(NULL);
6421 /* if the left side is a literal or
6422 if the right is in a pointer register and left
6424 if ((AOP_TYPE(left) == AOP_LIT) ||
6425 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6430 if(AOP_TYPE(right) == AOP_LIT)
6431 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6433 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6434 preserve_result = 1;
6436 if(result && !preserve_result)
6439 for(i = 0; i < AOP_SIZE(result); i++)
6440 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6444 /* if the right side is a literal then anything goes */
6445 if (AOP_TYPE(right) == AOP_LIT &&
6446 AOP_TYPE(left) != AOP_DIR ) {
6449 genc16bit2lit(left, lit, 0);
6451 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6454 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6457 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6458 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6460 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6466 if(res_offset < res_size-1)
6474 /* if the right side is in a register or in direct space or
6475 if the left is a pointer register & right is not */
6476 else if (AOP_TYPE(right) == AOP_REG ||
6477 AOP_TYPE(right) == AOP_DIR ||
6478 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6479 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6480 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6481 int lbl_key = lbl->key;
6484 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6485 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6487 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6488 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6489 __FUNCTION__,__LINE__);
6493 /* switch(size) { */
6495 /* genc16bit2lit(left, lit, 0); */
6497 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6502 if((AOP_TYPE(left) == AOP_DIR) &&
6503 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6505 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6508 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6510 switch (lit & 0xff) {
6512 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6515 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6516 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6521 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6523 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6524 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6528 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6529 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6534 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6537 if(AOP_TYPE(result) == AOP_CRY) {
6538 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6543 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6545 /* fix me. probably need to check result size too */
6546 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6551 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6552 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6559 if(res_offset < res_size-1)
6564 } else if(AOP_TYPE(right) == AOP_REG &&
6565 AOP_TYPE(left) != AOP_DIR){
6568 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6569 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6570 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6575 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6577 if(res_offset < res_size-1)
6582 /* right is a pointer reg need both a & b */
6584 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6586 pic16_emitcode("mov","b,%s",l);
6587 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6593 if(result && preserve_result)
6596 for(i = 0; i < AOP_SIZE(result); i++)
6597 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6600 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6602 if(result && preserve_result)
6603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6606 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6608 pic16_emitpLabel(lbl->key);
6610 if(result && preserve_result)
6613 for(i = 0; i < AOP_SIZE(result); i++)
6614 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6616 pic16_emitpLabel(lbl_done->key);
6619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6627 /*-----------------------------------------------------------------*/
6628 /* gencjne - compare and jump if not equal */
6629 /*-----------------------------------------------------------------*/
6630 static void gencjne(operand *left, operand *right, iCode *ifx)
6632 symbol *tlbl = newiTempLabel(NULL);
6634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6635 gencjneshort(left, right, lbl);
6637 pic16_emitcode("mov","a,%s",one);
6638 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6639 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6640 pic16_emitcode("clr","a");
6641 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6643 pic16_emitpLabel(lbl->key);
6644 pic16_emitpLabel(tlbl->key);
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitOp - check if operand has to be treated as literal */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitOp(operand *op)
6655 return ((AOP_TYPE(op) == AOP_LIT)
6656 || ( (AOP_TYPE(op) == AOP_PCODE)
6657 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6658 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6661 /*-----------------------------------------------------------------*/
6662 /* is_LitAOp - check if operand has to be treated as literal */
6663 /*-----------------------------------------------------------------*/
6664 static bool is_LitAOp(asmop *aop)
6666 return ((aop->type == AOP_LIT)
6667 || ( (aop->type == AOP_PCODE)
6668 && ( (aop->aopu.pcop->type == PO_LITERAL)
6669 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6674 /*-----------------------------------------------------------------*/
6675 /* genCmpEq - generates code for equal to */
6676 /*-----------------------------------------------------------------*/
6677 static void genCmpEq (iCode *ic, iCode *ifx)
6679 operand *left, *right, *result;
6680 symbol *falselbl = newiTempLabel(NULL);
6681 symbol *donelbl = newiTempLabel(NULL);
6683 int preserve_result = 0;
6684 int generate_result = 0;
6686 unsigned long lit = -1;
6690 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6691 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6692 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6694 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6696 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6698 werror(W_POSSBUG2, __FILE__, __LINE__);
6699 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6700 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6704 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6706 operand *tmp = right ;
6711 if (AOP_TYPE(right) == AOP_LIT) {
6712 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6715 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6716 preserve_result = 1;
6718 if(result && AOP_SIZE(result))
6719 generate_result = 1;
6721 if(generate_result && !preserve_result)
6723 for(i = 0; i < AOP_SIZE(result); i++)
6724 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6727 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6728 for(i=0; i < AOP_SIZE(left); i++)
6730 if(AOP_TYPE(left) != AOP_ACC)
6733 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6737 if(is_LitOp(right)) {
6738 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6739 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6742 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6744 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6749 if(generate_result && preserve_result)
6751 for(i = 0; i < AOP_SIZE(result); i++)
6752 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6756 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6758 if(generate_result && preserve_result)
6759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6761 if(ifx && IC_TRUE(ifx))
6762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6764 if(ifx && IC_FALSE(ifx))
6765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6767 pic16_emitpLabel(falselbl->key);
6771 if(ifx && IC_FALSE(ifx))
6772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6774 if(generate_result && preserve_result)
6776 for(i = 0; i < AOP_SIZE(result); i++)
6777 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6780 pic16_emitpLabel(donelbl->key);
6786 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6787 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6788 pic16_freeAsmop(result,NULL,ic,TRUE);
6794 // old version kept for reference
6796 /*-----------------------------------------------------------------*/
6797 /* genCmpEq - generates code for equal to */
6798 /*-----------------------------------------------------------------*/
6799 static void genCmpEq (iCode *ic, iCode *ifx)
6801 operand *left, *right, *result;
6802 unsigned long lit = 0L;
6804 symbol *falselbl = newiTempLabel(NULL);
6807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6810 DEBUGpic16_emitcode ("; ifx is non-null","");
6812 DEBUGpic16_emitcode ("; ifx is null","");
6814 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6815 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6816 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6818 size = max(AOP_SIZE(left),AOP_SIZE(right));
6820 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6822 /* if literal, literal on the right or
6823 if the right is in a pointer register and left
6825 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6826 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6827 operand *tmp = right ;
6833 if(ifx && !AOP_SIZE(result)){
6835 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6836 /* if they are both bit variables */
6837 if (AOP_TYPE(left) == AOP_CRY &&
6838 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6839 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6840 if(AOP_TYPE(right) == AOP_LIT){
6841 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6843 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844 pic16_emitcode("cpl","c");
6845 } else if(lit == 1L) {
6846 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6848 pic16_emitcode("clr","c");
6850 /* AOP_TYPE(right) == AOP_CRY */
6852 symbol *lbl = newiTempLabel(NULL);
6853 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6854 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6855 pic16_emitcode("cpl","c");
6856 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6858 /* if true label then we jump if condition
6860 tlbl = newiTempLabel(NULL);
6861 if ( IC_TRUE(ifx) ) {
6862 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6863 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6865 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6866 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6868 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6871 /* left and right are both bit variables, result is carry */
6874 resolveIfx(&rIfx,ifx);
6876 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6877 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6878 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6879 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6884 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6886 /* They're not both bit variables. Is the right a literal? */
6887 if(AOP_TYPE(right) == AOP_LIT) {
6888 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6893 switch(lit & 0xff) {
6895 if ( IC_TRUE(ifx) ) {
6896 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6900 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6905 if ( IC_TRUE(ifx) ) {
6906 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6910 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6911 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6917 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6922 /* end of size == 1 */
6926 genc16bit2lit(left,lit,offset);
6929 /* end of size == 2 */
6934 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6935 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6936 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6937 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6940 /* search for patterns that can be optimized */
6942 genc16bit2lit(left,lit,0);
6946 emitSKPZ; // if hi word unequal
6948 emitSKPNZ; // if hi word equal
6950 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6951 genc16bit2lit(left,lit,2);
6954 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6955 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6959 pic16_emitpLabel(falselbl->key);
6968 } else if(AOP_TYPE(right) == AOP_CRY ) {
6969 /* we know the left is not a bit, but that the right is */
6970 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6971 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6972 pic16_popGet(AOP(right),offset));
6973 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6975 /* if the two are equal, then W will be 0 and the Z bit is set
6976 * we could test Z now, or go ahead and check the high order bytes if
6977 * the variable we're comparing is larger than a byte. */
6980 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6982 if ( IC_TRUE(ifx) ) {
6984 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6985 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6988 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6989 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6993 /* They're both variables that are larger than bits */
6996 tlbl = newiTempLabel(NULL);
6999 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7000 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7002 if ( IC_TRUE(ifx) ) {
7006 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7009 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7013 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7017 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7022 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7024 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7025 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7029 if(s>1 && IC_TRUE(ifx)) {
7030 pic16_emitpLabel(tlbl->key);
7031 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7035 /* mark the icode as generated */
7040 /* if they are both bit variables */
7041 if (AOP_TYPE(left) == AOP_CRY &&
7042 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7043 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7044 if(AOP_TYPE(right) == AOP_LIT){
7045 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7047 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048 pic16_emitcode("cpl","c");
7049 } else if(lit == 1L) {
7050 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7052 pic16_emitcode("clr","c");
7054 /* AOP_TYPE(right) == AOP_CRY */
7056 symbol *lbl = newiTempLabel(NULL);
7057 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7058 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7059 pic16_emitcode("cpl","c");
7060 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7063 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7064 pic16_outBitC(result);
7068 genIfxJump (ifx,"c");
7071 /* if the result is used in an arithmetic operation
7072 then put the result in place */
7073 pic16_outBitC(result);
7076 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7077 gencjne(left,right,result,ifx);
7080 gencjne(left,right,newiTempLabel(NULL));
7082 if(IC_TRUE(ifx)->key)
7083 gencjne(left,right,IC_TRUE(ifx)->key);
7085 gencjne(left,right,IC_FALSE(ifx)->key);
7089 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7090 pic16_aopPut(AOP(result),"a",0);
7095 genIfxJump (ifx,"a");
7099 /* if the result is used in an arithmetic operation
7100 then put the result in place */
7102 if (AOP_TYPE(result) != AOP_CRY)
7103 pic16_outAcc(result);
7105 /* leave the result in acc */
7109 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7110 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7111 pic16_freeAsmop(result,NULL,ic,TRUE);
7115 /*-----------------------------------------------------------------*/
7116 /* ifxForOp - returns the icode containing the ifx for operand */
7117 /*-----------------------------------------------------------------*/
7118 static iCode *ifxForOp ( operand *op, iCode *ic )
7122 /* if true symbol then needs to be assigned */
7123 if (IS_TRUE_SYMOP(op))
7126 /* if this has register type condition and
7127 the next instruction is ifx with the same operand
7128 and live to of the operand is upto the ifx only then */
7130 && ic->next->op == IFX
7131 && IC_COND(ic->next)->key == op->key
7132 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7134 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7140 ic->next->op == IFX &&
7141 IC_COND(ic->next)->key == op->key) {
7142 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7147 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7149 ic->next->op == IFX)
7150 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7153 ic->next->op == IFX &&
7154 IC_COND(ic->next)->key == op->key) {
7155 DEBUGpic16_emitcode ("; "," key is okay");
7156 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7157 OP_SYMBOL(op)->liveTo,
7162 /* the code below is completely untested
7163 * it just allows ulong2fs.c compile -- VR */
7166 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7167 __FILE__, __FUNCTION__, __LINE__);
7169 /* if this has register type condition and
7170 the next instruction is ifx with the same operand
7171 and live to of the operand is upto the ifx only then */
7173 ic->next->op == IFX &&
7174 IC_COND(ic->next)->key == op->key &&
7175 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7179 ic->next->op == IFX &&
7180 IC_COND(ic->next)->key == op->key) {
7181 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7185 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7186 __FILE__, __FUNCTION__, __LINE__);
7188 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7193 /*-----------------------------------------------------------------*/
7194 /* genAndOp - for && operation */
7195 /*-----------------------------------------------------------------*/
7196 static void genAndOp (iCode *ic)
7198 operand *left,*right, *result;
7203 /* note here that && operations that are in an
7204 if statement are taken away by backPatchLabels
7205 only those used in arthmetic operations remain */
7206 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7207 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7208 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7210 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7212 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7213 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7216 /* if both are bit variables */
7217 /* if (AOP_TYPE(left) == AOP_CRY && */
7218 /* AOP_TYPE(right) == AOP_CRY ) { */
7219 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7220 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7221 /* pic16_outBitC(result); */
7223 /* tlbl = newiTempLabel(NULL); */
7224 /* pic16_toBoolean(left); */
7225 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7226 /* pic16_toBoolean(right); */
7227 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7228 /* pic16_outBitAcc(result); */
7231 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7232 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7233 pic16_freeAsmop(result,NULL,ic,TRUE);
7237 /*-----------------------------------------------------------------*/
7238 /* genOrOp - for || operation */
7239 /*-----------------------------------------------------------------*/
7242 modified this code, but it doesn't appear to ever get called
7245 static void genOrOp (iCode *ic)
7247 operand *left,*right, *result;
7252 /* note here that || operations that are in an
7253 if statement are taken away by backPatchLabels
7254 only those used in arthmetic operations remain */
7255 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7256 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7257 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7259 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7261 /* if both are bit variables */
7262 if (AOP_TYPE(left) == AOP_CRY &&
7263 AOP_TYPE(right) == AOP_CRY ) {
7264 pic16_emitcode("clrc","");
7265 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7266 AOP(left)->aopu.aop_dir,
7267 AOP(left)->aopu.aop_dir);
7268 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7269 AOP(right)->aopu.aop_dir,
7270 AOP(right)->aopu.aop_dir);
7271 pic16_emitcode("setc","");
7274 tlbl = newiTempLabel(NULL);
7275 pic16_toBoolean(left);
7277 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7278 pic16_toBoolean(right);
7279 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7281 pic16_outBitAcc(result);
7284 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7285 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7286 pic16_freeAsmop(result,NULL,ic,TRUE);
7289 /*-----------------------------------------------------------------*/
7290 /* isLiteralBit - test if lit == 2^n */
7291 /*-----------------------------------------------------------------*/
7292 static int isLiteralBit(unsigned long lit)
7294 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7295 0x100L,0x200L,0x400L,0x800L,
7296 0x1000L,0x2000L,0x4000L,0x8000L,
7297 0x10000L,0x20000L,0x40000L,0x80000L,
7298 0x100000L,0x200000L,0x400000L,0x800000L,
7299 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7300 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7303 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7304 for(idx = 0; idx < 32; idx++)
7310 /*-----------------------------------------------------------------*/
7311 /* continueIfTrue - */
7312 /*-----------------------------------------------------------------*/
7313 static void continueIfTrue (iCode *ic)
7317 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7321 /*-----------------------------------------------------------------*/
7323 /*-----------------------------------------------------------------*/
7324 static void jumpIfTrue (iCode *ic)
7328 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7332 /*-----------------------------------------------------------------*/
7333 /* jmpTrueOrFalse - */
7334 /*-----------------------------------------------------------------*/
7335 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7337 // ugly but optimized by peephole
7340 symbol *nlbl = newiTempLabel(NULL);
7341 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7342 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7343 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7344 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7346 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7347 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7352 /*-----------------------------------------------------------------*/
7353 /* genAnd - code for and */
7354 /*-----------------------------------------------------------------*/
7355 static void genAnd (iCode *ic, iCode *ifx)
7357 operand *left, *right, *result;
7359 unsigned long lit = 0L;
7365 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7366 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7367 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7369 resolveIfx(&rIfx,ifx);
7371 /* if left is a literal & right is not then exchange them */
7372 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7373 AOP_NEEDSACC(left)) {
7374 operand *tmp = right ;
7379 /* if result = right then exchange them */
7380 if(pic16_sameRegs(AOP(result),AOP(right))){
7381 operand *tmp = right ;
7386 /* if right is bit then exchange them */
7387 if (AOP_TYPE(right) == AOP_CRY &&
7388 AOP_TYPE(left) != AOP_CRY){
7389 operand *tmp = right ;
7393 if(AOP_TYPE(right) == AOP_LIT)
7394 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7396 size = AOP_SIZE(result);
7398 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7401 // result = bit & yy;
7402 if (AOP_TYPE(left) == AOP_CRY){
7403 // c = bit & literal;
7404 if(AOP_TYPE(right) == AOP_LIT){
7406 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7409 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7412 if(size && (AOP_TYPE(result) == AOP_CRY)){
7413 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7416 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7420 pic16_emitcode("clr","c");
7423 if (AOP_TYPE(right) == AOP_CRY){
7425 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7426 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7429 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7431 pic16_emitcode("rrc","a");
7432 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7438 pic16_outBitC(result);
7440 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7441 genIfxJump(ifx, "c");
7445 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7446 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7447 if((AOP_TYPE(right) == AOP_LIT) &&
7448 (AOP_TYPE(result) == AOP_CRY) &&
7449 (AOP_TYPE(left) != AOP_CRY)){
7450 int posbit = isLiteralBit(lit);
7454 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7457 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7463 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7466 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7467 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7470 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7471 size = AOP_SIZE(left);
7474 int bp = posbit, ofs=0;
7481 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7482 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7486 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7487 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7489 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7496 symbol *tlbl = newiTempLabel(NULL);
7497 int sizel = AOP_SIZE(left);
7503 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7505 /* patch provided by Aaron Colwell */
7506 if((posbit = isLiteralBit(bytelit)) != 0) {
7507 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7508 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7509 (posbit-1),0, PO_GPR_REGISTER));
7511 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7512 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7514 if (bytelit == 0xff) {
7515 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7516 * a peephole could optimize it out -- VR */
7517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7519 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7520 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7523 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7524 pic16_popGetLabel(tlbl->key));
7528 /* old code, left here for reference -- VR 09/2004 */
7529 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7531 if((posbit = isLiteralBit(bytelit)) != 0)
7532 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7534 if(bytelit != 0x0FFL)
7535 pic16_emitcode("anl","a,%s",
7536 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7537 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7543 // bit = left & literal
7546 pic16_emitpLabel(tlbl->key);
7548 // if(left & literal)
7551 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7554 pic16_emitpLabel(tlbl->key);
7559 pic16_outBitC(result);
7563 /* if left is same as result */
7564 if(pic16_sameRegs(AOP(result),AOP(left))){
7566 for(;size--; offset++,lit>>=8) {
7567 if(AOP_TYPE(right) == AOP_LIT){
7568 switch(lit & 0xff) {
7570 /* and'ing with 0 has clears the result */
7571 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7575 /* and'ing with 0xff is a nop when the result and left are the same */
7580 int p = pic16_my_powof2( (~lit) & 0xff );
7582 /* only one bit is set in the literal, so use a bcf instruction */
7583 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7584 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7587 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7588 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7589 if(know_W != (lit&0xff))
7590 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7592 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7597 if (AOP_TYPE(left) == AOP_ACC) {
7598 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7600 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7601 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7608 // left & result in different registers
7609 if(AOP_TYPE(result) == AOP_CRY){
7611 // if(size), result in bit
7612 // if(!size && ifx), conditional oper: if(left & right)
7613 symbol *tlbl = newiTempLabel(NULL);
7614 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7616 pic16_emitcode("setb","c");
7618 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7619 pic16_emitcode("anl","a,%s",
7620 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7621 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7626 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7627 pic16_outBitC(result);
7629 jmpTrueOrFalse(ifx, tlbl);
7631 for(;(size--);offset++) {
7633 // result = left & right
7634 if(AOP_TYPE(right) == AOP_LIT){
7635 int t = (lit >> (offset*8)) & 0x0FFL;
7638 pic16_emitcode("clrf","%s",
7639 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7643 pic16_emitcode("movf","%s,w",
7644 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645 pic16_emitcode("movwf","%s",
7646 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7648 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7651 pic16_emitcode("movlw","0x%x",t);
7652 pic16_emitcode("andwf","%s,w",
7653 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654 pic16_emitcode("movwf","%s",
7655 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7657 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7658 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7659 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7664 if (AOP_TYPE(left) == AOP_ACC) {
7665 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7666 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7668 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7669 pic16_emitcode("andwf","%s,w",
7670 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7671 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7672 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7674 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7675 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7681 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7682 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7683 pic16_freeAsmop(result,NULL,ic,TRUE);
7686 /*-----------------------------------------------------------------*/
7687 /* genOr - code for or */
7688 /*-----------------------------------------------------------------*/
7689 static void genOr (iCode *ic, iCode *ifx)
7691 operand *left, *right, *result;
7693 unsigned long lit = 0L;
7695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7697 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7698 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7699 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7701 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7703 /* if left is a literal & right is not then exchange them */
7704 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7705 AOP_NEEDSACC(left)) {
7706 operand *tmp = right ;
7711 /* if result = right then exchange them */
7712 if(pic16_sameRegs(AOP(result),AOP(right))){
7713 operand *tmp = right ;
7718 /* if right is bit then exchange them */
7719 if (AOP_TYPE(right) == AOP_CRY &&
7720 AOP_TYPE(left) != AOP_CRY){
7721 operand *tmp = right ;
7726 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7728 if(AOP_TYPE(right) == AOP_LIT)
7729 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7731 size = AOP_SIZE(result);
7735 if (AOP_TYPE(left) == AOP_CRY){
7736 if(AOP_TYPE(right) == AOP_LIT){
7737 // c = bit & literal;
7739 // lit != 0 => result = 1
7740 if(AOP_TYPE(result) == AOP_CRY){
7742 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7743 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7744 // AOP(result)->aopu.aop_dir,
7745 // AOP(result)->aopu.aop_dir);
7747 continueIfTrue(ifx);
7751 // lit == 0 => result = left
7752 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7754 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7757 if (AOP_TYPE(right) == AOP_CRY){
7758 if(pic16_sameRegs(AOP(result),AOP(left))){
7760 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7761 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7762 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7764 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7765 AOP(result)->aopu.aop_dir,
7766 AOP(result)->aopu.aop_dir);
7767 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7768 AOP(right)->aopu.aop_dir,
7769 AOP(right)->aopu.aop_dir);
7770 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7771 AOP(result)->aopu.aop_dir,
7772 AOP(result)->aopu.aop_dir);
7774 if( AOP_TYPE(result) == AOP_ACC) {
7775 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7776 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7782 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7783 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7784 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7785 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7787 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7788 AOP(result)->aopu.aop_dir,
7789 AOP(result)->aopu.aop_dir);
7790 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7791 AOP(right)->aopu.aop_dir,
7792 AOP(right)->aopu.aop_dir);
7793 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7794 AOP(left)->aopu.aop_dir,
7795 AOP(left)->aopu.aop_dir);
7796 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7797 AOP(result)->aopu.aop_dir,
7798 AOP(result)->aopu.aop_dir);
7803 symbol *tlbl = newiTempLabel(NULL);
7804 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7807 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7808 if( AOP_TYPE(right) == AOP_ACC) {
7809 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7811 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7812 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7817 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7818 pic16_emitcode(";XXX setb","c");
7819 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7820 AOP(left)->aopu.aop_dir,tlbl->key+100);
7821 pic16_toBoolean(right);
7822 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7823 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7824 jmpTrueOrFalse(ifx, tlbl);
7828 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7835 pic16_outBitC(result);
7837 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7838 genIfxJump(ifx, "c");
7842 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7843 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7844 if((AOP_TYPE(right) == AOP_LIT) &&
7845 (AOP_TYPE(result) == AOP_CRY) &&
7846 (AOP_TYPE(left) != AOP_CRY)){
7848 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7851 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7853 continueIfTrue(ifx);
7856 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7857 // lit = 0, result = boolean(left)
7859 pic16_emitcode(";XXX setb","c");
7860 pic16_toBoolean(right);
7862 symbol *tlbl = newiTempLabel(NULL);
7863 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7865 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7867 genIfxJump (ifx,"a");
7871 pic16_outBitC(result);
7875 /* if left is same as result */
7876 if(pic16_sameRegs(AOP(result),AOP(left))){
7878 for(;size--; offset++,lit>>=8) {
7879 if(AOP_TYPE(right) == AOP_LIT){
7880 if((lit & 0xff) == 0)
7881 /* or'ing with 0 has no effect */
7884 int p = pic16_my_powof2(lit & 0xff);
7886 /* only one bit is set in the literal, so use a bsf instruction */
7887 pic16_emitpcode(POC_BSF,
7888 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7890 if(know_W != (lit & 0xff))
7891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7892 know_W = lit & 0xff;
7893 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7898 if (AOP_TYPE(left) == AOP_ACC) {
7899 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7900 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7903 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7905 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7906 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7912 // left & result in different registers
7913 if(AOP_TYPE(result) == AOP_CRY){
7915 // if(size), result in bit
7916 // if(!size && ifx), conditional oper: if(left | right)
7917 symbol *tlbl = newiTempLabel(NULL);
7918 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7919 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7923 pic16_emitcode(";XXX setb","c");
7925 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926 pic16_emitcode(";XXX orl","a,%s",
7927 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7933 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7934 pic16_outBitC(result);
7936 jmpTrueOrFalse(ifx, tlbl);
7937 } else for(;(size--);offset++){
7939 // result = left & right
7940 if(AOP_TYPE(right) == AOP_LIT){
7941 int t = (lit >> (offset*8)) & 0x0FFL;
7944 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7947 // pic16_emitcode("movf","%s,w",
7948 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7949 // pic16_emitcode("movwf","%s",
7950 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7954 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7957 // pic16_emitcode("movlw","0x%x",t);
7958 // pic16_emitcode("iorwf","%s,w",
7959 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7960 // pic16_emitcode("movwf","%s",
7961 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7967 // faster than result <- left, anl result,right
7968 // and better if result is SFR
7969 if (AOP_TYPE(left) == AOP_ACC) {
7970 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7971 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7973 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7974 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7976 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7977 // pic16_emitcode("iorwf","%s,w",
7978 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7980 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7981 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7986 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7987 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7988 pic16_freeAsmop(result,NULL,ic,TRUE);
7991 /*-----------------------------------------------------------------*/
7992 /* genXor - code for xclusive or */
7993 /*-----------------------------------------------------------------*/
7994 static void genXor (iCode *ic, iCode *ifx)
7996 operand *left, *right, *result;
7998 unsigned long lit = 0L;
8000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8002 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8003 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8004 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8006 /* if left is a literal & right is not ||
8007 if left needs acc & right does not */
8008 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8009 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8010 operand *tmp = right ;
8015 /* if result = right then exchange them */
8016 if(pic16_sameRegs(AOP(result),AOP(right))){
8017 operand *tmp = right ;
8022 /* if right is bit then exchange them */
8023 if (AOP_TYPE(right) == AOP_CRY &&
8024 AOP_TYPE(left) != AOP_CRY){
8025 operand *tmp = right ;
8029 if(AOP_TYPE(right) == AOP_LIT)
8030 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8032 size = AOP_SIZE(result);
8036 if (AOP_TYPE(left) == AOP_CRY){
8037 if(AOP_TYPE(right) == AOP_LIT){
8038 // c = bit & literal;
8040 // lit>>1 != 0 => result = 1
8041 if(AOP_TYPE(result) == AOP_CRY){
8043 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8044 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8046 continueIfTrue(ifx);
8049 pic16_emitcode("setb","c");
8053 // lit == 0, result = left
8054 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8056 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8058 // lit == 1, result = not(left)
8059 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8060 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8061 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8062 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8065 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8066 pic16_emitcode("cpl","c");
8073 symbol *tlbl = newiTempLabel(NULL);
8074 if (AOP_TYPE(right) == AOP_CRY){
8076 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8079 int sizer = AOP_SIZE(right);
8081 // if val>>1 != 0, result = 1
8082 pic16_emitcode("setb","c");
8084 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8086 // test the msb of the lsb
8087 pic16_emitcode("anl","a,#0xfe");
8088 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8092 pic16_emitcode("rrc","a");
8094 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8095 pic16_emitcode("cpl","c");
8096 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8101 pic16_outBitC(result);
8103 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8104 genIfxJump(ifx, "c");
8108 if(pic16_sameRegs(AOP(result),AOP(left))){
8109 /* if left is same as result */
8110 for(;size--; offset++) {
8111 if(AOP_TYPE(right) == AOP_LIT){
8112 int t = (lit >> (offset*8)) & 0x0FFL;
8116 if (IS_AOP_PREG(left)) {
8117 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119 pic16_aopPut(AOP(result),"a",offset);
8121 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8122 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8123 pic16_emitcode("xrl","%s,%s",
8124 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8125 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8128 if (AOP_TYPE(left) == AOP_ACC)
8129 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8131 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8132 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8134 if (IS_AOP_PREG(left)) {
8135 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136 pic16_aopPut(AOP(result),"a",offset);
8138 pic16_emitcode("xrl","%s,a",
8139 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8145 // left & result in different registers
8146 if(AOP_TYPE(result) == AOP_CRY){
8148 // if(size), result in bit
8149 // if(!size && ifx), conditional oper: if(left ^ right)
8150 symbol *tlbl = newiTempLabel(NULL);
8151 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8153 pic16_emitcode("setb","c");
8155 if((AOP_TYPE(right) == AOP_LIT) &&
8156 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8157 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8160 pic16_emitcode("xrl","a,%s",
8161 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8163 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8168 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8169 pic16_outBitC(result);
8171 jmpTrueOrFalse(ifx, tlbl);
8172 } else for(;(size--);offset++){
8174 // result = left & right
8175 if(AOP_TYPE(right) == AOP_LIT){
8176 int t = (lit >> (offset*8)) & 0x0FFL;
8179 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181 pic16_emitcode("movf","%s,w",
8182 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183 pic16_emitcode("movwf","%s",
8184 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189 pic16_emitcode("comf","%s,w",
8190 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191 pic16_emitcode("movwf","%s",
8192 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8195 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8196 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8198 pic16_emitcode("movlw","0x%x",t);
8199 pic16_emitcode("xorwf","%s,w",
8200 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8201 pic16_emitcode("movwf","%s",
8202 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8208 // faster than result <- left, anl result,right
8209 // and better if result is SFR
8210 if (AOP_TYPE(left) == AOP_ACC) {
8211 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8212 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8214 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8215 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8216 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8219 if ( AOP_TYPE(result) != AOP_ACC){
8220 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8221 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8227 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8228 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229 pic16_freeAsmop(result,NULL,ic,TRUE);
8232 /*-----------------------------------------------------------------*/
8233 /* genInline - write the inline code out */
8234 /*-----------------------------------------------------------------*/
8235 static void genInline (iCode *ic)
8237 char *buffer, *bp, *bp1;
8239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8241 _G.inLine += (!options.asmpeep);
8243 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8244 strcpy(buffer,IC_INLINE(ic));
8246 while((bp1=strstr(bp, "\\n"))) {
8254 /* This is an experimental code for #pragma inline
8255 and is temporarily disabled for 2.5.0 release */
8263 cbuf = Safe_strdup(buffer);
8264 cblen = strlen(buffer)+1;
8265 memset(cbuf, 0, cblen);
8270 if(*bp != '%')*bp1++ = *bp++;
8276 if(i>elementsInSet(asmInlineMap))break;
8279 s = indexSet(asmInlineMap, i);
8280 DEBUGpc("searching symbol s = `%s'", s);
8281 sym = findSym(SymbolTab, NULL, s);
8284 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8286 strcat(bp1, sym->rname);
8292 if(strlen(bp1) > cblen - 16) {
8293 int i = strlen(cbuf);
8295 cbuf = realloc(cbuf, cblen);
8296 memset(cbuf+i, 0, 50);
8302 buffer = Safe_strdup( cbuf );
8309 /* emit each line as a code */
8315 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8323 /* print label, use this special format with NULL directive
8324 * to denote that the argument should not be indented with tab */
8325 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8328 /* advance to end of line (prevent splitting of comments at ':' */
8329 while (*bp && *bp != '\n') {
8337 if ((bp1 != bp) && *bp1)
8338 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8343 _G.inLine -= (!options.asmpeep);
8346 /*-----------------------------------------------------------------*/
8347 /* genRRC - rotate right with carry */
8348 /*-----------------------------------------------------------------*/
8349 static void genRRC (iCode *ic)
8351 operand *left , *result ;
8352 int size, offset = 0, same;
8354 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8356 /* rotate right with carry */
8358 result=IC_RESULT(ic);
8359 pic16_aopOp (left,ic,FALSE);
8360 pic16_aopOp (result,ic,TRUE);
8362 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8364 same = pic16_sameRegs(AOP(result),AOP(left));
8366 size = AOP_SIZE(result);
8368 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8370 /* get the lsb and put it into the carry */
8371 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8378 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8380 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8387 pic16_freeAsmop(left,NULL,ic,TRUE);
8388 pic16_freeAsmop(result,NULL,ic,TRUE);
8391 /*-----------------------------------------------------------------*/
8392 /* genRLC - generate code for rotate left with carry */
8393 /*-----------------------------------------------------------------*/
8394 static void genRLC (iCode *ic)
8396 operand *left , *result ;
8397 int size, offset = 0;
8400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8401 /* rotate right with carry */
8403 result=IC_RESULT(ic);
8404 pic16_aopOp (left,ic,FALSE);
8405 pic16_aopOp (result,ic,TRUE);
8407 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8409 same = pic16_sameRegs(AOP(result),AOP(left));
8411 /* move it to the result */
8412 size = AOP_SIZE(result);
8414 /* get the msb and put it into the carry */
8415 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8422 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8424 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8425 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8432 pic16_freeAsmop(left,NULL,ic,TRUE);
8433 pic16_freeAsmop(result,NULL,ic,TRUE);
8437 /* gpasm can get the highest order bit with HIGH/UPPER
8438 * so the following probably is not needed -- VR */
8440 /*-----------------------------------------------------------------*/
8441 /* genGetHbit - generates code get highest order bit */
8442 /*-----------------------------------------------------------------*/
8443 static void genGetHbit (iCode *ic)
8445 operand *left, *result;
8447 result=IC_RESULT(ic);
8448 pic16_aopOp (left,ic,FALSE);
8449 pic16_aopOp (result,ic,FALSE);
8451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8452 /* get the highest order byte into a */
8453 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8454 if(AOP_TYPE(result) == AOP_CRY){
8455 pic16_emitcode("rlc","a");
8456 pic16_outBitC(result);
8459 pic16_emitcode("rl","a");
8460 pic16_emitcode("anl","a,#0x01");
8461 pic16_outAcc(result);
8465 pic16_freeAsmop(left,NULL,ic,TRUE);
8466 pic16_freeAsmop(result,NULL,ic,TRUE);
8470 /*-----------------------------------------------------------------*/
8471 /* AccRol - rotate left accumulator by known count */
8472 /*-----------------------------------------------------------------*/
8473 static void AccRol (int shCount)
8475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8476 shCount &= 0x0007; // shCount : 0..7
8481 pic16_emitcode("rl","a");
8484 pic16_emitcode("rl","a");
8485 pic16_emitcode("rl","a");
8488 pic16_emitcode("swap","a");
8489 pic16_emitcode("rr","a");
8492 pic16_emitcode("swap","a");
8495 pic16_emitcode("swap","a");
8496 pic16_emitcode("rl","a");
8499 pic16_emitcode("rr","a");
8500 pic16_emitcode("rr","a");
8503 pic16_emitcode("rr","a");
8509 /*-----------------------------------------------------------------*/
8510 /* AccLsh - left shift accumulator by known count */
8511 /*-----------------------------------------------------------------*/
8512 static void AccLsh (int shCount, int doMask)
8514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8520 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8534 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8538 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8542 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8546 /* no masking is required in genPackBits */
8547 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8551 /*-----------------------------------------------------------------*/
8552 /* AccRsh - right shift accumulator by known count */
8553 /*-----------------------------------------------------------------*/
8554 static void AccRsh (int shCount, int andmask)
8556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8561 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8569 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8572 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8575 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8576 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8580 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8583 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8588 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8590 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8594 /*-----------------------------------------------------------------*/
8595 /* AccSRsh - signed right shift accumulator by known count */
8596 /*-----------------------------------------------------------------*/
8597 static void AccSRsh (int shCount)
8600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8603 pic16_emitcode("mov","c,acc.7");
8604 pic16_emitcode("rrc","a");
8605 } else if(shCount == 2){
8606 pic16_emitcode("mov","c,acc.7");
8607 pic16_emitcode("rrc","a");
8608 pic16_emitcode("mov","c,acc.7");
8609 pic16_emitcode("rrc","a");
8611 tlbl = newiTempLabel(NULL);
8612 /* rotate right accumulator */
8613 AccRol(8 - shCount);
8614 /* and kill the higher order bits */
8615 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8616 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8617 pic16_emitcode("orl","a,#0x%02x",
8618 (unsigned char)~SRMask[shCount]);
8619 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR1Left2Result - shift right one byte from left to result */
8627 /*-----------------------------------------------------------------*/
8628 static void shiftR1Left2ResultSigned (operand *left, int offl,
8629 operand *result, int offr,
8634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8636 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8640 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8642 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8644 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8645 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8653 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8655 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8659 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8665 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8667 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8672 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8675 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8697 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8698 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8705 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8707 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8709 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8722 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8723 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8724 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8727 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8728 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8736 /*-----------------------------------------------------------------*/
8737 /* shiftR1Left2Result - shift right one byte from left to result */
8738 /*-----------------------------------------------------------------*/
8739 static void shiftR1Left2Result (operand *left, int offl,
8740 operand *result, int offr,
8741 int shCount, int sign)
8745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8747 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8749 /* Copy the msb into the carry if signed. */
8751 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8761 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8784 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8788 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8789 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8795 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8796 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8801 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8802 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8810 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8811 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8812 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8813 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8818 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8819 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8820 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8829 /*-----------------------------------------------------------------*/
8830 /* shiftL1Left2Result - shift left one byte from left to result */
8831 /*-----------------------------------------------------------------*/
8832 static void shiftL1Left2Result (operand *left, int offl,
8833 operand *result, int offr, int shCount)
8838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8840 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8841 DEBUGpic16_emitcode ("; ***","same = %d",same);
8842 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8844 /* shift left accumulator */
8845 //AccLsh(shCount, 1); // don't comment out just yet...
8846 // pic16_aopPut(AOP(result),"a",offr);
8850 /* Shift left 1 bit position */
8851 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8855 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8856 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8861 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8862 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8867 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8868 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8874 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8875 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8879 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8880 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8881 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8885 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8886 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8888 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8893 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8897 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8902 /*-----------------------------------------------------------------*/
8903 /* movLeft2Result - move byte from left to result */
8904 /*-----------------------------------------------------------------*/
8905 static void movLeft2Result (operand *left, int offl,
8906 operand *result, int offr)
8909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8910 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8911 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8913 if (*l == '@' && (IS_AOP_PREG(result))) {
8914 pic16_emitcode("mov","a,%s",l);
8915 pic16_aopPut(AOP(result),"a",offr);
8917 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8918 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8923 /*-----------------------------------------------------------------*/
8924 /* shiftL2Left2Result - shift left two bytes from left to result */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftL2Left2Result (operand *left, int offl,
8927 operand *result, int offr, int shCount)
8929 int same = pic16_sameRegs(AOP(result), AOP(left));
8932 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8934 if (same && (offl != offr)) { // shift bytes
8937 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8938 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8940 } else { // just treat as different later on
8953 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8967 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8968 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8974 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8979 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8980 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8982 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8983 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8984 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8985 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8987 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8991 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8992 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8994 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9005 /* note, use a mov/add for the shift since the mov has a
9006 chance of getting optimized out */
9007 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9015 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9028 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9033 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9041 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9046 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9047 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9050 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9053 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9054 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9055 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9056 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9057 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9062 /*-----------------------------------------------------------------*/
9063 /* shiftR2Left2Result - shift right two bytes from left to result */
9064 /*-----------------------------------------------------------------*/
9065 static void shiftR2Left2Result (operand *left, int offl,
9066 operand *result, int offr,
9067 int shCount, int sign)
9069 int same = pic16_sameRegs(AOP(result), AOP(left));
9071 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9073 if (same && (offl != offr)) { // shift right bytes
9076 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9077 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9079 } else { // just treat as different later on
9090 /* obtain sign from left operand */
9092 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9097 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9100 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9101 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9103 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9108 /* now get sign from already assigned result (avoid BANKSEL) */
9109 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9112 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9113 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9121 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9124 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9125 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9126 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9127 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9129 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9130 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9131 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9133 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9134 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9135 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9136 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9137 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9142 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9147 pic16_emitpcode(POC_BTFSC,
9148 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9149 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9158 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9162 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9165 pic16_emitpcode(POC_BTFSC,
9166 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9167 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9169 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9170 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9171 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9175 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9176 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9178 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9179 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9181 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9183 pic16_emitpcode(POC_BTFSC,
9184 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9185 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9187 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9188 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9195 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9196 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9198 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9201 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9203 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9208 /*-----------------------------------------------------------------*/
9209 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9210 /*-----------------------------------------------------------------*/
9211 static void shiftLLeftOrResult (operand *left, int offl,
9212 operand *result, int offr, int shCount)
9214 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9216 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9217 /* shift left accumulator */
9219 /* or with result */
9220 /* back to result */
9221 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9224 /*-----------------------------------------------------------------*/
9225 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9226 /*-----------------------------------------------------------------*/
9227 static void shiftRLeftOrResult (operand *left, int offl,
9228 operand *result, int offr, int shCount)
9230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9232 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9233 /* shift right accumulator */
9235 /* or with result */
9236 /* back to result */
9237 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9240 /*-----------------------------------------------------------------*/
9241 /* genlshOne - left shift a one byte quantity by known count */
9242 /*-----------------------------------------------------------------*/
9243 static void genlshOne (operand *result, operand *left, int shCount)
9245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9246 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9249 /*-----------------------------------------------------------------*/
9250 /* genlshTwo - left shift two bytes by known amount != 0 */
9251 /*-----------------------------------------------------------------*/
9252 static void genlshTwo (operand *result,operand *left, int shCount)
9256 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9257 size = pic16_getDataSize(result);
9259 /* if shCount >= 8 */
9265 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9267 movLeft2Result(left, LSB, result, MSB16);
9269 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9272 /* 1 <= shCount <= 7 */
9275 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9277 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9281 /*-----------------------------------------------------------------*/
9282 /* shiftLLong - shift left one long from left to result */
9283 /* offr = LSB or MSB16 */
9284 /*-----------------------------------------------------------------*/
9285 static void shiftLLong (operand *left, operand *result, int offr )
9287 int size = AOP_SIZE(result);
9288 int same = pic16_sameRegs(AOP(left),AOP(result));
9291 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9293 if (same && (offr == MSB16)) { //shift one byte
9294 for(i=size-1;i>=MSB16;i--) {
9295 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9296 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9299 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9302 if (size > LSB+offr ){
9304 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9306 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9307 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9311 if(size > MSB16+offr){
9313 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9315 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9316 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9320 if(size > MSB24+offr){
9322 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9324 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9325 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9329 if(size > MSB32+offr){
9331 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9333 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9334 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9338 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9342 /*-----------------------------------------------------------------*/
9343 /* genlshFour - shift four byte by a known amount != 0 */
9344 /*-----------------------------------------------------------------*/
9345 static void genlshFour (operand *result, operand *left, int shCount)
9349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9350 size = AOP_SIZE(result);
9352 /* if shifting more that 3 bytes */
9353 if (shCount >= 24 ) {
9356 /* lowest order of left goes to the highest
9357 order of the destination */
9358 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9360 movLeft2Result(left, LSB, result, MSB32);
9362 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9363 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9364 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9369 /* more than two bytes */
9370 else if ( shCount >= 16 ) {
9371 /* lower order two bytes goes to higher order two bytes */
9373 /* if some more remaining */
9375 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9377 movLeft2Result(left, MSB16, result, MSB32);
9378 movLeft2Result(left, LSB, result, MSB24);
9380 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9381 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9385 /* if more than 1 byte */
9386 else if ( shCount >= 8 ) {
9387 /* lower order three bytes goes to higher order three bytes */
9391 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9393 movLeft2Result(left, LSB, result, MSB16);
9395 else{ /* size = 4 */
9397 movLeft2Result(left, MSB24, result, MSB32);
9398 movLeft2Result(left, MSB16, result, MSB24);
9399 movLeft2Result(left, LSB, result, MSB16);
9400 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9402 else if(shCount == 1)
9403 shiftLLong(left, result, MSB16);
9405 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9406 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9407 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9408 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9413 /* 1 <= shCount <= 7 */
9414 else if(shCount <= 3)
9416 shiftLLong(left, result, LSB);
9417 while(--shCount >= 1)
9418 shiftLLong(result, result, LSB);
9420 /* 3 <= shCount <= 7, optimize */
9422 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9423 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9424 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9428 /*-----------------------------------------------------------------*/
9429 /* genLeftShiftLiteral - left shifting by known count */
9430 /*-----------------------------------------------------------------*/
9431 void pic16_genLeftShiftLiteral (operand *left,
9436 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9440 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9441 pic16_freeAsmop(right,NULL,ic,TRUE);
9443 pic16_aopOp(left,ic,FALSE);
9444 pic16_aopOp(result,ic,TRUE);
9446 size = getSize(operandType(result));
9449 pic16_emitcode("; shift left ","result %d, left %d",size,
9453 /* I suppose that the left size >= result size */
9456 movLeft2Result(left, size, result, size);
9460 else if(shCount >= (size * 8))
9462 pic16_aopPut(AOP(result),zero,size);
9466 genlshOne (result,left,shCount);
9471 genlshTwo (result,left,shCount);
9475 genlshFour (result,left,shCount);
9479 pic16_freeAsmop(left,NULL,ic,TRUE);
9480 pic16_freeAsmop(result,NULL,ic,TRUE);
9483 /*-----------------------------------------------------------------*
9484 * genMultiAsm - repeat assembly instruction for size of register.
9485 * if endian == 1, then the high byte (i.e base address + size of
9486 * register) is used first else the low byte is used first;
9487 *-----------------------------------------------------------------*/
9488 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9493 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9506 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9512 #if !(USE_GENERIC_SIGNED_SHIFT)
9513 /*-----------------------------------------------------------------*/
9514 /* genLeftShift - generates code for left shifting */
9515 /*-----------------------------------------------------------------*/
9516 static void genLeftShift (iCode *ic)
9518 operand *left,*right, *result;
9521 symbol *tlbl , *tlbl1;
9524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9526 right = IC_RIGHT(ic);
9528 result = IC_RESULT(ic);
9530 pic16_aopOp(right,ic,FALSE);
9532 /* if the shift count is known then do it
9533 as efficiently as possible */
9534 if (AOP_TYPE(right) == AOP_LIT) {
9535 pic16_genLeftShiftLiteral (left,right,result,ic);
9539 /* shift count is unknown then we have to form
9540 * a loop. Get the loop count in WREG : Note: we take
9541 * only the lower order byte since shifting
9542 * more than 32 bits make no sense anyway, ( the
9543 * largest size of an object can be only 32 bits ) */
9545 pic16_aopOp(left,ic,FALSE);
9546 pic16_aopOp(result,ic,FALSE);
9548 /* now move the left to the result if they are not the
9549 * same, and if size > 1,
9550 * and if right is not same to result (!!!) -- VR */
9551 if (!pic16_sameRegs(AOP(left),AOP(result))
9552 && (AOP_SIZE(result) > 1)) {
9554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9556 size = AOP_SIZE(result);
9561 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9562 if (*l == '@' && (IS_AOP_PREG(result))) {
9564 pic16_emitcode("mov","a,%s",l);
9565 pic16_aopPut(AOP(result),"a",offset);
9569 /* we don't know if left is a literal or a register, take care -- VR */
9570 pic16_mov2f(AOP(result), AOP(left), offset);
9576 size = AOP_SIZE(result);
9578 /* if it is only one byte then */
9580 if(optimized_for_speed) {
9581 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9582 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9583 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9586 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9587 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9588 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9589 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9590 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9591 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9592 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9597 tlbl = newiTempLabel(NULL);
9600 /* this is already done, why change it? */
9601 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9602 pic16_mov2f(AOP(result), AOP(left), 0);
9606 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9607 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9608 pic16_emitpLabel(tlbl->key);
9609 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9610 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9612 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9617 if (pic16_sameRegs(AOP(left),AOP(result))) {
9619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9621 tlbl = newiTempLabel(NULL);
9622 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9623 genMultiAsm(POC_RRCF, result, size,1);
9624 pic16_emitpLabel(tlbl->key);
9625 genMultiAsm(POC_RLCF, result, size,0);
9626 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9628 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9632 //tlbl = newiTempLabel(NULL);
9634 //tlbl1 = newiTempLabel(NULL);
9636 //reAdjustPreg(AOP(result));
9638 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9639 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9640 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9642 //pic16_emitcode("add","a,acc");
9643 //pic16_aopPut(AOP(result),"a",offset++);
9645 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9647 // pic16_emitcode("rlc","a");
9648 // pic16_aopPut(AOP(result),"a",offset++);
9650 //reAdjustPreg(AOP(result));
9652 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9653 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9656 tlbl = newiTempLabel(NULL);
9657 tlbl1= newiTempLabel(NULL);
9659 size = AOP_SIZE(result);
9662 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9664 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9666 /* offset should be 0, 1 or 3 */
9668 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9670 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9672 pic16_emitpcode(POC_MOVWF, pctemp);
9675 pic16_emitpLabel(tlbl->key);
9678 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9680 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9682 pic16_emitpcode(POC_DECFSZ, pctemp);
9683 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9684 pic16_emitpLabel(tlbl1->key);
9686 pic16_popReleaseTempReg(pctemp,1);
9690 pic16_freeAsmop (right,NULL,ic,TRUE);
9691 pic16_freeAsmop(left,NULL,ic,TRUE);
9692 pic16_freeAsmop(result,NULL,ic,TRUE);
9698 #error old code (left here for reference)
9699 /*-----------------------------------------------------------------*/
9700 /* genLeftShift - generates code for left shifting */
9701 /*-----------------------------------------------------------------*/
9702 static void genLeftShift (iCode *ic)
9704 operand *left,*right, *result;
9707 symbol *tlbl , *tlbl1;
9710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9712 right = IC_RIGHT(ic);
9714 result = IC_RESULT(ic);
9716 pic16_aopOp(right,ic,FALSE);
9718 /* if the shift count is known then do it
9719 as efficiently as possible */
9720 if (AOP_TYPE(right) == AOP_LIT) {
9721 pic16_genLeftShiftLiteral (left,right,result,ic);
9725 /* shift count is unknown then we have to form
9726 a loop get the loop count in B : Note: we take
9727 only the lower order byte since shifting
9728 more that 32 bits make no sense anyway, ( the
9729 largest size of an object can be only 32 bits ) */
9732 pic16_aopOp(left,ic,FALSE);
9733 pic16_aopOp(result,ic,FALSE);
9735 /* now move the left to the result if they are not the
9737 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9738 AOP_SIZE(result) > 1) {
9740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9742 size = AOP_SIZE(result);
9745 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9746 if (*l == '@' && (IS_AOP_PREG(result))) {
9748 pic16_emitcode("mov","a,%s",l);
9749 pic16_aopPut(AOP(result),"a",offset);
9752 /* we don't know if left is a literal or a register, take care -- VR */
9753 pic16_mov2f(AOP(result), AOP(left), offset);
9759 size = AOP_SIZE(result);
9761 /* if it is only one byte then */
9763 if(optimized_for_speed) {
9764 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9765 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9766 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9769 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9770 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9771 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9772 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9773 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9774 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9775 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9780 tlbl = newiTempLabel(NULL);
9781 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9782 pic16_mov2f(AOP(result), AOP(left), 0);
9784 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9785 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9788 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9789 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9790 pic16_emitpLabel(tlbl->key);
9791 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9792 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9794 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9799 if (pic16_sameRegs(AOP(left),AOP(result))) {
9801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9803 tlbl = newiTempLabel(NULL);
9804 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9805 genMultiAsm(POC_RRCF, result, size,1);
9806 pic16_emitpLabel(tlbl->key);
9807 genMultiAsm(POC_RLCF, result, size,0);
9808 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9810 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9814 //tlbl = newiTempLabel(NULL);
9816 //tlbl1 = newiTempLabel(NULL);
9818 //reAdjustPreg(AOP(result));
9820 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9821 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9822 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9824 //pic16_emitcode("add","a,acc");
9825 //pic16_aopPut(AOP(result),"a",offset++);
9827 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9829 // pic16_emitcode("rlc","a");
9830 // pic16_aopPut(AOP(result),"a",offset++);
9832 //reAdjustPreg(AOP(result));
9834 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9835 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9838 tlbl = newiTempLabel(NULL);
9839 tlbl1= newiTempLabel(NULL);
9841 size = AOP_SIZE(result);
9844 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9846 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9848 /* offset should be 0, 1 or 3 */
9850 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9852 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9854 pic16_emitpcode(POC_MOVWF, pctemp);
9857 pic16_emitpLabel(tlbl->key);
9860 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9862 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9864 pic16_emitpcode(POC_DECFSZ, pctemp);
9865 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9866 pic16_emitpLabel(tlbl1->key);
9868 pic16_popReleaseTempReg(pctemp,1);
9872 pic16_freeAsmop (right,NULL,ic,TRUE);
9873 pic16_freeAsmop(left,NULL,ic,TRUE);
9874 pic16_freeAsmop(result,NULL,ic,TRUE);
9878 /*-----------------------------------------------------------------*/
9879 /* genrshOne - right shift a one byte quantity by known count */
9880 /*-----------------------------------------------------------------*/
9881 static void genrshOne (operand *result, operand *left,
9882 int shCount, int sign)
9884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9885 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9888 /*-----------------------------------------------------------------*/
9889 /* genrshTwo - right shift two bytes by known amount != 0 */
9890 /*-----------------------------------------------------------------*/
9891 static void genrshTwo (operand *result,operand *left,
9892 int shCount, int sign)
9894 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9895 /* if shCount >= 8 */
9899 shiftR1Left2Result(left, MSB16, result, LSB,
9902 movLeft2Result(left, MSB16, result, LSB);
9904 pic16_addSign (result, 1, sign);
9907 /* 1 <= shCount <= 7 */
9909 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9912 /*-----------------------------------------------------------------*/
9913 /* shiftRLong - shift right one long from left to result */
9914 /* offl = LSB or MSB16 */
9915 /*-----------------------------------------------------------------*/
9916 static void shiftRLong (operand *left, int offl,
9917 operand *result, int sign)
9919 int size = AOP_SIZE(result);
9920 int same = pic16_sameRegs(AOP(left),AOP(result));
9922 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9924 if (same && (offl == MSB16)) { //shift one byte right
9925 for(i=MSB16;i<size;i++) {
9926 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9927 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9932 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9938 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9940 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9945 /* add sign of "a" */
9946 pic16_addSign(result, MSB32, sign);
9950 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9952 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9957 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9959 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9960 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9967 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9973 /*-----------------------------------------------------------------*/
9974 /* genrshFour - shift four byte by a known amount != 0 */
9975 /*-----------------------------------------------------------------*/
9976 static void genrshFour (operand *result, operand *left,
9977 int shCount, int sign)
9979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9980 /* if shifting more that 3 bytes */
9981 if(shCount >= 24 ) {
9984 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9986 movLeft2Result(left, MSB32, result, LSB);
9988 pic16_addSign(result, MSB16, sign);
9990 else if(shCount >= 16){
9993 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9995 movLeft2Result(left, MSB24, result, LSB);
9996 movLeft2Result(left, MSB32, result, MSB16);
9998 pic16_addSign(result, MSB24, sign);
10000 else if(shCount >= 8){
10003 shiftRLong(left, MSB16, result, sign);
10004 else if(shCount == 0){
10005 movLeft2Result(left, MSB16, result, LSB);
10006 movLeft2Result(left, MSB24, result, MSB16);
10007 movLeft2Result(left, MSB32, result, MSB24);
10008 pic16_addSign(result, MSB32, sign);
10010 else{ //shcount >= 2
10011 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10012 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10013 /* the last shift is signed */
10014 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10015 pic16_addSign(result, MSB32, sign);
10018 else{ /* 1 <= shCount <= 7 */
10020 shiftRLong(left, LSB, result, sign);
10022 shiftRLong(result, LSB, result, sign);
10025 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10026 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10027 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10032 /*-----------------------------------------------------------------*/
10033 /* genRightShiftLiteral - right shifting by known count */
10034 /*-----------------------------------------------------------------*/
10035 static void genRightShiftLiteral (operand *left,
10041 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10042 int lsize,res_size;
10044 pic16_freeAsmop(right,NULL,ic,TRUE);
10046 pic16_aopOp(left,ic,FALSE);
10047 pic16_aopOp(result,ic,TRUE);
10049 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10052 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10056 lsize = pic16_getDataSize(left);
10057 res_size = pic16_getDataSize(result);
10058 /* test the LEFT size !!! */
10060 /* I suppose that the left size >= result size */
10062 assert (res_size <= lsize);
10063 while (res_size--) {
10064 pic16_mov2f (AOP(result), AOP(left), res_size);
10068 else if(shCount >= (lsize * 8)){
10070 if(res_size == 1) {
10071 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10073 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10074 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10079 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10080 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10081 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10083 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10088 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10093 switch (res_size) {
10095 genrshOne (result,left,shCount,sign);
10099 genrshTwo (result,left,shCount,sign);
10103 genrshFour (result,left,shCount,sign);
10111 pic16_freeAsmop(left,NULL,ic,TRUE);
10112 pic16_freeAsmop(result,NULL,ic,TRUE);
10115 #if !(USE_GENERIC_SIGNED_SHIFT)
10116 /*-----------------------------------------------------------------*/
10117 /* genSignedRightShift - right shift of signed number */
10118 /*-----------------------------------------------------------------*/
10119 static void genSignedRightShift (iCode *ic)
10121 operand *right, *left, *result;
10124 symbol *tlbl, *tlbl1 ;
10127 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10129 /* we do it the hard way put the shift count in b
10130 and loop thru preserving the sign */
10131 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10133 right = IC_RIGHT(ic);
10134 left = IC_LEFT(ic);
10135 result = IC_RESULT(ic);
10137 pic16_aopOp(right,ic,FALSE);
10138 pic16_aopOp(left,ic,FALSE);
10139 pic16_aopOp(result,ic,FALSE);
10142 if ( AOP_TYPE(right) == AOP_LIT) {
10143 genRightShiftLiteral (left,right,result,ic,1);
10146 /* shift count is unknown then we have to form
10147 a loop get the loop count in B : Note: we take
10148 only the lower order byte since shifting
10149 more that 32 bits make no sense anyway, ( the
10150 largest size of an object can be only 32 bits ) */
10152 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10153 //pic16_emitcode("inc","b");
10154 //pic16_freeAsmop (right,NULL,ic,TRUE);
10155 //pic16_aopOp(left,ic,FALSE);
10156 //pic16_aopOp(result,ic,FALSE);
10158 /* now move the left to the result if they are not the
10160 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10161 AOP_SIZE(result) > 1) {
10163 size = AOP_SIZE(result);
10167 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10168 if (*l == '@' && IS_AOP_PREG(result)) {
10170 pic16_emitcode("mov","a,%s",l);
10171 pic16_aopPut(AOP(result),"a",offset);
10173 pic16_aopPut(AOP(result),l,offset);
10175 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10176 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10182 /* mov the highest order bit to OVR */
10183 tlbl = newiTempLabel(NULL);
10184 tlbl1= newiTempLabel(NULL);
10186 size = AOP_SIZE(result);
10189 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10191 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10193 /* offset should be 0, 1 or 3 */
10194 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10196 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10198 pic16_emitpcode(POC_MOVWF, pctemp);
10201 pic16_emitpLabel(tlbl->key);
10203 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10204 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10207 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10210 pic16_emitpcode(POC_DECFSZ, pctemp);
10211 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10212 pic16_emitpLabel(tlbl1->key);
10214 pic16_popReleaseTempReg(pctemp,1);
10216 size = AOP_SIZE(result);
10218 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10219 pic16_emitcode("rlc","a");
10220 pic16_emitcode("mov","ov,c");
10221 /* if it is only one byte then */
10223 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10225 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10227 pic16_emitcode("mov","c,ov");
10228 pic16_emitcode("rrc","a");
10229 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10230 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10231 pic16_aopPut(AOP(result),"a",0);
10235 reAdjustPreg(AOP(result));
10236 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10237 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10238 pic16_emitcode("mov","c,ov");
10240 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10242 pic16_emitcode("rrc","a");
10243 pic16_aopPut(AOP(result),"a",offset--);
10245 reAdjustPreg(AOP(result));
10246 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10247 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10252 pic16_freeAsmop(left,NULL,ic,TRUE);
10253 pic16_freeAsmop(result,NULL,ic,TRUE);
10254 pic16_freeAsmop(right,NULL,ic,TRUE);
10258 #if !(USE_GENERIC_SIGNED_SHIFT)
10259 #warning This implementation of genRightShift() is incomplete!
10260 /*-----------------------------------------------------------------*/
10261 /* genRightShift - generate code for right shifting */
10262 /*-----------------------------------------------------------------*/
10263 static void genRightShift (iCode *ic)
10265 operand *right, *left, *result;
10269 symbol *tlbl, *tlbl1 ;
10271 /* if signed then we do it the hard way preserve the
10272 sign bit moving it inwards */
10273 letype = getSpec(operandType(IC_LEFT(ic)));
10274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10276 if (!SPEC_USIGN(letype)) {
10277 genSignedRightShift (ic);
10281 /* signed & unsigned types are treated the same : i.e. the
10282 signed is NOT propagated inwards : quoting from the
10283 ANSI - standard : "for E1 >> E2, is equivalent to division
10284 by 2**E2 if unsigned or if it has a non-negative value,
10285 otherwise the result is implementation defined ", MY definition
10286 is that the sign does not get propagated */
10288 right = IC_RIGHT(ic);
10289 left = IC_LEFT(ic);
10290 result = IC_RESULT(ic);
10292 pic16_aopOp(right,ic,FALSE);
10294 /* if the shift count is known then do it
10295 as efficiently as possible */
10296 if (AOP_TYPE(right) == AOP_LIT) {
10297 genRightShiftLiteral (left,right,result,ic, 0);
10301 /* shift count is unknown then we have to form
10302 a loop get the loop count in B : Note: we take
10303 only the lower order byte since shifting
10304 more that 32 bits make no sense anyway, ( the
10305 largest size of an object can be only 32 bits ) */
10307 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10308 pic16_emitcode("inc","b");
10309 pic16_aopOp(left,ic,FALSE);
10310 pic16_aopOp(result,ic,FALSE);
10312 /* now move the left to the result if they are not the
10314 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10315 AOP_SIZE(result) > 1) {
10317 size = AOP_SIZE(result);
10320 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10321 if (*l == '@' && IS_AOP_PREG(result)) {
10323 pic16_emitcode("mov","a,%s",l);
10324 pic16_aopPut(AOP(result),"a",offset);
10326 pic16_aopPut(AOP(result),l,offset);
10331 tlbl = newiTempLabel(NULL);
10332 tlbl1= newiTempLabel(NULL);
10333 size = AOP_SIZE(result);
10336 /* if it is only one byte then */
10339 tlbl = newiTempLabel(NULL);
10340 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10341 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10342 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10345 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10346 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10347 pic16_emitpLabel(tlbl->key);
10348 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10349 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10351 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10356 reAdjustPreg(AOP(result));
10357 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10358 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10361 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10363 pic16_emitcode("rrc","a");
10364 pic16_aopPut(AOP(result),"a",offset--);
10366 reAdjustPreg(AOP(result));
10368 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10369 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10372 pic16_freeAsmop(left,NULL,ic,TRUE);
10373 pic16_freeAsmop (right,NULL,ic,TRUE);
10374 pic16_freeAsmop(result,NULL,ic,TRUE);
10378 #if (USE_GENERIC_SIGNED_SHIFT)
10379 /*-----------------------------------------------------------------*/
10380 /* genGenericShift - generates code for left or right shifting */
10381 /*-----------------------------------------------------------------*/
10382 static void genGenericShift (iCode *ic, int isShiftLeft) {
10383 operand *left,*right, *result;
10385 int sign, signedCount;
10386 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10387 PIC_OPCODE pos_shift, neg_shift;
10391 right = IC_RIGHT(ic);
10392 left = IC_LEFT(ic);
10393 result = IC_RESULT(ic);
10395 pic16_aopOp(right,ic,FALSE);
10396 pic16_aopOp(left,ic,FALSE);
10397 pic16_aopOp(result,ic,TRUE);
10399 sign = !SPEC_USIGN(operandType (left));
10400 signedCount = !SPEC_USIGN(operandType (right));
10402 /* if the shift count is known then do it
10403 as efficiently as possible */
10404 if (AOP_TYPE(right) == AOP_LIT) {
10405 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10406 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10407 // we should modify right->aopu.aop_lit here!
10408 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10409 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10411 pic16_genLeftShiftLiteral (left,right,result,ic);
10413 genRightShiftLiteral (left,right,result,ic, sign);
10416 } // if (right is literal)
10418 /* shift count is unknown then we have to form a loop.
10419 * Note: we take only the lower order byte since shifting
10420 * more than 32 bits make no sense anyway, ( the
10421 * largest size of an object can be only 32 bits )
10422 * Note: we perform arithmetic shifts if the left operand is
10423 * signed and we do an (effective) right shift, i. e. we
10424 * shift in the sign bit from the left. */
10426 label_complete = newiTempLabel ( NULL );
10427 label_loop_pos = newiTempLabel ( NULL );
10428 label_loop_neg = NULL;
10429 label_negative = NULL;
10430 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10431 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10434 // additional labels needed
10435 label_loop_neg = newiTempLabel ( NULL );
10436 label_negative = newiTempLabel ( NULL );
10439 // copy source to result -- this will effectively truncate the left operand to the size of result!
10440 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10441 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10442 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10443 pic16_mov2f (AOP(result),AOP(left), offset);
10446 // if result is longer than left, fill with zeros (or sign)
10447 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10448 if (sign && AOP_SIZE(left) > 0) {
10449 // shift signed operand -- fill with sign
10450 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10451 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10452 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10453 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10454 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10457 // shift unsigned operand -- fill result with zeros
10458 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10459 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10462 } // if (size mismatch)
10464 pic16_mov2w (AOP(right), 0);
10465 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10466 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10469 // perform a shift by one (shift count is positive)
10470 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10471 // 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])
10472 pic16_emitpLabel (label_loop_pos->key);
10474 if (sign && (pos_shift == POC_RRCF)) {
10475 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10478 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10479 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10480 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10482 // perform a shift by one (shift count is positive)
10483 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10484 // 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])
10485 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10486 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10488 pic16_emitpLabel (label_loop_pos->key);
10489 if (sign && (pos_shift == POC_RRCF)) {
10490 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10493 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10494 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10500 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10502 pic16_emitpLabel (label_negative->key);
10503 // perform a shift by -1 (shift count is negative)
10504 // 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)
10506 pic16_emitpLabel (label_loop_neg->key);
10507 if (sign && (neg_shift == POC_RRCF)) {
10508 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10511 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10512 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10513 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10514 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10515 } // if (signedCount)
10517 pic16_emitpLabel (label_complete->key);
10520 pic16_freeAsmop (right,NULL,ic,TRUE);
10521 pic16_freeAsmop(left,NULL,ic,TRUE);
10522 pic16_freeAsmop(result,NULL,ic,TRUE);
10525 static void genLeftShift (iCode *ic) {
10526 genGenericShift (ic, 1);
10529 static void genRightShift (iCode *ic) {
10530 genGenericShift (ic, 0);
10535 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10536 void pic16_loadFSR0(operand *op, int lit)
10538 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10539 if (AOP_TYPE(op) == AOP_LIT) {
10540 /* handle 12 bit integers correctly */
10541 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10542 if ((val & 0x0fff) != val) {
10543 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10544 val, (val & 0x0fff) );
10547 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10549 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10552 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10553 // set up FSR0 with address of result
10554 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10555 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10559 /*----------------------------------------------------------------*/
10560 /* pic16_derefPtr - move one byte from the location ptr points to */
10561 /* to WREG (doWrite == 0) or one byte from WREG */
10562 /* to the location ptr points to (doWrite != 0) */
10563 /*----------------------------------------------------------------*/
10564 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10566 if (!IS_PTR(operandType(ptr)))
10568 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10569 else pic16_mov2w (AOP(ptr), 0);
10573 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10574 /* We might determine pointer type right here: */
10575 p_type = DCL_TYPE(operandType(ptr));
10580 if (!fsr0_setup || !*fsr0_setup)
10582 pic16_loadFSR0( ptr, 0 );
10583 if (fsr0_setup) *fsr0_setup = 1;
10586 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10588 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10592 if (AOP(ptr)->aopu.aop_reg[2]) {
10593 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10594 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10595 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10596 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10597 pic16_mov2w(AOP(ptr), 2);
10598 pic16_callGenericPointerRW(doWrite, 1);
10600 // data pointer (just 2 byte given)
10601 if (!fsr0_setup || !*fsr0_setup)
10603 pic16_loadFSR0( ptr, 0 );
10604 if (fsr0_setup) *fsr0_setup = 1;
10607 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10609 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10614 assert (0 && "invalid pointer type specified");
10619 /*-----------------------------------------------------------------*/
10620 /* genUnpackBits - generates code for unpacking bits */
10621 /*-----------------------------------------------------------------*/
10622 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10625 sym_link *etype, *letype;
10626 int blen=0, bstr=0;
10631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10632 etype = getSpec(operandType(result));
10633 letype = getSpec(operandType(left));
10635 // if(IS_BITFIELD(etype)) {
10636 blen = SPEC_BLEN(etype);
10637 bstr = SPEC_BSTR(etype);
10640 lbstr = SPEC_BSTR( letype );
10642 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10643 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10646 if((blen == 1) && (bstr < 8)
10647 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10648 /* it is a single bit, so use the appropriate bit instructions */
10649 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10651 same = pic16_sameRegs(AOP(left),AOP(result));
10652 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10653 pic16_emitpcode(POC_CLRF, op);
10655 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10656 /* workaround to reduce the extra lfsr instruction */
10657 pic16_emitpcode(POC_BTFSC,
10658 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10660 assert (PIC_IS_DATA_PTR (operandType(left)));
10661 pic16_loadFSR0 (left, 0);
10662 pic16_emitpcode(POC_BTFSC,
10663 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10666 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10667 /* unsigned bitfields result in either 0 or 1 */
10668 pic16_emitpcode(POC_INCF, op);
10670 /* signed bitfields result in either 0 or -1 */
10671 pic16_emitpcode(POC_DECF, op);
10674 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10677 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10683 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10684 // access symbol directly
10685 pic16_mov2w (AOP(left), 0);
10687 pic16_derefPtr (left, ptype, 0, NULL);
10690 /* if we have bitdisplacement then it fits */
10691 /* into this byte completely or if length is */
10692 /* less than a byte */
10693 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10695 /* shift right acc */
10698 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10699 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10701 /* VR -- normally I would use the following, but since we use the hack,
10702 * to avoid the masking from AccRsh, why not mask it right now? */
10705 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10708 /* extend signed bitfields to 8 bits */
10709 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10711 assert (blen + bstr > 0);
10712 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10713 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10716 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10718 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10722 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10723 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10724 exit(EXIT_FAILURE);
10730 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10732 int size, offset = 0, leoffset=0 ;
10734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10735 pic16_aopOp(result, ic, TRUE);
10739 size = AOP_SIZE(result);
10740 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10744 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10745 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10746 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10751 if(AOP(left)->aopu.pcop->type == PO_DIR)
10752 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10754 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10757 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10759 // pic16_DumpOp("(result)",result);
10760 if(is_LitAOp(AOP(result))) {
10761 pic16_mov2w(AOP(left), offset); // patch 8
10762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10764 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10765 pic16_popGet(AOP(left), offset), //patch 8
10766 pic16_popGet(AOP(result), offset)));
10774 pic16_freeAsmop(result,NULL,ic,TRUE);
10779 /*-----------------------------------------------------------------*/
10780 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10781 /*-----------------------------------------------------------------*/
10782 static void genNearPointerGet (operand *left,
10786 // asmop *aop = NULL;
10787 //regs *preg = NULL ;
10788 sym_link *rtype, *retype;
10789 sym_link *ltype, *letype;
10793 rtype = operandType(result);
10794 retype= getSpec(rtype);
10795 ltype = operandType(left);
10796 letype= getSpec(ltype);
10798 pic16_aopOp(left,ic,FALSE);
10800 // pic16_DumpOp("(left)",left);
10801 // pic16_DumpOp("(result)",result);
10803 /* if left is rematerialisable and
10804 * result is not bit variable type and
10805 * the left is pointer to data space i.e
10806 * lower 128 bytes of space */
10808 if (AOP_TYPE(left) == AOP_PCODE
10809 && !IS_BITFIELD(retype)
10810 && DCL_TYPE(ltype) == POINTER) {
10812 genDataPointerGet (left,result,ic);
10813 pic16_freeAsmop(left, NULL, ic, TRUE);
10817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10818 pic16_aopOp (result,ic,TRUE);
10820 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10823 if(IS_BITFIELD( retype )
10824 && (SPEC_BLEN(operandType(result))==1)
10828 int bitstrt, bytestrt;
10830 /* if this is bitfield of size 1, see if we are checking the value
10831 * of a single bit in an if-statement,
10832 * if yes, then don't generate usual code, but execute the
10833 * genIfx directly -- VR */
10837 /* CHECK: if next iCode is IFX
10838 * and current result operand is nextic's conditional operand
10839 * and current result operand live ranges ends at nextic's key number
10841 if((nextic->op == IFX)
10842 && (result == IC_COND(nextic))
10843 && (OP_LIVETO(result) == nextic->seq)
10844 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10846 /* everything is ok then */
10847 /* find a way to optimize the genIfx iCode */
10849 bytestrt = SPEC_BSTR(operandType(result))/8;
10850 bitstrt = SPEC_BSTR(operandType(result))%8;
10852 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10854 genIfxpCOpJump(nextic, jop);
10856 pic16_freeAsmop(left, NULL, ic, TRUE);
10857 pic16_freeAsmop(result, NULL, ic, TRUE);
10863 /* if bitfield then unpack the bits */
10864 if (IS_BITFIELD(letype))
10865 genUnpackBits (result, left, NULL, POINTER);
10867 /* we have can just get the values */
10868 int size = AOP_SIZE(result);
10871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10873 pic16_loadFSR0( left, 0 );
10877 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10878 pic16_popGet(AOP(result), offset++)));
10880 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10881 pic16_popGet(AOP(result), offset++)));
10887 /* now some housekeeping stuff */
10889 /* we had to allocate for this iCode */
10890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10891 pic16_freeAsmop(NULL,aop,ic,TRUE);
10893 /* we did not allocate which means left
10894 * already in a pointer register, then
10895 * if size > 0 && this could be used again
10896 * we have to point it back to where it
10898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10899 if (AOP_SIZE(result) > 1
10900 && !OP_SYMBOL(left)->remat
10901 && ( OP_SYMBOL(left)->liveTo > ic->seq
10903 // int size = AOP_SIZE(result) - 1;
10905 // pic16_emitcode("dec","%s",rname);
10911 pic16_freeAsmop(left,NULL,ic,TRUE);
10912 pic16_freeAsmop(result,NULL,ic,TRUE);
10915 /*-----------------------------------------------------------------*/
10916 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10917 /*-----------------------------------------------------------------*/
10918 static void genPagedPointerGet (operand *left,
10923 regs *preg = NULL ;
10925 sym_link *rtype, *retype;
10927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10929 rtype = operandType(result);
10930 retype= getSpec(rtype);
10932 pic16_aopOp(left,ic,FALSE);
10934 /* if the value is already in a pointer register
10935 then don't need anything more */
10936 if (!AOP_INPREG(AOP(left))) {
10937 /* otherwise get a free pointer register */
10939 preg = getFreePtr(ic,&aop,FALSE);
10940 pic16_emitcode("mov","%s,%s",
10942 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10943 rname = preg->name ;
10945 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10947 pic16_freeAsmop(left,NULL,ic,TRUE);
10948 pic16_aopOp (result,ic,TRUE);
10950 /* if bitfield then unpack the bits */
10951 if (IS_BITFIELD(retype))
10952 genUnpackBits (result,left,rname,PPOINTER);
10954 /* we have can just get the values */
10955 int size = AOP_SIZE(result);
10960 pic16_emitcode("movx","a,@%s",rname);
10961 pic16_aopPut(AOP(result),"a",offset);
10966 pic16_emitcode("inc","%s",rname);
10970 /* now some housekeeping stuff */
10972 /* we had to allocate for this iCode */
10973 pic16_freeAsmop(NULL,aop,ic,TRUE);
10975 /* we did not allocate which means left
10976 already in a pointer register, then
10977 if size > 0 && this could be used again
10978 we have to point it back to where it
10980 if (AOP_SIZE(result) > 1 &&
10981 !OP_SYMBOL(left)->remat &&
10982 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10984 int size = AOP_SIZE(result) - 1;
10986 pic16_emitcode("dec","%s",rname);
10991 pic16_freeAsmop(result,NULL,ic,TRUE);
10997 /* This code is not adjusted to PIC16 and fails utterly.
10998 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11000 /*-----------------------------------------------------------------*/
11001 /* genFarPointerGet - gget value from far space */
11002 /*-----------------------------------------------------------------*/
11003 static void genFarPointerGet (operand *left,
11004 operand *result, iCode *ic)
11007 sym_link *retype = getSpec(operandType(result));
11009 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11011 pic16_aopOp(left,ic,FALSE);
11013 /* if the operand is already in dptr
11014 then we do nothing else we move the value to dptr */
11015 if (AOP_TYPE(left) != AOP_STR) {
11016 /* if this is remateriazable */
11017 if (AOP_TYPE(left) == AOP_IMMD)
11018 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11019 else { /* we need to get it byte by byte */
11020 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11021 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11022 if (options.model == MODEL_FLAT24)
11024 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11028 /* so dptr know contains the address */
11029 pic16_freeAsmop(left,NULL,ic,TRUE);
11030 pic16_aopOp(result,ic,TRUE);
11032 /* if bit then unpack */
11033 if (IS_BITFIELD(retype))
11034 genUnpackBits(result,left,"dptr",FPOINTER);
11036 size = AOP_SIZE(result);
11040 pic16_emitcode("movx","a,@dptr");
11041 pic16_aopPut(AOP(result),"a",offset++);
11043 pic16_emitcode("inc","dptr");
11047 pic16_freeAsmop(result,NULL,ic,TRUE);
11052 /*-----------------------------------------------------------------*/
11053 /* genCodePointerGet - get value from code space */
11054 /*-----------------------------------------------------------------*/
11055 static void genCodePointerGet (operand *left,
11056 operand *result, iCode *ic)
11059 sym_link *retype = getSpec(operandType(result));
11061 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11063 pic16_aopOp(left,ic,FALSE);
11065 /* if the operand is already in dptr
11066 then we do nothing else we move the value to dptr */
11067 if (AOP_TYPE(left) != AOP_STR) {
11068 /* if this is remateriazable */
11069 if (AOP_TYPE(left) == AOP_IMMD)
11070 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11071 else { /* we need to get it byte by byte */
11072 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11073 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11074 if (options.model == MODEL_FLAT24)
11076 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11080 /* so dptr know contains the address */
11081 pic16_freeAsmop(left,NULL,ic,TRUE);
11082 pic16_aopOp(result,ic,FALSE);
11084 /* if bit then unpack */
11085 if (IS_BITFIELD(retype))
11086 genUnpackBits(result,left,"dptr",CPOINTER);
11088 size = AOP_SIZE(result);
11092 pic16_emitcode("clr","a");
11093 pic16_emitcode("movc","a,@a+dptr");
11094 pic16_aopPut(AOP(result),"a",offset++);
11096 pic16_emitcode("inc","dptr");
11100 pic16_freeAsmop(result,NULL,ic,TRUE);
11105 /*-----------------------------------------------------------------*/
11106 /* genGenPointerGet - gget value from generic pointer space */
11107 /*-----------------------------------------------------------------*/
11108 static void genGenPointerGet (operand *left,
11109 operand *result, iCode *ic)
11111 int size, offset, lit;
11112 sym_link *retype = getSpec(operandType(result));
11114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11115 pic16_aopOp(left,ic,FALSE);
11116 pic16_aopOp(result,ic,FALSE);
11117 size = AOP_SIZE(result);
11119 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11121 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11123 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11124 // load FSR0 from immediate
11125 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11127 // pic16_loadFSR0( left );
11132 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11134 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11141 else { /* we need to get it byte by byte */
11142 // set up FSR0 with address from left
11143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11144 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11150 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11152 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11159 /* if bit then unpack */
11160 if (IS_BITFIELD(retype))
11161 genUnpackBits(result,left,"BAD",GPOINTER);
11164 pic16_freeAsmop(left,NULL,ic,TRUE);
11165 pic16_freeAsmop(result,NULL,ic,TRUE);
11171 /*-----------------------------------------------------------------*/
11172 /* genGenPointerGet - gget value from generic pointer space */
11173 /*-----------------------------------------------------------------*/
11174 static void genGenPointerGet (operand *left,
11175 operand *result, iCode *ic)
11177 int size, offset, lit;
11178 sym_link *letype = getSpec(operandType(left));
11180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11181 pic16_aopOp(left,ic,FALSE);
11182 pic16_aopOp(result,ic,TRUE);
11183 size = AOP_SIZE(result);
11185 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11187 /* if bit then unpack */
11188 if (IS_BITFIELD(letype)) {
11189 genUnpackBits(result,left,"BAD",GPOINTER);
11193 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11195 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11196 // load FSR0 from immediate
11197 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11199 werror(W_POSSBUG2, __FILE__, __LINE__);
11204 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11206 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11213 } else { /* we need to get it byte by byte */
11215 /* set up WREG:PRODL:FSR0L with address from left */
11216 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11217 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11218 pic16_mov2w(AOP(left), 2);
11219 pic16_callGenericPointerRW(0, size);
11221 assignResultValue(result, 1);
11227 pic16_freeAsmop(left,NULL,ic,TRUE);
11228 pic16_freeAsmop(result,NULL,ic,TRUE);
11231 /*-----------------------------------------------------------------*/
11232 /* genConstPointerGet - get value from const generic pointer space */
11233 /*-----------------------------------------------------------------*/
11234 static void genConstPointerGet (operand *left,
11235 operand *result, iCode *ic)
11237 //sym_link *retype = getSpec(operandType(result));
11238 // symbol *albl = newiTempLabel(NULL); // patch 15
11239 // symbol *blbl = newiTempLabel(NULL); //
11240 // PIC_OPCODE poc; // patch 15
11244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11245 pic16_aopOp(left,ic,FALSE);
11246 pic16_aopOp(result,ic,TRUE);
11247 size = AOP_SIZE(result);
11249 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11251 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11253 // set up table pointer
11254 if( (AOP_TYPE(left) == AOP_PCODE)
11255 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11256 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11258 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11260 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11261 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11262 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11263 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11265 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11266 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11267 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11271 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11272 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11276 pic16_freeAsmop(left,NULL,ic,TRUE);
11277 pic16_freeAsmop(result,NULL,ic,TRUE);
11281 /*-----------------------------------------------------------------*/
11282 /* genPointerGet - generate code for pointer get */
11283 /*-----------------------------------------------------------------*/
11284 static void genPointerGet (iCode *ic)
11286 operand *left, *result ;
11287 sym_link *type, *etype;
11292 left = IC_LEFT(ic);
11293 result = IC_RESULT(ic) ;
11295 /* depending on the type of pointer we need to
11296 move it to the correct pointer register */
11297 type = operandType(left);
11298 etype = getSpec(type);
11301 if (IS_PTR_CONST(type))
11303 if (IS_CODEPTR(type))
11305 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11307 /* if left is of type of pointer then it is simple */
11308 if (IS_PTR(type) && !IS_FUNC(type->next))
11309 p_type = DCL_TYPE(type);
11311 /* we have to go by the storage class */
11312 p_type = PTR_TYPE(SPEC_OCLS(etype));
11314 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11316 if (SPEC_OCLS(etype)->codesp ) {
11317 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11318 //p_type = CPOINTER ;
11320 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11321 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11322 /*p_type = FPOINTER ;*/
11324 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11325 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11326 /* p_type = PPOINTER; */
11328 if (SPEC_OCLS(etype) == idata ) {
11329 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11330 /* p_type = IPOINTER; */
11332 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11333 /* p_type = POINTER ; */
11337 /* now that we have the pointer type we assign
11338 the pointer values */
11343 genNearPointerGet (left,result,ic);
11347 genPagedPointerGet(left,result,ic);
11351 /* PICs do not support FAR pointers... */
11352 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11354 genFarPointerGet (left,result,ic);
11359 genConstPointerGet (left,result,ic);
11360 //pic16_emitcodePointerGet (left,result,ic);
11365 if (IS_PTR_CONST(type))
11366 genConstPointerGet (left,result,ic);
11369 genGenPointerGet (left,result,ic);
11373 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11374 "genPointerGet: illegal pointer type");
11379 /*-----------------------------------------------------------------*/
11380 /* genPackBits - generates code for packed bit storage */
11381 /*-----------------------------------------------------------------*/
11382 static void genPackBits (sym_link *etype , operand *result,
11384 char *rname, int p_type)
11390 int shifted_and_masked = 0;
11391 unsigned long lit = (unsigned long)-1;
11394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11395 blen = SPEC_BLEN(etype);
11396 bstr = SPEC_BSTR(etype);
11398 retype = getSpec(operandType(right));
11400 if(AOP_TYPE(right) == AOP_LIT) {
11401 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11403 if((blen == 1) && (bstr < 8)) {
11404 /* it is a single bit, so use the appropriate bit instructions */
11406 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11408 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11409 /* workaround to reduce the extra lfsr instruction */
11411 pic16_emitpcode(POC_BSF,
11412 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11414 pic16_emitpcode(POC_BCF,
11415 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11418 if (PIC_IS_DATA_PTR(operandType(result))) {
11419 pic16_loadFSR0(result, 0);
11420 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11421 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11423 /* get old value */
11424 pic16_derefPtr (result, p_type, 0, NULL);
11425 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11426 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11427 /* write back new value */
11428 pic16_derefPtr (result, p_type, 1, NULL);
11434 /* IORLW below is more efficient */
11435 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11436 lit = (lit & ((1UL << blen) - 1)) << bstr;
11437 shifted_and_masked = 1;
11440 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11441 && IS_BITFIELD(retype)
11442 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11446 rblen = SPEC_BLEN( retype );
11447 rbstr = SPEC_BSTR( retype );
11449 if(IS_BITFIELD(etype)) {
11450 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11451 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11453 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11456 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11458 if(IS_BITFIELD(etype)) {
11459 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11461 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11464 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11468 /* move right to W */
11469 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11472 /* if the bit length is less than or */
11473 /* it exactly fits a byte then */
11474 if((shCnt=SPEC_BSTR(etype))
11475 || SPEC_BLEN(etype) <= 8 ) {
11476 int fsr0_setup = 0;
11478 if (blen != 8 || bstr != 0) {
11479 // we need to combine the value with the old value
11480 if(!shifted_and_masked)
11482 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11484 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11485 SPEC_BSTR(etype), SPEC_BLEN(etype));
11487 /* shift left acc, do NOT mask the result again */
11490 /* using PRODH as a temporary register here */
11491 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11494 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11495 || IS_DIRECT(result)) {
11496 /* access symbol directly */
11497 pic16_mov2w (AOP(result), 0);
11499 /* get old value */
11500 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11503 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11504 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11505 (unsigned char)(0xff >> (8-bstr))) ));
11506 if (!shifted_and_masked) {
11507 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11509 /* We have the shifted and masked (literal) right value in `lit' */
11511 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11513 } // if (blen != 8 || bstr != 0)
11515 /* write new value back */
11516 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11517 || IS_DIRECT(result)) {
11518 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11520 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11529 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11530 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11531 exit(EXIT_FAILURE);
11535 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11536 rLen = SPEC_BLEN(etype)-8;
11538 /* now generate for lengths greater than one byte */
11542 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11548 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11554 pic16_emitcode("movx","@dptr,a");
11559 DEBUGpic16_emitcode(";lcall","__gptrput");
11567 pic16_mov2w(AOP(right), offset++);
11570 /* last last was not complete */
11572 /* save the byte & read byte */
11575 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11576 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11581 pic16_emitcode ("mov","b,a");
11582 pic16_emitcode("movx","a,@dptr");
11586 pic16_emitcode ("push","b");
11587 pic16_emitcode ("push","acc");
11588 pic16_emitcode ("lcall","__gptrget");
11589 pic16_emitcode ("pop","b");
11595 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11596 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11597 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11598 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11599 // pic16_emitcode ("orl","a,b");
11602 // if (p_type == GPOINTER)
11603 // pic16_emitcode("pop","b");
11608 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11609 // pic16_emitcode("mov","@%s,a",rname);
11613 pic16_emitcode("movx","@dptr,a");
11617 DEBUGpic16_emitcode(";lcall","__gptrput");
11624 // pic16_freeAsmop(right, NULL, ic, TRUE);
11627 /*-----------------------------------------------------------------*/
11628 /* genDataPointerSet - remat pointer to data space */
11629 /*-----------------------------------------------------------------*/
11630 static void genDataPointerSet(operand *right,
11634 int size, offset = 0, resoffset=0 ;
11636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11637 pic16_aopOp(right,ic,FALSE);
11639 size = AOP_SIZE(right);
11641 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11644 if ( AOP_TYPE(result) == AOP_PCODE) {
11645 fprintf(stderr,"genDataPointerSet %s, %d\n",
11646 AOP(result)->aopu.pcop->name,
11647 (AOP(result)->aopu.pcop->type == PO_DIR)?
11648 PCOR(AOP(result)->aopu.pcop)->instance:
11649 PCOI(AOP(result)->aopu.pcop)->offset);
11653 if(AOP(result)->aopu.pcop->type == PO_DIR)
11654 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11657 if (AOP_TYPE(right) == AOP_LIT) {
11660 if(!IS_FLOAT(operandType( right )))
11661 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11664 unsigned long lit_int;
11668 /* take care if literal is a float */
11669 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11670 lit = info.lit_int;
11672 lit = lit >> (8*offset);
11673 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11675 pic16_mov2w(AOP(right), offset);
11676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11682 pic16_freeAsmop(right,NULL,ic,TRUE);
11687 /*-----------------------------------------------------------------*/
11688 /* genNearPointerSet - pic16_emitcode for near pointer put */
11689 /*-----------------------------------------------------------------*/
11690 static void genNearPointerSet (operand *right,
11696 sym_link *ptype = operandType(result);
11697 sym_link *resetype;
11699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11700 retype= getSpec(operandType(right));
11701 resetype = getSpec(operandType(result));
11703 pic16_aopOp(result,ic,FALSE);
11705 /* if the result is rematerializable &
11706 * in data space & not a bit variable */
11708 /* and result is not a bit variable */
11709 if (AOP_TYPE(result) == AOP_PCODE
11710 // && AOP_TYPE(result) == AOP_IMMD
11711 && DCL_TYPE(ptype) == POINTER
11712 && !IS_BITFIELD(retype)
11713 && !IS_BITFIELD(resetype)) {
11715 genDataPointerSet (right,result,ic);
11716 pic16_freeAsmop(result,NULL,ic,TRUE);
11720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11721 pic16_aopOp(right,ic,FALSE);
11722 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11724 /* if bitfield then unpack the bits */
11725 if (IS_BITFIELD(resetype)) {
11726 genPackBits (resetype, result, right, NULL, POINTER);
11728 /* we have can just get the values */
11729 int size = AOP_SIZE(right);
11732 pic16_loadFSR0(result, 0);
11734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11736 if (AOP_TYPE(right) == AOP_LIT) {
11737 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11739 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11741 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11743 } else { // no literal
11745 pic16_emitpcode(POC_MOVFF,
11746 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11747 pic16_popCopyReg(&pic16_pc_postinc0)));
11749 pic16_emitpcode(POC_MOVFF,
11750 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11751 pic16_popCopyReg(&pic16_pc_indf0)));
11759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11760 /* now some housekeeping stuff */
11762 /* we had to allocate for this iCode */
11763 pic16_freeAsmop(NULL,aop,ic,TRUE);
11765 /* we did not allocate which means left
11766 * already in a pointer register, then
11767 * if size > 0 && this could be used again
11768 * we have to point it back to where it
11770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11771 if (AOP_SIZE(right) > 1
11772 && !OP_SYMBOL(result)->remat
11773 && ( OP_SYMBOL(result)->liveTo > ic->seq
11776 int size = AOP_SIZE(right) - 1;
11779 pic16_emitcode("decf","fsr0,f");
11780 //pic16_emitcode("dec","%s",rname);
11784 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11787 pic16_freeAsmop(right,NULL,ic,TRUE);
11788 pic16_freeAsmop(result,NULL,ic,TRUE);
11791 /*-----------------------------------------------------------------*/
11792 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11793 /*-----------------------------------------------------------------*/
11794 static void genPagedPointerSet (operand *right,
11799 regs *preg = NULL ;
11803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11805 retype= getSpec(operandType(right));
11807 pic16_aopOp(result,ic,FALSE);
11809 /* if the value is already in a pointer register
11810 then don't need anything more */
11811 if (!AOP_INPREG(AOP(result))) {
11812 /* otherwise get a free pointer register */
11814 preg = getFreePtr(ic,&aop,FALSE);
11815 pic16_emitcode("mov","%s,%s",
11817 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11818 rname = preg->name ;
11820 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11822 pic16_freeAsmop(result,NULL,ic,TRUE);
11823 pic16_aopOp (right,ic,FALSE);
11825 /* if bitfield then unpack the bits */
11826 if (IS_BITFIELD(retype))
11827 genPackBits (retype,result,right,rname,PPOINTER);
11829 /* we have can just get the values */
11830 int size = AOP_SIZE(right);
11834 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11837 pic16_emitcode("movx","@%s,a",rname);
11840 pic16_emitcode("inc","%s",rname);
11846 /* now some housekeeping stuff */
11848 /* we had to allocate for this iCode */
11849 pic16_freeAsmop(NULL,aop,ic,TRUE);
11851 /* we did not allocate which means left
11852 already in a pointer register, then
11853 if size > 0 && this could be used again
11854 we have to point it back to where it
11856 if (AOP_SIZE(right) > 1 &&
11857 !OP_SYMBOL(result)->remat &&
11858 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11860 int size = AOP_SIZE(right) - 1;
11862 pic16_emitcode("dec","%s",rname);
11867 pic16_freeAsmop(right,NULL,ic,TRUE);
11873 /* This code is not adjusted to PIC16 and fails utterly...
11874 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11876 /*-----------------------------------------------------------------*/
11877 /* genFarPointerSet - set value from far space */
11878 /*-----------------------------------------------------------------*/
11879 static void genFarPointerSet (operand *right,
11880 operand *result, iCode *ic)
11883 sym_link *retype = getSpec(operandType(right));
11885 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11886 pic16_aopOp(result,ic,FALSE);
11888 /* if the operand is already in dptr
11889 then we do nothing else we move the value to dptr */
11890 if (AOP_TYPE(result) != AOP_STR) {
11891 /* if this is remateriazable */
11892 if (AOP_TYPE(result) == AOP_IMMD)
11893 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11894 else { /* we need to get it byte by byte */
11895 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11896 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11897 if (options.model == MODEL_FLAT24)
11899 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11903 /* so dptr know contains the address */
11904 pic16_freeAsmop(result,NULL,ic,TRUE);
11905 pic16_aopOp(right,ic,FALSE);
11907 /* if bit then unpack */
11908 if (IS_BITFIELD(retype))
11909 genPackBits(retype,result,right,"dptr",FPOINTER);
11911 size = AOP_SIZE(right);
11915 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11917 pic16_emitcode("movx","@dptr,a");
11919 pic16_emitcode("inc","dptr");
11923 pic16_freeAsmop(right,NULL,ic,TRUE);
11927 /*-----------------------------------------------------------------*/
11928 /* genGenPointerSet - set value from generic pointer space */
11929 /*-----------------------------------------------------------------*/
11931 static void genGenPointerSet (operand *right,
11932 operand *result, iCode *ic)
11934 int i, size, offset, lit;
11935 sym_link *retype = getSpec(operandType(right));
11937 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11939 pic16_aopOp(result,ic,FALSE);
11940 pic16_aopOp(right,ic,FALSE);
11941 size = AOP_SIZE(right);
11944 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11946 /* if the operand is already in dptr
11947 then we do nothing else we move the value to dptr */
11948 if (AOP_TYPE(result) != AOP_STR) {
11949 /* if this is remateriazable */
11950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11951 // WARNING: anythig until "else" is untested!
11952 if (AOP_TYPE(result) == AOP_IMMD) {
11953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11954 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11955 // load FSR0 from immediate
11956 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11960 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11962 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11968 else { /* we need to get it byte by byte */
11969 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11970 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11972 // set up FSR0 with address of result
11973 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11974 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11976 /* hack hack! see if this the FSR. If so don't load W */
11977 if(AOP_TYPE(right) != AOP_ACC) {
11979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11981 if(AOP_TYPE(right) == AOP_LIT)
11984 // note: pic16_popGet handles sign extension
11985 for(i=0;i<size;i++) {
11986 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11988 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11990 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11995 for(i=0;i<size;i++) {
11997 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11998 pic16_popCopyReg(&pic16_pc_postinc0)));
12000 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12001 pic16_popCopyReg(&pic16_pc_indf0)));
12007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12008 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12010 } // if (AOP_TYPE(result) != AOP_IMMD)
12012 } // if (AOP_TYPE(result) != AOP_STR)
12013 /* so dptr know contains the address */
12016 /* if bit then unpack */
12017 if (IS_BITFIELD(retype))
12018 genPackBits(retype,result,right,"dptr",GPOINTER);
12020 size = AOP_SIZE(right);
12023 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12025 // set up FSR0 with address of result
12026 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12027 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12030 if (AOP_TYPE(right) == AOP_LIT) {
12031 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12033 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12035 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12037 } else { // no literal
12039 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12041 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12049 pic16_freeAsmop(right,NULL,ic,TRUE);
12050 pic16_freeAsmop(result,NULL,ic,TRUE);
12054 static void genGenPointerSet (operand *right,
12055 operand *result, iCode *ic)
12058 sym_link *retype = getSpec(operandType(result));
12060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12062 pic16_aopOp(result,ic,FALSE);
12063 pic16_aopOp(right,ic,FALSE);
12064 size = AOP_SIZE(right);
12066 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12069 /* if bit then unpack */
12070 if (IS_BITFIELD(retype)) {
12071 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12072 genPackBits(retype,result,right,"dptr",GPOINTER);
12076 size = AOP_SIZE(right);
12078 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12081 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12083 /* value of right+0 is placed on stack, which will be retrieved
12084 * by the support function thus restoring the stack. The important
12085 * thing is that there is no need to manually restore stack pointer
12087 pushaop(AOP(right), 0);
12088 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12089 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12090 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12091 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12093 /* load address to write to in WREG:FSR0H:FSR0L */
12094 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12095 pic16_popCopyReg(&pic16_pc_fsr0l)));
12096 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12097 pic16_popCopyReg(&pic16_pc_prodl)));
12098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12100 pic16_callGenericPointerRW(1, size);
12103 pic16_freeAsmop(right,NULL,ic,TRUE);
12104 pic16_freeAsmop(result,NULL,ic,TRUE);
12107 /*-----------------------------------------------------------------*/
12108 /* genPointerSet - stores the value into a pointer location */
12109 /*-----------------------------------------------------------------*/
12110 static void genPointerSet (iCode *ic)
12112 operand *right, *result ;
12113 sym_link *type, *etype;
12118 right = IC_RIGHT(ic);
12119 result = IC_RESULT(ic) ;
12121 /* depending on the type of pointer we need to
12122 move it to the correct pointer register */
12123 type = operandType(result);
12124 etype = getSpec(type);
12126 /* if left is of type of pointer then it is simple */
12127 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12128 p_type = DCL_TYPE(type);
12131 /* we have to go by the storage class */
12132 p_type = PTR_TYPE(SPEC_OCLS(etype));
12134 /* if (SPEC_OCLS(etype)->codesp ) { */
12135 /* p_type = CPOINTER ; */
12138 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12139 /* p_type = FPOINTER ; */
12141 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12142 /* p_type = PPOINTER ; */
12144 /* if (SPEC_OCLS(etype) == idata ) */
12145 /* p_type = IPOINTER ; */
12147 /* p_type = POINTER ; */
12150 /* now that we have the pointer type we assign
12151 the pointer values */
12156 genNearPointerSet (right,result,ic);
12160 genPagedPointerSet (right,result,ic);
12164 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12166 genFarPointerSet (right,result,ic);
12171 genGenPointerSet (right,result,ic);
12175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12176 "genPointerSet: illegal pointer type");
12180 /*-----------------------------------------------------------------*/
12181 /* genIfx - generate code for Ifx statement */
12182 /*-----------------------------------------------------------------*/
12183 static void genIfx (iCode *ic, iCode *popIc)
12185 operand *cond = IC_COND(ic);
12190 pic16_aopOp(cond,ic,FALSE);
12192 /* get the value into acc */
12193 if (AOP_TYPE(cond) != AOP_CRY)
12194 pic16_toBoolean(cond);
12197 /* the result is now in the accumulator */
12198 pic16_freeAsmop(cond,NULL,ic,TRUE);
12200 /* if there was something to be popped then do it */
12204 /* if the condition is a bit variable */
12205 if (isbit && IS_ITEMP(cond) &&
12207 genIfxJump(ic,"c");
12208 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12210 if (isbit && !IS_ITEMP(cond))
12211 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12213 genIfxJump(ic,"a");
12218 /*-----------------------------------------------------------------*/
12219 /* genAddrOf - generates code for address of */
12220 /*-----------------------------------------------------------------*/
12221 static void genAddrOf (iCode *ic)
12223 operand *result, *left;
12225 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12226 pCodeOp *pcop0, *pcop1, *pcop2;
12230 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12232 sym = OP_SYMBOL( IC_LEFT(ic) );
12235 /* get address of symbol on stack */
12236 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12238 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12239 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12242 // operands on stack are accessible via "FSR2 + index" with index
12243 // starting at 2 for arguments and growing from 0 downwards for
12244 // local variables (index == 0 is not assigned so we add one here)
12246 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12249 assert (soffs < 0);
12253 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12254 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12255 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12256 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12257 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12258 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12259 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12265 // if(pic16_debug_verbose) {
12266 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12267 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12270 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12271 size = AOP_SIZE(IC_RESULT(ic));
12273 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12274 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12275 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12278 pic16_emitpcode(POC_MOVLW, pcop0);
12279 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12280 pic16_emitpcode(POC_MOVLW, pcop1);
12281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12282 pic16_emitpcode(POC_MOVLW, pcop2);
12283 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12286 pic16_emitpcode(POC_MOVLW, pcop0);
12287 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12288 pic16_emitpcode(POC_MOVLW, pcop1);
12289 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12291 pic16_emitpcode(POC_MOVLW, pcop0);
12292 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12295 pic16_freeAsmop(left, NULL, ic, FALSE);
12297 pic16_freeAsmop(result,NULL,ic,TRUE);
12302 /*-----------------------------------------------------------------*/
12303 /* genFarFarAssign - assignment when both are in far space */
12304 /*-----------------------------------------------------------------*/
12305 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12307 int size = AOP_SIZE(right);
12310 /* first push the right side on to the stack */
12312 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12314 pic16_emitcode ("push","acc");
12317 pic16_freeAsmop(right,NULL,ic,FALSE);
12318 /* now assign DPTR to result */
12319 pic16_aopOp(result,ic,FALSE);
12320 size = AOP_SIZE(result);
12322 pic16_emitcode ("pop","acc");
12323 pic16_aopPut(AOP(result),"a",--offset);
12325 pic16_freeAsmop(result,NULL,ic,FALSE);
12330 /*-----------------------------------------------------------------*/
12331 /* genAssign - generate code for assignment */
12332 /*-----------------------------------------------------------------*/
12333 static void genAssign (iCode *ic)
12335 operand *result, *right;
12336 sym_link *restype, *rtype;
12337 int size, offset,know_W;
12338 unsigned long lit = 0L;
12340 result = IC_RESULT(ic);
12341 right = IC_RIGHT(ic) ;
12345 /* if they are the same */
12346 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12349 /* reversed order operands are aopOp'ed so that result operand
12350 * is effective in case right is a stack symbol. This maneauver
12351 * allows to use the _G.resDirect flag later */
12352 pic16_aopOp(result,ic,TRUE);
12353 pic16_aopOp(right,ic,FALSE);
12355 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12357 /* if they are the same registers */
12358 if (pic16_sameRegs(AOP(right),AOP(result)))
12361 /* if the result is a bit */
12362 if (AOP_TYPE(result) == AOP_CRY) {
12363 /* if the right size is a literal then
12364 we know what the value is */
12365 if (AOP_TYPE(right) == AOP_LIT) {
12367 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12368 pic16_popGet(AOP(result),0));
12370 if (((int) operandLitValue(right)))
12371 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12372 AOP(result)->aopu.aop_dir,
12373 AOP(result)->aopu.aop_dir);
12375 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12376 AOP(result)->aopu.aop_dir,
12377 AOP(result)->aopu.aop_dir);
12382 /* the right is also a bit variable */
12383 if (AOP_TYPE(right) == AOP_CRY) {
12384 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12385 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12386 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12391 /* we need to or */
12392 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12393 pic16_toBoolean(right);
12395 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12396 //pic16_aopPut(AOP(result),"a",0);
12400 /* bit variables done */
12402 size = AOP_SIZE(result);
12405 /* bit variables done */
12407 size = AOP_SIZE(result);
12408 restype = operandType(result);
12409 rtype = operandType(right);
12412 if(AOP_TYPE(right) == AOP_LIT) {
12413 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12415 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12417 /* patch tag for literals that are cast to pointers */
12418 if (IS_CODEPTR(restype)) {
12419 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12420 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12422 if (IS_GENPTR(restype))
12424 if (IS_CODEPTR(rtype)) {
12425 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12426 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12427 } else if (PIC_IS_DATA_PTR(rtype)) {
12428 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12429 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12430 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12431 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12432 } else if (IS_PTR(rtype)) {
12433 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12434 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12440 unsigned long lit_int;
12445 if(IS_FIXED16X16(operandType(right))) {
12446 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12448 /* take care if literal is a float */
12449 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12450 lit = info.lit_int;
12455 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12456 // sizeof(unsigned long int), sizeof(float));
12459 if (AOP_TYPE(right) == AOP_REG) {
12460 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12462 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12467 /* when do we have to read the program memory?
12468 * - if right itself is a symbol in code space
12469 * (we don't care what it points to if it's a pointer)
12470 * - AND right is not a function (we would want its address)
12472 if(AOP_TYPE(right) != AOP_LIT
12473 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12474 && !IS_FUNC(OP_SYM_TYPE(right))
12475 && !IS_ITEMP(right)) {
12477 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12478 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12480 // set up table pointer
12481 if(is_LitOp(right)) {
12482 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12483 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12484 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12485 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12486 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12487 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12488 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12490 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12491 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12492 pic16_popCopyReg(&pic16_pc_tblptrl)));
12493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12494 pic16_popCopyReg(&pic16_pc_tblptrh)));
12495 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12496 pic16_popCopyReg(&pic16_pc_tblptru)));
12499 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12500 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12502 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12503 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12504 pic16_popGet(AOP(result),offset)));
12508 /* FIXME: for pointers we need to extend differently (according
12509 * to pointer type DATA/CODE/EEPROM/... :*/
12510 size = getSize(OP_SYM_TYPE(right));
12511 if(AOP_SIZE(result) > size) {
12512 size = AOP_SIZE(result) - size;
12514 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12522 /* VR - What is this?! */
12523 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12526 if(aopIdx(AOP(result),0) == 4) {
12527 /* this is a workaround to save value of right into wreg too,
12528 * value of wreg is going to be used later */
12529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12530 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12531 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12535 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12541 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12542 if(AOP_TYPE(right) == AOP_LIT) {
12544 if(know_W != (lit&0xff))
12545 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12547 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12549 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12553 } else if (AOP_TYPE(right) == AOP_CRY) {
12554 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12556 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12557 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12558 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12560 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12561 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12562 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12566 if(!_G.resDirect) { /* use this aopForSym feature */
12567 if(AOP_TYPE(result) == AOP_ACC) {
12568 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12570 if(AOP_TYPE(right) == AOP_ACC) {
12571 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12573 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12582 pic16_freeAsmop (right,NULL,ic,FALSE);
12583 pic16_freeAsmop (result,NULL,ic,TRUE);
12586 /*-----------------------------------------------------------------*/
12587 /* genJumpTab - generates code for jump table */
12588 /*-----------------------------------------------------------------*/
12589 static void genJumpTab (iCode *ic)
12594 pCodeOp *jt_offs_hi;
12599 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12600 /* get the condition into accumulator */
12601 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12603 /* multiply by three */
12604 pic16_emitcode("add","a,acc");
12605 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12607 jtab = newiTempLabel(NULL);
12608 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12609 pic16_emitcode("jmp","@a+dptr");
12610 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12613 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12614 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12616 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12617 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12618 pic16_emitpLabel(jtab->key);
12622 jt_offs = pic16_popGetTempReg(0);
12623 jt_offs_hi = pic16_popGetTempReg(1);
12624 jt_label = pic16_popGetLabel (jtab->key);
12625 //fprintf (stderr, "Creating jump table...\n");
12627 // calculate offset into jump table (idx * sizeof (GOTO))
12628 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12629 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12630 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12631 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12632 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12633 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12634 pic16_emitpcode(POC_MOVWF , jt_offs);
12636 // prepare PCLATx (set to first entry in jump table)
12637 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12638 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12639 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12640 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12641 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12643 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12644 pic16_emitpcode(POC_ADDWF , jt_offs);
12645 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12646 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12648 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12650 // release temporaries and prepare jump into table (new PCL --> WREG)
12651 pic16_emitpcode(POC_MOVFW , jt_offs);
12652 pic16_popReleaseTempReg (jt_offs_hi, 1);
12653 pic16_popReleaseTempReg (jt_offs, 0);
12655 // jump into the table
12656 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12658 pic16_emitpLabelFORCE(jtab->key);
12661 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12662 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12664 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12665 /* now generate the jump labels */
12666 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12667 jtab = setNextItem(IC_JTLABELS(ic))) {
12668 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12669 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12672 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12676 /*-----------------------------------------------------------------*/
12677 /* genMixedOperation - gen code for operators between mixed types */
12678 /*-----------------------------------------------------------------*/
12680 TSD - Written for the PIC port - but this unfortunately is buggy.
12681 This routine is good in that it is able to efficiently promote
12682 types to different (larger) sizes. Unfortunately, the temporary
12683 variables that are optimized out by this routine are sometimes
12684 used in other places. So until I know how to really parse the
12685 iCode tree, I'm going to not be using this routine :(.
12687 static int genMixedOperation (iCode *ic)
12690 operand *result = IC_RESULT(ic);
12691 sym_link *ctype = operandType(IC_LEFT(ic));
12692 operand *right = IC_RIGHT(ic);
12698 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12700 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12706 nextright = IC_RIGHT(nextic);
12707 nextleft = IC_LEFT(nextic);
12708 nextresult = IC_RESULT(nextic);
12710 pic16_aopOp(right,ic,FALSE);
12711 pic16_aopOp(result,ic,FALSE);
12712 pic16_aopOp(nextright, nextic, FALSE);
12713 pic16_aopOp(nextleft, nextic, FALSE);
12714 pic16_aopOp(nextresult, nextic, FALSE);
12716 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12718 operand *t = right;
12722 pic16_emitcode(";remove right +","");
12724 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12726 operand *t = right;
12730 pic16_emitcode(";remove left +","");
12734 big = AOP_SIZE(nextleft);
12735 small = AOP_SIZE(nextright);
12737 switch(nextic->op) {
12740 pic16_emitcode(";optimize a +","");
12741 /* if unsigned or not an integral type */
12742 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12743 pic16_emitcode(";add a bit to something","");
12746 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12748 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12749 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12750 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12752 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12760 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12761 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12762 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12765 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12767 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12768 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12769 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12770 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12771 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12774 pic16_emitcode("rlf","known_zero,w");
12781 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12782 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12783 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12785 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12795 pic16_freeAsmop(right,NULL,ic,TRUE);
12796 pic16_freeAsmop(result,NULL,ic,TRUE);
12797 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12798 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12800 nextic->generated = 1;
12807 /*-----------------------------------------------------------------*/
12808 /* genCast - gen code for casting */
12809 /*-----------------------------------------------------------------*/
12810 static void genCast (iCode *ic)
12812 operand *result = IC_RESULT(ic);
12813 sym_link *ctype = operandType(IC_LEFT(ic));
12814 sym_link *rtype = operandType(IC_RIGHT(ic));
12815 sym_link *restype = operandType(IC_RESULT(ic));
12816 operand *right = IC_RIGHT(ic);
12822 /* if they are equivalent then do nothing */
12823 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12826 pic16_aopOp(result,ic,FALSE);
12827 pic16_aopOp(right,ic,FALSE) ;
12829 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12832 /* if the result is a bit */
12833 if (AOP_TYPE(result) == AOP_CRY) {
12835 /* if the right size is a literal then
12836 * we know what the value is */
12837 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12839 if (AOP_TYPE(right) == AOP_LIT) {
12840 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12841 pic16_popGet(AOP(result),0));
12843 if (((int) operandLitValue(right)))
12844 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12845 AOP(result)->aopu.aop_dir,
12846 AOP(result)->aopu.aop_dir);
12848 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12849 AOP(result)->aopu.aop_dir,
12850 AOP(result)->aopu.aop_dir);
12854 /* the right is also a bit variable */
12855 if (AOP_TYPE(right) == AOP_CRY) {
12857 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12859 pic16_emitcode("clrc","");
12860 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12861 AOP(right)->aopu.aop_dir,
12862 AOP(right)->aopu.aop_dir);
12863 pic16_aopPut(AOP(result),"c",0);
12867 /* we need to or */
12868 if (AOP_TYPE(right) == AOP_REG) {
12869 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12870 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12871 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12873 pic16_toBoolean(right);
12874 pic16_aopPut(AOP(result),"a",0);
12878 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12881 size = AOP_SIZE(result);
12883 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12885 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12886 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12887 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12890 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12895 if(IS_BITFIELD(getSpec(restype))
12896 && IS_BITFIELD(getSpec(rtype))) {
12897 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12900 /* port from pic14 to cope with generic pointers */
12901 if (PIC_IS_TAGGED(restype))
12903 operand *result = IC_RESULT(ic);
12904 //operand *left = IC_LEFT(ic);
12905 operand *right = IC_RIGHT(ic);
12908 /* copy common part */
12909 int max, size = AOP_SIZE(result);
12910 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12911 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12916 pic16_mov2w (AOP(right), size);
12917 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12920 /* upcast into generic pointer type? */
12921 if (IS_GENPTR(restype)
12922 && !PIC_IS_TAGGED(rtype)
12923 && (AOP_SIZE(result) > max))
12925 /* determine appropriate tag for right */
12926 if (PIC_IS_DATA_PTR(rtype))
12927 tag = GPTR_TAG_DATA;
12928 else if (IS_CODEPTR(rtype))
12929 tag = GPTR_TAG_CODE;
12930 else if (PIC_IS_DATA_PTR(ctype)) {
12931 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12932 tag = GPTR_TAG_DATA;
12933 } else if (IS_CODEPTR(ctype)) {
12934 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12935 tag = GPTR_TAG_CODE;
12936 } else if (IS_PTR(rtype)) {
12937 PERFORM_ONCE(weirdcast,
12938 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12940 tag = GPTR_TAG_DATA;
12942 PERFORM_ONCE(weirdcast,
12943 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12945 tag = GPTR_TAG_DATA;
12948 assert (AOP_SIZE(result) == 3);
12949 /* zero-extend address... */
12950 for (size = max; size < AOP_SIZE(result)-1; size++)
12951 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12952 /* ...and add tag */
12953 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12954 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12955 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12956 for (size = max; size < AOP_SIZE(result)-1; size++)
12957 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12958 /* add __code tag */
12959 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12960 } else if (AOP_SIZE(result) > max) {
12961 /* extend non-pointers */
12962 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12963 pic16_addSign(result, max, 0);
12968 /* if they are the same size : or less */
12969 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12971 /* if they are in the same place */
12972 if (pic16_sameRegs(AOP(right),AOP(result)))
12975 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12977 if (IS_PTR_CONST(rtype))
12979 if (IS_CODEPTR(rtype))
12981 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12984 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12986 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12988 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12991 if(AOP_TYPE(right) == AOP_IMMD) {
12992 pCodeOp *pcop0, *pcop1, *pcop2;
12993 symbol *sym = OP_SYMBOL( right );
12995 size = AOP_SIZE(result);
12997 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12999 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13001 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13004 pic16_emitpcode(POC_MOVLW, pcop0);
13005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13006 pic16_emitpcode(POC_MOVLW, pcop1);
13007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13008 pic16_emitpcode(POC_MOVLW, pcop2);
13009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13012 pic16_emitpcode(POC_MOVLW, pcop0);
13013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13014 pic16_emitpcode(POC_MOVLW, pcop1);
13015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13017 pic16_emitpcode(POC_MOVLW, pcop0);
13018 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13022 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13023 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13026 if(AOP_SIZE(result) < 2) {
13027 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13029 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13033 /* if they in different places then copy */
13034 size = AOP_SIZE(result);
13037 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13038 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13045 /* if the result is of type pointer */
13046 if (IS_PTR(ctype)) {
13048 sym_link *type = operandType(right);
13049 sym_link *etype = getSpec(type);
13051 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13053 /* pointer to generic pointer */
13054 if (IS_GENPTR(ctype)) {
13058 p_type = DCL_TYPE(type);
13060 /* we have to go by the storage class */
13061 p_type = PTR_TYPE(SPEC_OCLS(etype));
13063 /* if (SPEC_OCLS(etype)->codesp ) */
13064 /* p_type = CPOINTER ; */
13066 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13067 /* p_type = FPOINTER ; */
13069 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13070 /* p_type = PPOINTER; */
13072 /* if (SPEC_OCLS(etype) == idata ) */
13073 /* p_type = IPOINTER ; */
13075 /* p_type = POINTER ; */
13078 /* the first two bytes are known */
13079 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13080 size = GPTRSIZE - 1;
13083 if(offset < AOP_SIZE(right)) {
13084 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13085 pic16_mov2f(AOP(result), AOP(right), offset);
13087 if ((AOP_TYPE(right) == AOP_PCODE) &&
13088 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13089 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13090 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13093 pic16_aopPut(AOP(result),
13094 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13099 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13102 /* the last byte depending on type */
13107 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13111 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13115 pic16_emitcode(";BUG!? ","%d",__LINE__);
13120 if (GPTRSIZE > AOP_SIZE(right)) {
13121 // assume __data pointer... THIS MIGHT BE WRONG!
13122 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13124 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13129 /* this should never happen */
13130 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13131 "got unknown pointer type");
13134 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13140 /* just copy the pointers */
13141 size = AOP_SIZE(result);
13144 pic16_aopPut(AOP(result),
13145 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13154 /* so we now know that the size of destination is greater
13155 than the size of the source.
13156 Now, if the next iCode is an operator then we might be
13157 able to optimize the operation without performing a cast.
13159 if(genMixedOperation(ic))
13162 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13164 /* we move to result for the size of source */
13165 size = AOP_SIZE(right);
13170 pic16_mov2f(AOP(result), AOP(right), offset);
13174 /* now depending on the sign of the destination */
13175 size = AOP_SIZE(result) - AOP_SIZE(right);
13176 /* if unsigned or not an integral type */
13177 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13179 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13181 /* we need to extend the sign :( */
13184 /* Save one instruction of casting char to int */
13185 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13186 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13187 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13189 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13192 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13194 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13196 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13199 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13204 pic16_freeAsmop(right,NULL,ic,TRUE);
13205 pic16_freeAsmop(result,NULL,ic,TRUE);
13209 /*-----------------------------------------------------------------*/
13210 /* genDjnz - generate decrement & jump if not zero instrucion */
13211 /*-----------------------------------------------------------------*/
13212 static int genDjnz (iCode *ic, iCode *ifx)
13214 symbol *lbl, *lbl1;
13215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13220 /* if the if condition has a false label
13221 then we cannot save */
13225 /* if the minus is not of the form
13227 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13228 !IS_OP_LITERAL(IC_RIGHT(ic)))
13231 if (operandLitValue(IC_RIGHT(ic)) != 1)
13234 /* if the size of this greater than one then no
13236 if (getSize(operandType(IC_RESULT(ic))) > 1)
13239 /* otherwise we can save BIG */
13240 lbl = newiTempLabel(NULL);
13241 lbl1= newiTempLabel(NULL);
13243 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13245 if (IS_AOP_PREG(IC_RESULT(ic))) {
13246 pic16_emitcode("dec","%s",
13247 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13248 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13249 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13253 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13254 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13256 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13257 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13261 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13262 ifx->generated = 1;
13266 /*-----------------------------------------------------------------*/
13267 /* genReceive - generate code for a receive iCode */
13268 /*-----------------------------------------------------------------*/
13269 static void genReceive (iCode *ic)
13275 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13276 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13278 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13280 if (isOperandInFarSpace(IC_RESULT(ic))
13281 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13282 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13284 int size = getSize(operandType(IC_RESULT(ic)));
13285 int offset = pic16_fReturnSizePic - size;
13289 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13290 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13294 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13296 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13297 size = AOP_SIZE(IC_RESULT(ic));
13300 pic16_emitcode ("pop","acc");
13301 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13304 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13306 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13309 /* set pseudo stack pointer to where it should be - dw*/
13310 GpsuedoStkPtr = ic->parmBytes;
13312 /* setting GpsuedoStkPtr has side effects here: */
13313 assignResultValue(IC_RESULT(ic), 0);
13316 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13319 /*-----------------------------------------------------------------*/
13320 /* genDummyRead - generate code for dummy read of volatiles */
13321 /*-----------------------------------------------------------------*/
13323 genDummyRead (iCode * ic)
13329 if (op && IS_SYMOP(op)) {
13330 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13331 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13334 pic16_aopOp (op, ic, FALSE);
13335 for (i=0; i < AOP_SIZE(op); i++) {
13336 // may need to protect this from the peepholer -- this is not nice but works...
13337 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13338 pic16_mov2w (AOP(op),i);
13339 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13341 pic16_freeAsmop (op, NULL, ic, TRUE);
13343 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13347 /*-----------------------------------------------------------------*/
13348 /* genpic16Code - generate code for pic16 based controllers */
13349 /*-----------------------------------------------------------------*/
13351 * At this point, ralloc.c has gone through the iCode and attempted
13352 * to optimize in a way suitable for a PIC. Now we've got to generate
13353 * PIC instructions that correspond to the iCode.
13355 * Once the instructions are generated, we'll pass through both the
13356 * peep hole optimizer and the pCode optimizer.
13357 *-----------------------------------------------------------------*/
13359 void genpic16Code (iCode *lic)
13364 lineHead = lineCurr = NULL;
13366 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13367 pic16_addpBlock(pb);
13370 /* if debug information required */
13371 if (options.debug && currFunc) {
13373 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13378 for (ic = lic ; ic ; ic = ic->next ) {
13380 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13381 if ( cln != ic->lineno ) {
13382 if ( options.debug ) {
13383 debugFile->writeCLine (ic);
13386 if(!options.noCcodeInAsm) {
13387 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13388 printCLine(ic->filename, ic->lineno)));
13394 if(options.iCodeInAsm) {
13397 /* insert here code to print iCode as comment */
13398 l = Safe_strdup(printILine(ic));
13399 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13402 /* if the result is marked as
13403 * spilt and rematerializable or code for
13404 * this has already been generated then
13406 if (resultRemat(ic) || ic->generated )
13409 /* depending on the operation */
13428 /* IPOP happens only when trying to restore a
13429 * spilt live range, if there is an ifx statement
13430 * following this pop then the if statement might
13431 * be using some of the registers being popped which
13432 * would destroy the contents of the register so
13433 * we need to check for this condition and handle it */
13435 && ic->next->op == IFX
13436 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13437 genIfx (ic->next,ic);
13455 genEndFunction (ic);
13471 pic16_genPlus (ic) ;
13475 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13476 pic16_genMinus (ic);
13492 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13496 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13502 /* note these two are xlated by algebraic equivalence
13503 * during parsing SDCC.y */
13504 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13505 "got '>=' or '<=' shouldn't have come here");
13509 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13521 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13525 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13529 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13553 genRightShift (ic);
13556 case GET_VALUE_AT_ADDRESS:
13561 if (POINTER_SET(ic))
13588 addSet(&_G.sendSet,ic);
13591 case DUMMY_READ_VOLATILE:
13601 /* now we are ready to call the
13602 peep hole optimizer */
13603 if (!options.nopeep)
13604 peepHole (&lineHead);
13606 /* now do the actual printing */
13607 printLine (lineHead, codeOutFile);
13610 DFPRINTF((stderr,"printing pBlock\n\n"));
13611 pic16_printpBlock(stdout,pb);