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 ;
2046 /* offset is greater than
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);
2125 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2126 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2128 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2130 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2131 // pcop->type = PO_GPR_REGISTER;
2132 PCOR(pcop)->rIdx = rIdx;
2133 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2134 PCOR(pcop)->r->wasUsed=1;
2135 PCOR(pcop)->r->isFree=0;
2137 PCOR(pcop)->instance = offset;
2138 pcop->type = PCOR(pcop)->r->pc_type;
2140 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2141 // rs = aop->aopu.aop_reg[offset]->name;
2142 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2147 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2149 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2150 PCOR(pcop)->instance = offset;
2151 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2152 //if(PCOR(pcop)->r == NULL)
2153 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2157 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2158 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2161 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2162 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2165 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2166 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2167 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2168 pcop->type = PCOR(pcop)->r->pc_type;
2169 pcop->name = PCOR(pcop)->r->name;
2175 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2177 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2178 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2179 switch( aop->aopu.pcop->type ) {
2180 case PO_DIR: PCOR(pcop)->instance += offset; break;
2181 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2186 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2187 assert( 0 ); /* should never reach here */;
2192 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2193 "pic16_popGet got unsupported aop->type");
2196 /*-----------------------------------------------------------------*/
2197 /* pic16_aopPut - puts a string for a aop */
2198 /*-----------------------------------------------------------------*/
2199 void pic16_aopPut (asmop *aop, char *s, int offset)
2206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2208 if (aop->size && offset > ( aop->size - 1)) {
2209 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2210 "pic16_aopPut got offset > aop->size");
2214 /* will assign value to value */
2215 /* depending on where it is ofcourse */
2216 switch (aop->type) {
2219 sprintf(d,"(%s + %d)",
2220 aop->aopu.aop_dir,offset);
2221 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2224 sprintf(d,"%s",aop->aopu.aop_dir);
2227 DEBUGpic16_emitcode(";","%d",__LINE__);
2229 pic16_emitcode("movf","%s,w",s);
2230 pic16_emitcode("movwf","%s",d);
2233 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2234 if(offset >= aop->size) {
2235 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2238 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2241 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2248 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2249 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2252 strcmp(s,"r0") == 0 ||
2253 strcmp(s,"r1") == 0 ||
2254 strcmp(s,"r2") == 0 ||
2255 strcmp(s,"r3") == 0 ||
2256 strcmp(s,"r4") == 0 ||
2257 strcmp(s,"r5") == 0 ||
2258 strcmp(s,"r6") == 0 ||
2259 strcmp(s,"r7") == 0 )
2260 pic16_emitcode("mov","%s,%s ; %d",
2261 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2265 if(strcmp(s,"W")==0 )
2266 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2268 pic16_emitcode("movwf","%s",
2269 aop->aopu.aop_reg[offset]->name);
2271 if(strcmp(s,zero)==0) {
2272 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2274 } else if(strcmp(s,"W")==0) {
2275 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2276 pcop->type = PO_GPR_REGISTER;
2278 PCOR(pcop)->rIdx = -1;
2279 PCOR(pcop)->r = NULL;
2281 DEBUGpic16_emitcode(";","%d",__LINE__);
2282 pcop->name = Safe_strdup(s);
2283 pic16_emitpcode(POC_MOVFW,pcop);
2284 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2285 } else if(strcmp(s,one)==0) {
2286 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2287 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2289 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2297 if (aop->type == AOP_DPTR2)
2303 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2304 "pic16_aopPut writting to code space");
2308 while (offset > aop->coff) {
2310 pic16_emitcode ("inc","dptr");
2313 while (offset < aop->coff) {
2315 pic16_emitcode("lcall","__decdptr");
2320 /* if not in accumulater */
2323 pic16_emitcode ("movx","@dptr,a");
2325 if (aop->type == AOP_DPTR2)
2333 while (offset > aop->coff) {
2335 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2337 while (offset < aop->coff) {
2339 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2345 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2350 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2352 if (strcmp(s,"r0") == 0 ||
2353 strcmp(s,"r1") == 0 ||
2354 strcmp(s,"r2") == 0 ||
2355 strcmp(s,"r3") == 0 ||
2356 strcmp(s,"r4") == 0 ||
2357 strcmp(s,"r5") == 0 ||
2358 strcmp(s,"r6") == 0 ||
2359 strcmp(s,"r7") == 0 ) {
2361 sprintf(buffer,"a%s",s);
2362 pic16_emitcode("mov","@%s,%s",
2363 aop->aopu.aop_ptr->name,buffer);
2365 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2370 if (strcmp(s,"a") == 0)
2371 pic16_emitcode("push","acc");
2373 pic16_emitcode("push","%s",s);
2378 /* if bit variable */
2379 if (!aop->aopu.aop_dir) {
2380 pic16_emitcode("clr","a");
2381 pic16_emitcode("rlc","a");
2384 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2387 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2390 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2392 lbl = newiTempLabel(NULL);
2394 if (strcmp(s,"a")) {
2397 pic16_emitcode("clr","c");
2398 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2399 pic16_emitcode("cpl","c");
2400 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2401 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2408 if (strcmp(aop->aopu.aop_str[offset],s))
2409 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2414 if (!offset && (strcmp(s,"acc") == 0))
2417 if (strcmp(aop->aopu.aop_str[offset],s))
2418 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2422 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2423 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2424 // "pic16_aopPut got unsupported aop->type");
2430 /*-----------------------------------------------------------------*/
2431 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2432 /*-----------------------------------------------------------------*/
2433 void pic16_mov2w (asmop *aop, int offset)
2435 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2438 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2440 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2443 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2445 if(is_LitAOp(src)) {
2446 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2447 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2449 if(pic16_sameRegsOfs(src, dst, offset))return;
2450 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2451 pic16_popGet(dst, offset)));
2455 static void pic16_movLit2f(pCodeOp *pc, int lit)
2457 if (0 == (lit & 0x00ff))
2459 pic16_emitpcode (POC_CLRF, pc);
2460 } else if (0xff == (lit & 0x00ff))
2462 pic16_emitpcode (POC_SETF, pc);
2464 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2465 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2469 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2471 if(is_LitAOp(src)) {
2472 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2473 pic16_emitpcode(POC_MOVWF, dst);
2475 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2479 void pic16_testStackOverflow(void)
2481 #define GSTACK_TEST_NAME "_gstack_test"
2483 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2488 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2489 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2490 // strcpy(sym->rname, GSTACK_TEST_NAME);
2491 checkAddSym(&externs, sym);
2496 /* push pcop into stack */
2497 void pic16_pushpCodeOp(pCodeOp *pcop)
2499 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2500 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2501 if(pic16_options.gstack)
2502 pic16_testStackOverflow();
2506 /* pop pcop from stack */
2507 void pic16_poppCodeOp(pCodeOp *pcop)
2509 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2510 if(pic16_options.gstack)
2511 pic16_testStackOverflow();
2515 /*-----------------------------------------------------------------*/
2516 /* pushw - pushes wreg to stack */
2517 /*-----------------------------------------------------------------*/
2520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2521 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2522 if(pic16_options.gstack)
2523 pic16_testStackOverflow();
2527 /*-----------------------------------------------------------------*/
2528 /* pushaop - pushes aop to stack */
2529 /*-----------------------------------------------------------------*/
2530 void pushaop(asmop *aop, int offset)
2532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2534 if(_G.resDirect)return;
2536 if(is_LitAOp(aop)) {
2537 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2538 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2540 pic16_emitpcode(POC_MOVFF,
2541 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2544 if(pic16_options.gstack)
2545 pic16_testStackOverflow();
2548 /*-----------------------------------------------------------------*/
2549 /* popaop - pops aop from stack */
2550 /*-----------------------------------------------------------------*/
2551 void popaop(asmop *aop, int offset)
2553 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2554 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2555 if(pic16_options.gstack)
2556 pic16_testStackOverflow();
2559 void popaopidx(asmop *aop, int offset, int index)
2563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2565 if(STACK_MODEL_LARGE)ofs++;
2567 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2568 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2569 if(pic16_options.gstack)
2570 pic16_testStackOverflow();
2573 #if !(USE_GENERIC_SIGNED_SHIFT)
2574 /*-----------------------------------------------------------------*/
2575 /* reAdjustPreg - points a register back to where it should */
2576 /*-----------------------------------------------------------------*/
2577 static void reAdjustPreg (asmop *aop)
2581 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2583 if ((size = aop->size) <= 1)
2586 switch (aop->type) {
2590 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2594 if (aop->type == AOP_DPTR2)
2600 pic16_emitcode("lcall","__decdptr");
2603 if (aop->type == AOP_DPTR2)
2615 /*-----------------------------------------------------------------*/
2616 /* opIsGptr: returns non-zero if the passed operand is */
2617 /* a generic pointer type. */
2618 /*-----------------------------------------------------------------*/
2619 static int opIsGptr(operand *op)
2621 sym_link *type = operandType(op);
2623 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2624 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2632 /*-----------------------------------------------------------------*/
2633 /* pic16_getDataSize - get the operand data size */
2634 /*-----------------------------------------------------------------*/
2635 int pic16_getDataSize(operand *op)
2637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2640 return AOP_SIZE(op);
2642 // tsd- in the pic port, the genptr size is 1, so this code here
2643 // fails. ( in the 8051 port, the size was 4).
2646 size = AOP_SIZE(op);
2647 if (size == GPTRSIZE)
2649 sym_link *type = operandType(op);
2650 if (IS_GENPTR(type))
2652 /* generic pointer; arithmetic operations
2653 * should ignore the high byte (pointer type).
2656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_outAcc - output Acc */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_outAcc(operand *result)
2669 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2670 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2673 size = pic16_getDataSize(result);
2675 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2678 /* unsigned or positive */
2680 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2685 /*-----------------------------------------------------------------*/
2686 /* pic16_outBitC - output a bit C */
2687 /* Move to result the value of Carry flag -- VR */
2688 /*-----------------------------------------------------------------*/
2689 void pic16_outBitC(operand *result)
2693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2695 /* if the result is bit */
2696 if (AOP_TYPE(result) == AOP_CRY) {
2697 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2698 pic16_aopPut(AOP(result),"c",0);
2701 i = AOP_SIZE(result);
2703 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2705 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2709 /*-----------------------------------------------------------------*/
2710 /* pic16_outBitOp - output a bit from Op */
2711 /* Move to result the value of set/clr op -- VR */
2712 /*-----------------------------------------------------------------*/
2713 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2719 /* if the result is bit */
2720 if (AOP_TYPE(result) == AOP_CRY) {
2721 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2722 pic16_aopPut(AOP(result),"c",0);
2725 i = AOP_SIZE(result);
2727 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2729 pic16_emitpcode(POC_RRCF, pcop);
2730 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2734 /*-----------------------------------------------------------------*/
2735 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2736 /*-----------------------------------------------------------------*/
2737 void pic16_toBoolean(operand *oper)
2739 int size = AOP_SIZE(oper) - 1;
2742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2744 if ( AOP_TYPE(oper) != AOP_ACC) {
2745 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2748 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2752 /*-----------------------------------------------------------------*/
2753 /* genUminusFloat - unary minus for floating points */
2754 /*-----------------------------------------------------------------*/
2755 static void genUminusFloat(operand *op,operand *result)
2757 int size ,offset =0 ;
2760 /* for this we just need to flip the
2761 first it then copy the rest in place */
2762 size = AOP_SIZE(op);
2763 assert( size == AOP_SIZE(result) );
2766 pic16_mov2f(AOP(result), AOP(op), offset);
2770 /* toggle the MSB's highest bit */
2771 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2774 /*-----------------------------------------------------------------*/
2775 /* genUminus - unary minus code generation */
2776 /*-----------------------------------------------------------------*/
2777 static void genUminus (iCode *ic)
2780 sym_link *optype, *rtype;
2787 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2788 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2790 /* if both in bit space then special case */
2791 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2792 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2794 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2795 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2796 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2800 optype = operandType(IC_LEFT(ic));
2801 rtype = operandType(IC_RESULT(ic));
2804 /* if float then do float stuff */
2805 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2806 if(IS_FIXED(optype))
2807 debugf("implement fixed16x16 type\n", 0);
2809 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2813 /* otherwise subtract from zero by taking the 2's complement */
2814 size = AOP_SIZE(IC_LEFT(ic));
2815 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2816 label = newiTempLabel ( NULL );
2818 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2819 for (i=size-1; i > 0; i--) {
2820 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2822 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2823 for (i=1; i < size; i++) {
2824 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2825 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2828 for (i=size-1; i >= 0; i--) {
2829 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2830 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2833 for (i=0; i < size-2; i++) {
2834 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2835 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2837 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2839 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2842 pic16_emitpLabel (label->key);
2845 /* release the aops */
2846 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2847 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2851 /*-----------------------------------------------------------------*/
2852 /* saveRegisters - will look for a call and save the registers */
2853 /*-----------------------------------------------------------------*/
2854 static void saveRegisters(iCode *lic)
2861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2863 for (ic = lic ; ic ; ic = ic->next)
2864 if (ic->op == CALL || ic->op == PCALL)
2868 fprintf(stderr,"found parameter push with no function call\n");
2872 /* if the registers have been saved already then
2874 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2877 /* find the registers in use at this time
2878 and push them away to safety */
2879 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2883 if (options.useXstack) {
2884 if (bitVectBitValue(rsave,R0_IDX))
2885 pic16_emitcode("mov","b,r0");
2886 pic16_emitcode("mov","r0,%s",spname);
2887 for (i = 0 ; i < pic16_nRegs ; i++) {
2888 if (bitVectBitValue(rsave,i)) {
2890 pic16_emitcode("mov","a,b");
2892 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2893 pic16_emitcode("movx","@r0,a");
2894 pic16_emitcode("inc","r0");
2897 pic16_emitcode("mov","%s,r0",spname);
2898 if (bitVectBitValue(rsave,R0_IDX))
2899 pic16_emitcode("mov","r0,b");
2901 //for (i = 0 ; i < pic16_nRegs ; i++) {
2902 // if (bitVectBitValue(rsave,i))
2903 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2906 dtype = operandType(IC_LEFT(ic));
2907 if (currFunc && dtype &&
2908 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2909 IFFUNC_ISISR(currFunc->type) &&
2912 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2915 /*-----------------------------------------------------------------*/
2916 /* unsaveRegisters - pop the pushed registers */
2917 /*-----------------------------------------------------------------*/
2918 static void unsaveRegisters (iCode *ic)
2923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2924 /* find the registers in use at this time
2925 and push them away to safety */
2926 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2929 if (options.useXstack) {
2930 pic16_emitcode("mov","r0,%s",spname);
2931 for (i = pic16_nRegs ; i >= 0 ; i--) {
2932 if (bitVectBitValue(rsave,i)) {
2933 pic16_emitcode("dec","r0");
2934 pic16_emitcode("movx","a,@r0");
2936 pic16_emitcode("mov","b,a");
2938 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2942 pic16_emitcode("mov","%s,r0",spname);
2943 if (bitVectBitValue(rsave,R0_IDX))
2944 pic16_emitcode("mov","r0,b");
2946 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2947 // if (bitVectBitValue(rsave,i))
2948 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2955 /*-----------------------------------------------------------------*/
2957 /*-----------------------------------------------------------------*/
2958 static void pushSide(operand * oper, int size)
2961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2963 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2964 if (AOP_TYPE(oper) != AOP_REG &&
2965 AOP_TYPE(oper) != AOP_DIR &&
2967 pic16_emitcode("mov","a,%s",l);
2968 pic16_emitcode("push","acc");
2970 pic16_emitcode("push","%s",l);
2975 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2977 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2978 pic16_emitpcode(POC_MOVFW, src);
2979 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2981 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2982 src, pic16_popGet(AOP(op), offset)));
2987 /*-----------------------------------------------------------------*/
2988 /* assignResultValue - assign results to oper, rescall==1 is */
2989 /* called from genCall() or genPcall() */
2990 /*-----------------------------------------------------------------*/
2991 static void assignResultValue(operand * oper, int rescall)
2993 int size = AOP_SIZE(oper);
2997 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2998 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3001 /* assign result from a call/pcall function() */
3003 /* function results are stored in a special order,
3004 * see top of file with Function return policy, or manual */
3007 /* 8-bits, result in WREG */
3008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3011 /* 16-bits, result in PRODL:WREG */
3012 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3016 /* 24-bits, result in PRODH:PRODL:WREG */
3017 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3021 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3022 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3026 /* >32-bits, result on stack, and FSR0 points to beginning.
3027 * Fix stack when done */
3029 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3031 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3032 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3034 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3039 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3040 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3041 if(STACK_MODEL_LARGE) {
3043 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3047 int areg = 0; /* matching argument register */
3049 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3050 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3053 /* its called from genReceive (probably) -- VR */
3054 /* I hope this code will not be called from somewhere else in the future!
3055 * We manually set the pseudo stack pointer in genReceive. - dw
3057 if(!GpsuedoStkPtr && _G.useWreg) {
3058 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3060 /* The last byte in the assignment is in W */
3061 if(areg <= GpsuedoStkPtr) {
3063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3065 // debugf("receive from WREG\n", 0);
3067 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3070 _G.stack_lat = AOP_SIZE(oper)-1;
3075 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3076 // debugf("receive from STACK\n", 0);
3083 /*-----------------------------------------------------------------*/
3084 /* genIpush - generate code for pushing this gets a little complex */
3085 /*-----------------------------------------------------------------*/
3086 static void genIpush (iCode *ic)
3088 // int size, offset=0;
3091 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3094 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3096 /* send to stack as normal */
3097 addSet(&_G.sendSet,ic);
3098 // addSetHead(&_G.sendSet,ic);
3099 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3104 int size, offset = 0 ;
3108 /* if this is not a parm push : ie. it is spill push
3109 and spill push is always done on the local stack */
3110 if (!ic->parmPush) {
3112 /* and the item is spilt then do nothing */
3113 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3116 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3117 size = AOP_SIZE(IC_LEFT(ic));
3118 /* push it on the stack */
3120 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3125 pic16_emitcode("push","%s",l);
3130 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3134 /*-----------------------------------------------------------------*/
3135 /* genIpop - recover the registers: can happen only for spilling */
3136 /*-----------------------------------------------------------------*/
3137 static void genIpop (iCode *ic)
3140 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3145 /* if the temp was not pushed then */
3146 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3149 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3150 size = AOP_SIZE(IC_LEFT(ic));
3153 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3156 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3161 /*-----------------------------------------------------------------*/
3162 /* unsaverbank - restores the resgister bank from stack */
3163 /*-----------------------------------------------------------------*/
3164 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3166 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3172 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3174 if (options.useXstack) {
3176 r = getFreePtr(ic,&aop,FALSE);
3179 pic16_emitcode("mov","%s,_spx",r->name);
3180 pic16_emitcode("movx","a,@%s",r->name);
3181 pic16_emitcode("mov","psw,a");
3182 pic16_emitcode("dec","%s",r->name);
3185 pic16_emitcode ("pop","psw");
3188 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3189 if (options.useXstack) {
3190 pic16_emitcode("movx","a,@%s",r->name);
3191 //pic16_emitcode("mov","(%s+%d),a",
3192 // regspic16[i].base,8*bank+regspic16[i].offset);
3193 pic16_emitcode("dec","%s",r->name);
3196 pic16_emitcode("pop",""); //"(%s+%d)",
3197 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3200 if (options.useXstack) {
3202 pic16_emitcode("mov","_spx,%s",r->name);
3203 pic16_freeAsmop(NULL,aop,ic,TRUE);
3209 /*-----------------------------------------------------------------*/
3210 /* saverbank - saves an entire register bank on the stack */
3211 /*-----------------------------------------------------------------*/
3212 static void saverbank (int bank, iCode *ic, bool pushPsw)
3214 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3221 if (options.useXstack) {
3224 r = getFreePtr(ic,&aop,FALSE);
3225 pic16_emitcode("mov","%s,_spx",r->name);
3229 for (i = 0 ; i < pic16_nRegs ;i++) {
3230 if (options.useXstack) {
3231 pic16_emitcode("inc","%s",r->name);
3232 //pic16_emitcode("mov","a,(%s+%d)",
3233 // regspic16[i].base,8*bank+regspic16[i].offset);
3234 pic16_emitcode("movx","@%s,a",r->name);
3236 pic16_emitcode("push","");// "(%s+%d)",
3237 //regspic16[i].base,8*bank+regspic16[i].offset);
3241 if (options.useXstack) {
3242 pic16_emitcode("mov","a,psw");
3243 pic16_emitcode("movx","@%s,a",r->name);
3244 pic16_emitcode("inc","%s",r->name);
3245 pic16_emitcode("mov","_spx,%s",r->name);
3246 pic16_freeAsmop (NULL,aop,ic,TRUE);
3249 pic16_emitcode("push","psw");
3251 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3259 static int wparamCmp(void *p1, void *p2)
3261 return (!strcmp((char *)p1, (char *)p2));
3264 int inWparamList(char *s)
3266 return isinSetWith(wparamList, s, wparamCmp);
3270 /*-----------------------------------------------------------------*/
3271 /* genCall - generates a call statement */
3272 /*-----------------------------------------------------------------*/
3273 static void genCall (iCode *ic)
3283 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3284 /* if caller saves & we have not saved then */
3285 // if (!ic->regsSaved)
3286 // saveRegisters(ic);
3288 /* initialise stackParms for IPUSH pushes */
3289 // stackParms = psuedoStkPtr;
3290 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3291 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3292 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3295 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3298 /* if send set is not empty the assign */
3301 int psuedoStkPtr=-1;
3302 int firstTimeThruLoop = 1;
3305 /* reverse sendSet if function is not reentrant */
3306 if(!IFFUNC_ISREENT(ftype))
3307 _G.sendSet = reverseSet(_G.sendSet);
3309 /* First figure how many parameters are getting passed */
3313 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3317 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3318 size = AOP_SIZE(IC_LEFT(sic));
3322 /* pass the last byte through WREG */
3326 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3327 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3328 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3330 if(!firstTimeThruLoop) {
3331 /* If this is not the first time we've been through the loop
3332 * then we need to save the parameter in a temporary
3333 * register. The last byte of the last parameter is
3337 // --psuedoStkPtr; // sanity check
3341 firstTimeThruLoop=0;
3343 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3348 /* all arguments are passed via stack */
3352 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3353 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3354 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3356 // pushaop(AOP(IC_LEFT(sic)), size);
3357 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3364 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3368 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3369 pushw(); /* save last parameter to stack if functions has varargs */
3373 } else use_wreg = 0;
3375 _G.stackRegSet = _G.sendSet;
3380 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3384 /* if we need to assign a result value */
3385 if ((IS_ITEMP(IC_RESULT(ic))
3386 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3387 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3388 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3391 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3394 assignResultValue(IC_RESULT(ic), 1);
3396 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3397 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3399 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3402 if(!stackParms && ic->parmBytes) {
3403 stackParms = ic->parmBytes;
3406 stackParms -= use_wreg;
3409 if(stackParms == 1) {
3410 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3412 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3413 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3415 if(STACK_MODEL_LARGE) {
3417 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3422 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3425 /* adjust the stack for parameters if required */
3426 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3429 /* if register bank was saved then pop them */
3431 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3433 /* if we hade saved some registers then unsave them */
3434 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3435 unsaveRegisters (ic);
3441 /*-----------------------------------------------------------------*/
3442 /* genPcall - generates a call by pointer statement */
3443 /* new version, created from genCall - HJD */
3444 /*-----------------------------------------------------------------*/
3445 static void genPcall (iCode *ic)
3449 symbol *retlbl = newiTempLabel(NULL);
3450 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3454 fntype = operandType( IC_LEFT(ic) )->next;
3456 /* if send set is not empty the assign */
3459 int psuedoStkPtr=-1;
3461 /* reverse sendSet if function is not reentrant */
3462 if(!IFFUNC_ISREENT(fntype))
3463 _G.sendSet = reverseSet(_G.sendSet);
3467 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3470 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3471 size = AOP_SIZE(IC_LEFT(sic));
3474 /* all parameters are passed via stack, since WREG is clobbered
3475 * by the calling sequence */
3477 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3478 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3479 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3481 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3485 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3488 _G.stackRegSet = _G.sendSet;
3492 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3494 // push return address
3495 // push $ on return stack, then replace with retlbl
3497 /* Thanks to Thorsten Klose for pointing out that the following
3498 * snippet should be interrupt safe */
3499 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3500 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3502 pic16_emitpcodeNULLop(POC_PUSH);
3504 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3505 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3506 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3507 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3508 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3509 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3512 /* restore interrupt control register */
3513 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3514 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3516 /* make the call by writing the pointer into pc */
3517 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3518 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3520 // note: MOVFF to PCL not allowed
3521 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3522 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3525 /* return address is here: (X) */
3526 pic16_emitpLabelFORCE(retlbl->key);
3528 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3531 /* if we need assign a result value */
3532 if ((IS_ITEMP(IC_RESULT(ic))
3533 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3534 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3535 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3538 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3541 assignResultValue(IC_RESULT(ic), 1);
3543 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3544 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3546 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3549 // stackParms -= use_wreg;
3552 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3553 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3554 if(STACK_MODEL_LARGE) {
3556 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3561 /*-----------------------------------------------------------------*/
3562 /* resultRemat - result is rematerializable */
3563 /*-----------------------------------------------------------------*/
3564 static int resultRemat (iCode *ic)
3566 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3567 if (SKIP_IC(ic) || ic->op == IFX)
3570 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3571 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3572 if (sym->remat && !POINTER_SET(ic))
3579 #if defined(__BORLANDC__) || defined(_MSC_VER)
3580 #define STRCASECMP stricmp
3582 #define STRCASECMP strcasecmp
3586 /*-----------------------------------------------------------------*/
3587 /* inExcludeList - return 1 if the string is in exclude Reg list */
3588 /*-----------------------------------------------------------------*/
3589 static bool inExcludeList(char *s)
3591 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3594 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3595 if (options.excludeRegs[i] &&
3596 STRCASECMP(options.excludeRegs[i],"none") == 0)
3599 for ( i = 0 ; options.excludeRegs[i]; i++) {
3600 if (options.excludeRegs[i] &&
3601 STRCASECMP(s,options.excludeRegs[i]) == 0)
3608 /*-----------------------------------------------------------------*/
3609 /* genFunction - generated code for function entry */
3610 /*-----------------------------------------------------------------*/
3611 static void genFunction (iCode *ic)
3617 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3619 pic16_labelOffset += (max_key+4);
3624 ftype = operandType(IC_LEFT(ic));
3625 sym = OP_SYMBOL(IC_LEFT(ic));
3627 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3628 /* create an absolute section at the interrupt vector:
3629 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3634 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3636 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3637 sprintf(asymname, "ivec_%s", sym->name);
3639 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3641 /* when an interrupt is declared as naked, do not emit the special
3642 * wrapper segment at vector address. The user should take care for
3643 * this instead. -- VR */
3645 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3646 asym = newSymbol(asymname, 0);
3647 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3648 pic16_addpBlock( apb );
3650 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3651 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3652 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3653 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3654 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3656 /* mark the end of this tiny function */
3657 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3659 sprintf(asymname, "%s", sym->rname);
3665 abSym = Safe_calloc(1, sizeof(absSym));
3666 strcpy(abSym->name, asymname);
3668 switch( FUNC_INTNO(sym->type) ) {
3669 case 0: abSym->address = 0x000000; break;
3670 case 1: abSym->address = 0x000008; break;
3671 case 2: abSym->address = 0x000018; break;
3674 // fprintf(stderr, "no interrupt number is given\n");
3675 abSym->address = -1; break;
3678 /* relocate interrupt vectors if needed */
3679 if(abSym->address != -1)
3680 abSym->address += pic16_options.ivt_loc;
3682 addSet(&absSymSet, abSym);
3686 /* create the function header */
3687 pic16_emitcode(";","-----------------------------------------");
3688 pic16_emitcode(";"," function %s",sym->name);
3689 pic16_emitcode(";","-----------------------------------------");
3691 pic16_emitcode("","%s:",sym->rname);
3692 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3697 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3698 if(!strcmp(ab->name, sym->rname)) {
3699 pic16_pBlockConvert2Absolute(pb);
3705 if(IFFUNC_ISNAKED(ftype)) {
3706 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3710 /* if critical function then turn interrupts off */
3711 if (IFFUNC_ISCRITICAL(ftype)) {
3712 //pic16_emitcode("clr","ea");
3715 currFunc = sym; /* update the currFunc symbol */
3716 _G.fregsUsed = sym->regsUsed;
3717 _G.sregsAlloc = newBitVect(128);
3720 /* if this is an interrupt service routine then
3721 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3722 if (IFFUNC_ISISR(sym->type)) {
3723 _G.usefastretfie = 1; /* use shadow registers by default */
3725 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3726 if(!FUNC_ISSHADOWREGS(sym->type)) {
3727 /* do not save WREG,STATUS,BSR for high priority interrupts
3728 * because they are stored in the hardware shadow registers already */
3729 _G.usefastretfie = 0;
3730 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3731 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3732 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3735 /* these should really be optimized somehow, because not all
3736 * interrupt handlers modify them */
3737 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3738 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3739 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3740 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3742 // pic16_pBlockConvert2ISR(pb);
3745 /* emit code to setup stack frame if user enabled,
3746 * and function is not main() */
3748 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3749 if(strcmp(sym->name, "main")) {
3751 || !options.ommitFramePtr
3753 || IFFUNC_ARGS(sym->type)
3754 || FUNC_HASSTACKPARM(sym->etype)
3756 /* setup the stack frame */
3757 if(STACK_MODEL_LARGE)
3758 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3759 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3761 if(STACK_MODEL_LARGE)
3762 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3763 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3767 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3770 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3773 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3775 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3778 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3779 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3786 /* if callee-save to be used for this function
3787 * then save the registers being used in this function */
3788 // if (IFFUNC_CALLEESAVES(sym->type))
3789 if(strcmp(sym->name, "main")) {
3792 /* if any registers used */
3793 if (sym->regsUsed) {
3794 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3797 /* save the registers used */
3798 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3799 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3800 if (bitVectBitValue(sym->regsUsed,i)) {
3802 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3804 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3807 if(!pic16_regWithIdx(i)->wasUsed) {
3808 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3809 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3810 pic16_regWithIdx(i)->wasUsed = 1;
3817 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3818 for(i=0;i<sym->regsUsed->size;i++) {
3819 if(bitVectBitValue(sym->regsUsed, i)) {
3824 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3827 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3832 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3833 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3836 /*-----------------------------------------------------------------*/
3837 /* genEndFunction - generates epilogue for functions */
3838 /*-----------------------------------------------------------------*/
3839 static void genEndFunction (iCode *ic)
3841 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3845 if(IFFUNC_ISNAKED(sym->type)) {
3846 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3852 /* add code for ISCRITICAL */
3853 if(IFFUNC_ISCRITICAL(sym->type)) {
3854 /* if critical function, turn on interrupts */
3856 /* TODO: add code here -- VR */
3859 // sym->regsUsed = _G.fregsUsed;
3861 /* now we need to restore the registers */
3862 /* if any registers used */
3864 /* first restore registers that might be used for stack access */
3865 if(_G.sregsAllocSet) {
3868 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3869 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3870 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3874 if (strcmp(sym->name, "main") && sym->regsUsed) {
3877 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3878 /* restore registers used */
3879 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3880 for ( i = sym->regsUsed->size; i >= 0; i--) {
3881 if (bitVectBitValue(sym->regsUsed,i)) {
3882 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3886 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3891 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3893 if (sym->stack == 1) {
3894 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3895 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3897 // we have to add more than one...
3898 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3899 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3900 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3902 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3903 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3904 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3908 if(strcmp(sym->name, "main")) {
3910 || !options.ommitFramePtr
3912 || IFFUNC_ARGS(sym->type)
3913 || FUNC_HASSTACKPARM(sym->etype)
3915 /* restore stack frame */
3916 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3917 if(STACK_MODEL_LARGE)
3918 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3924 if (IFFUNC_ISISR(sym->type)) {
3925 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3926 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3928 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3930 if(!FUNC_ISSHADOWREGS(sym->type)) {
3931 /* do not restore interrupt vector for WREG,STATUS,BSR
3932 * for high priority interrupt, see genFunction */
3933 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3934 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3935 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3937 // _G.interruptvector = 0; /* sanity check */
3940 /* if debug then send end of function */
3941 /* if (options.debug && currFunc) */
3943 debugFile->writeEndFunction (currFunc, ic, 1);
3946 if(_G.usefastretfie)
3947 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3949 pic16_emitpcodeNULLop(POC_RETFIE);
3951 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3953 _G.usefastretfie = 0;
3957 if (IFFUNC_ISCRITICAL(sym->type)) {
3958 pic16_emitcode("setb","ea");
3961 /* if debug then send end of function */
3963 debugFile->writeEndFunction (currFunc, ic, 1);
3966 /* insert code to restore stack frame, if user enabled it
3967 * and function is not main() */
3970 pic16_emitpcodeNULLop(POC_RETURN);
3972 /* Mark the end of a function */
3973 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3977 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3979 unsigned long lit=1;
3984 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3985 if(AOP_TYPE(op) == AOP_LIT) {
3986 if(!IS_FLOAT(operandType( op ))) {
3987 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3990 unsigned long lit_int;
3994 /* take care if literal is a float */
3995 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4000 if (AOP_TYPE(op) == AOP_LIT) {
4001 /* FIXME: broken for
4002 * char __at(0x456) foo;
4004 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4005 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4006 } else if (AOP_TYPE(op) == AOP_PCODE
4007 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4008 /* char *s= "aaa"; return s; */
4009 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4010 * that the generic pointer is interpreted correctly
4011 * as referring to __code space, but this is fragile! */
4012 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4013 /* XXX: should check that dest != WREG */
4014 pic16_emitpcode(POC_MOVWF, dest);
4016 if(dest->type == PO_WREG && (offset == 0)) {
4017 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4020 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4024 /*-----------------------------------------------------------------*/
4025 /* genRet - generate code for return statement */
4026 /*-----------------------------------------------------------------*/
4027 static void genRet (iCode *ic)
4033 /* if we have no return value then
4034 * just generate the "ret" */
4039 /* we have something to return then
4040 * move the return value into place */
4041 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4042 size = AOP_SIZE(IC_LEFT(ic));
4046 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4049 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4052 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4054 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4057 /* >32-bits, setup stack and FSR0 */
4059 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4060 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4062 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4064 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4069 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4070 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4072 if(STACK_MODEL_LARGE) {
4073 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4074 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4076 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4081 /* old code, left here for reference -- VR */
4085 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4087 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4088 pic16_emitpcomment("push %s",l);
4091 DEBUGpic16_emitcode(";", "%d", __LINE__);
4092 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4093 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4095 if (strcmp(fReturn[offset],l)) {
4096 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4097 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4098 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4100 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4104 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4114 if (strcmp(fReturn[pushed],"a"))
4115 pic16_emitcode("pop",fReturn[pushed]);
4117 pic16_emitcode("pop","acc");
4123 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4126 /* generate a jump to the return label
4127 * if the next is not the return statement */
4128 if (!(ic->next && ic->next->op == LABEL
4129 && IC_LABEL(ic->next) == returnLabel)) {
4131 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4132 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4136 /*-----------------------------------------------------------------*/
4137 /* genLabel - generates a label */
4138 /*-----------------------------------------------------------------*/
4139 static void genLabel (iCode *ic)
4143 /* special case never generate */
4144 if (IC_LABEL(ic) == entryLabel)
4147 pic16_emitpLabel(IC_LABEL(ic)->key);
4148 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4151 /*-----------------------------------------------------------------*/
4152 /* genGoto - generates a goto */
4153 /*-----------------------------------------------------------------*/
4155 static void genGoto (iCode *ic)
4158 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4159 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4163 /*-----------------------------------------------------------------*/
4164 /* genMultbits :- multiplication of bits */
4165 /*-----------------------------------------------------------------*/
4166 static void genMultbits (operand *left,
4172 if(!pic16_sameRegs(AOP(result),AOP(right)))
4173 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4175 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4176 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4177 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4182 /*-----------------------------------------------------------------*/
4183 /* genMultOneByte : 8 bit multiplication & division */
4184 /*-----------------------------------------------------------------*/
4185 static void genMultOneByte (operand *left,
4191 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4192 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4194 /* (if two literals, the value is computed before) */
4195 /* if one literal, literal on the right */
4196 if (AOP_TYPE(left) == AOP_LIT){
4202 /* size is already checked in genMult == 1 */
4203 // size = AOP_SIZE(result);
4205 if (AOP_TYPE(right) == AOP_LIT){
4206 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4207 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4211 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4212 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4213 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4214 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4217 pic16_genMult8X8_8 (left, right,result);
4220 /*-----------------------------------------------------------------*/
4221 /* genMultOneWord : 16 bit multiplication */
4222 /*-----------------------------------------------------------------*/
4223 static void genMultOneWord (operand *left,
4228 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4229 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4231 /* (if two literals, the value is computed before)
4232 * if one literal, literal on the right */
4233 if (AOP_TYPE(left) == AOP_LIT){
4239 /* size is checked already == 2 */
4240 // size = AOP_SIZE(result);
4242 if (AOP_TYPE(right) == AOP_LIT) {
4243 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4244 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4245 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4246 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4248 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4249 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4250 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4251 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4254 pic16_genMult16X16_16(left, right,result);
4257 /*-----------------------------------------------------------------*/
4258 /* genMultOneLong : 32 bit multiplication */
4259 /*-----------------------------------------------------------------*/
4260 static void genMultOneLong (operand *left,
4265 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4266 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4268 /* (if two literals, the value is computed before)
4269 * if one literal, literal on the right */
4270 if (AOP_TYPE(left) == AOP_LIT){
4276 /* size is checked already == 4 */
4277 // size = AOP_SIZE(result);
4279 if (AOP_TYPE(right) == AOP_LIT) {
4280 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4281 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4282 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4283 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4285 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4286 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4287 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4288 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4291 pic16_genMult32X32_32(left, right,result);
4296 /*-----------------------------------------------------------------*/
4297 /* genMult - generates code for multiplication */
4298 /*-----------------------------------------------------------------*/
4299 static void genMult (iCode *ic)
4301 operand *left = IC_LEFT(ic);
4302 operand *right = IC_RIGHT(ic);
4303 operand *result= IC_RESULT(ic);
4306 /* assign the amsops */
4307 pic16_aopOp (left,ic,FALSE);
4308 pic16_aopOp (right,ic,FALSE);
4309 pic16_aopOp (result,ic,TRUE);
4311 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4313 /* special cases first *
4315 if (AOP_TYPE(left) == AOP_CRY
4316 && AOP_TYPE(right)== AOP_CRY) {
4317 genMultbits(left,right,result);
4321 /* if both are of size == 1 */
4322 if(AOP_SIZE(left) == 1
4323 && AOP_SIZE(right) == 1) {
4324 genMultOneByte(left,right,result);
4328 /* if both are of size == 2 */
4329 if(AOP_SIZE(left) == 2
4330 && AOP_SIZE(right) == 2) {
4331 genMultOneWord(left, right, result);
4335 /* if both are of size == 4 */
4336 if(AOP_SIZE(left) == 4
4337 && AOP_SIZE(right) == 4) {
4338 genMultOneLong(left, right, result);
4342 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4345 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4346 /* should have been converted to function call */
4350 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4352 pic16_freeAsmop(result,NULL,ic,TRUE);
4355 /*-----------------------------------------------------------------*/
4356 /* genDivbits :- division of bits */
4357 /*-----------------------------------------------------------------*/
4358 static void genDivbits (operand *left,
4365 /* the result must be bit */
4366 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4367 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4371 pic16_emitcode("div","ab");
4372 pic16_emitcode("rrc","a");
4373 pic16_aopPut(AOP(result),"c",0);
4376 /*-----------------------------------------------------------------*/
4377 /* genDivOneByte : 8 bit division */
4378 /*-----------------------------------------------------------------*/
4379 static void genDivOneByte (operand *left,
4383 sym_link *opetype = operandType(result);
4388 /* result = divident / divisor
4389 * - divident may be a register or a literal,
4390 * - divisor may be a register or a literal,
4391 * so there are 3 cases (literal / literal is optimized
4392 * by the front-end) to handle.
4393 * In addition we must handle signed and unsigned, which
4394 * result in 6 final different cases -- VR */
4398 size = AOP_SIZE(result) - 1;
4400 /* signed or unsigned */
4401 if (SPEC_USIGN(opetype)) {
4402 pCodeOp *pct1, /* count */
4405 symbol *label1, *label2, *label3;;
4408 /* unsigned is easy */
4410 pct1 = pic16_popGetTempReg(1);
4411 pct2 = pic16_popGetTempReg(1);
4412 pct3 = pic16_popGetTempReg(1);
4414 label1 = newiTempLabel(NULL);
4415 label2 = newiTempLabel(NULL);
4416 label3 = newiTempLabel(NULL);
4418 /* the following algorithm is extracted from divuint.c */
4420 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4421 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4423 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4425 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4427 pic16_emitpLabel(label1->key);
4430 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4434 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4438 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4440 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4441 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4443 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4444 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4445 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4447 pic16_emitpLabel( label3->key );
4448 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4449 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4453 pic16_emitpLabel(label2->key);
4454 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4455 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4456 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4458 /* result is in wreg */
4459 if(AOP_TYPE(result) != AOP_ACC)
4460 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4462 pic16_popReleaseTempReg( pct3, 1);
4463 pic16_popReleaseTempReg( pct2, 1);
4464 pic16_popReleaseTempReg( pct1, 1);
4469 /* signed is a little bit more difficult */
4471 /* save the signs of the operands */
4472 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4474 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4475 pic16_emitcode("push","acc"); /* save it on the stack */
4477 /* now sign adjust for both left & right */
4478 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4480 lbl = newiTempLabel(NULL);
4481 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4482 pic16_emitcode("cpl","a");
4483 pic16_emitcode("inc","a");
4484 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4485 pic16_emitcode("mov","b,a");
4487 /* sign adjust left side */
4488 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4491 lbl = newiTempLabel(NULL);
4492 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4493 pic16_emitcode("cpl","a");
4494 pic16_emitcode("inc","a");
4495 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4497 /* now the division */
4498 pic16_emitcode("div","ab");
4499 /* we are interested in the lower order
4501 pic16_emitcode("mov","b,a");
4502 lbl = newiTempLabel(NULL);
4503 pic16_emitcode("pop","acc");
4504 /* if there was an over flow we don't
4505 adjust the sign of the result */
4506 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4507 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4509 pic16_emitcode("clr","a");
4510 pic16_emitcode("subb","a,b");
4511 pic16_emitcode("mov","b,a");
4512 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4514 /* now we are done */
4515 pic16_aopPut(AOP(result),"b",0);
4517 pic16_emitcode("mov","c,b.7");
4518 pic16_emitcode("subb","a,acc");
4521 pic16_aopPut(AOP(result),"a",offset++);
4525 /*-----------------------------------------------------------------*/
4526 /* genDiv - generates code for division */
4527 /*-----------------------------------------------------------------*/
4528 static void genDiv (iCode *ic)
4530 operand *left = IC_LEFT(ic);
4531 operand *right = IC_RIGHT(ic);
4532 operand *result= IC_RESULT(ic);
4535 /* Division is a very lengthy algorithm, so it is better
4536 * to call support routines than inlining algorithm.
4537 * Division functions written here just in case someone
4538 * wants to inline and not use the support libraries -- VR */
4542 /* assign the amsops */
4543 pic16_aopOp (left,ic,FALSE);
4544 pic16_aopOp (right,ic,FALSE);
4545 pic16_aopOp (result,ic,TRUE);
4547 /* special cases first */
4549 if (AOP_TYPE(left) == AOP_CRY &&
4550 AOP_TYPE(right)== AOP_CRY) {
4551 genDivbits(left,right,result);
4555 /* if both are of size == 1 */
4556 if (AOP_SIZE(left) == 1 &&
4557 AOP_SIZE(right) == 1 ) {
4558 genDivOneByte(left,right,result);
4562 /* should have been converted to function call */
4565 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4566 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4567 pic16_freeAsmop(result,NULL,ic,TRUE);
4570 /*-----------------------------------------------------------------*/
4571 /* genModbits :- modulus of bits */
4572 /*-----------------------------------------------------------------*/
4573 static void genModbits (operand *left,
4581 werror(W_POSSBUG2, __FILE__, __LINE__);
4582 /* the result must be bit */
4583 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4584 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4588 pic16_emitcode("div","ab");
4589 pic16_emitcode("mov","a,b");
4590 pic16_emitcode("rrc","a");
4591 pic16_aopPut(AOP(result),"c",0);
4594 /*-----------------------------------------------------------------*/
4595 /* genModOneByte : 8 bit modulus */
4596 /*-----------------------------------------------------------------*/
4597 static void genModOneByte (operand *left,
4601 sym_link *opetype = operandType(result);
4606 werror(W_POSSBUG2, __FILE__, __LINE__);
4608 /* signed or unsigned */
4609 if (SPEC_USIGN(opetype)) {
4610 /* unsigned is easy */
4611 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4612 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4614 pic16_emitcode("div","ab");
4615 pic16_aopPut(AOP(result),"b",0);
4619 /* signed is a little bit more difficult */
4621 /* save the signs of the operands */
4622 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4625 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4626 pic16_emitcode("push","acc"); /* save it on the stack */
4628 /* now sign adjust for both left & right */
4629 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4632 lbl = newiTempLabel(NULL);
4633 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4634 pic16_emitcode("cpl","a");
4635 pic16_emitcode("inc","a");
4636 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4637 pic16_emitcode("mov","b,a");
4639 /* sign adjust left side */
4640 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4643 lbl = newiTempLabel(NULL);
4644 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4645 pic16_emitcode("cpl","a");
4646 pic16_emitcode("inc","a");
4647 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4649 /* now the multiplication */
4650 pic16_emitcode("div","ab");
4651 /* we are interested in the lower order
4653 lbl = newiTempLabel(NULL);
4654 pic16_emitcode("pop","acc");
4655 /* if there was an over flow we don't
4656 adjust the sign of the result */
4657 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4658 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4660 pic16_emitcode("clr","a");
4661 pic16_emitcode("subb","a,b");
4662 pic16_emitcode("mov","b,a");
4663 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4665 /* now we are done */
4666 pic16_aopPut(AOP(result),"b",0);
4670 /*-----------------------------------------------------------------*/
4671 /* genMod - generates code for division */
4672 /*-----------------------------------------------------------------*/
4673 static void genMod (iCode *ic)
4675 operand *left = IC_LEFT(ic);
4676 operand *right = IC_RIGHT(ic);
4677 operand *result= IC_RESULT(ic);
4681 /* assign the amsops */
4682 pic16_aopOp (left,ic,FALSE);
4683 pic16_aopOp (right,ic,FALSE);
4684 pic16_aopOp (result,ic,TRUE);
4686 /* special cases first */
4688 if (AOP_TYPE(left) == AOP_CRY &&
4689 AOP_TYPE(right)== AOP_CRY) {
4690 genModbits(left,right,result);
4694 /* if both are of size == 1 */
4695 if (AOP_SIZE(left) == 1 &&
4696 AOP_SIZE(right) == 1 ) {
4697 genModOneByte(left,right,result);
4701 /* should have been converted to function call */
4705 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4707 pic16_freeAsmop(result,NULL,ic,TRUE);
4710 /*-----------------------------------------------------------------*/
4711 /* genIfxJump :- will create a jump depending on the ifx */
4712 /*-----------------------------------------------------------------*/
4714 note: May need to add parameter to indicate when a variable is in bit space.
4716 static void genIfxJump (iCode *ic, char *jval)
4720 /* if true label then we jump if condition
4722 if ( IC_TRUE(ic) ) {
4724 if(strcmp(jval,"a") == 0)
4726 else if (strcmp(jval,"c") == 0)
4729 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4730 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4733 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4734 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4738 /* false label is present */
4739 if(strcmp(jval,"a") == 0)
4741 else if (strcmp(jval,"c") == 0)
4744 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4745 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4748 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4749 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4754 /* mark the icode as generated */
4758 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4762 /* if true label then we jump if condition
4764 if ( IC_TRUE(ic) ) {
4765 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4766 pic16_emitpcode(POC_BTFSC, jop);
4768 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4769 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4772 /* false label is present */
4773 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4774 pic16_emitpcode(POC_BTFSS, jop);
4776 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4777 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4781 /* mark the icode as generated */
4788 /*-----------------------------------------------------------------*/
4790 /*-----------------------------------------------------------------*/
4791 static void genSkip(iCode *ifx,int status_bit)
4793 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4797 if ( IC_TRUE(ifx) ) {
4798 switch(status_bit) {
4813 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4814 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4818 switch(status_bit) {
4832 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4833 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4840 /*-----------------------------------------------------------------*/
4842 /*-----------------------------------------------------------------*/
4843 static void genSkipc(resolvedIfx *rifx)
4845 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4855 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4856 rifx->generated = 1;
4859 #if !(USE_SIMPLE_GENCMP)
4860 /*-----------------------------------------------------------------*/
4862 /*-----------------------------------------------------------------*/
4863 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4865 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4870 if( (rifx->condition ^ invert_condition) & 1)
4875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4876 rifx->generated = 1;
4881 /*-----------------------------------------------------------------*/
4883 /*-----------------------------------------------------------------*/
4884 static void genSkipz(iCode *ifx, int condition)
4895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4897 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4900 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4902 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4907 #if !(USE_SIMPLE_GENCMP)
4908 /*-----------------------------------------------------------------*/
4910 /*-----------------------------------------------------------------*/
4911 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4917 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4919 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4922 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4923 rifx->generated = 1;
4928 /*-----------------------------------------------------------------*/
4929 /* genChkZeroes :- greater or less than comparison */
4930 /* For each byte in a literal that is zero, inclusive or the */
4931 /* the corresponding byte in the operand with W */
4932 /* returns true if any of the bytes are zero */
4933 /*-----------------------------------------------------------------*/
4934 static int genChkZeroes(operand *op, int lit, int size)
4941 i = (lit >> (size*8)) & 0xff;
4945 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4947 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4957 /*-----------------------------------------------------------------*/
4958 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4959 /* aop (if it's NOT a literal) or from lit (if */
4960 /* aop is a literal) */
4961 /*-----------------------------------------------------------------*/
4962 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4963 if (aop->type == AOP_LIT) {
4964 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4966 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4970 /*-----------------------------------------------------------------*/
4971 /* genCmp :- greater or less than comparison */
4972 /*-----------------------------------------------------------------*/
4974 #if USE_SIMPLE_GENCMP /* { */
4976 /* genCmp performs a left < right comparison, stores
4977 * the outcome in result (if != NULL) and generates
4978 * control flow code for the ifx (if != NULL).
4980 * This version leaves in sequences like
4981 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4982 * which should be optmized by the peephole
4983 * optimizer - RN 2005-01-01 */
4984 static void genCmp (operand *left,operand *right,
4985 operand *result, iCode *ifx, int sign)
4998 assert (left && right);
4999 assert (AOP_SIZE(left) == AOP_SIZE(right));
5001 size = AOP_SIZE(right) - 1;
5002 mask = (0x100UL << (size*8)) - 1;
5003 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5008 resolveIfx (&rIfx, ifx);
5010 /* handle for special cases */
5011 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5014 /**********************************************************************
5015 * handle bits - bit compares are promoted to int compares seemingly! *
5016 **********************************************************************/
5018 // THIS IS COMPLETELY UNTESTED!
5019 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5020 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5021 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5022 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5025 // 1 < {0,1} is false --> clear C by skipping the next instruction
5026 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5027 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5028 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5029 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5030 emitCLRC; // only skipped for left=0 && right=1
5032 goto correct_result_in_carry;
5036 /*************************************************
5037 * make sure that left is register (or the like) *
5038 *************************************************/
5039 if (!isAOP_REGlike(left)) {
5040 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5041 assert (isAOP_LIT(left));
5042 assert (isAOP_REGlike(right));
5043 // swap left and right
5044 // left < right <==> right > left <==> (right >= left + 1)
5045 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5047 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5048 // MAXVALUE < right? always false
5049 if (performedLt) emitCLRC; else emitSETC;
5050 goto correct_result_in_carry;
5053 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5054 // that's why we handled it above.
5061 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5062 } else if (isAOP_LIT(right)) {
5063 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5066 assert (isAOP_REGlike(left)); // left must be register or the like
5067 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5069 /*************************************************
5070 * special cases go here *
5071 *************************************************/
5073 if (isAOP_LIT(right)) {
5075 // unsigned comparison to a literal
5076 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5078 // unsigned left < 0? always false
5079 if (performedLt) emitCLRC; else emitSETC;
5080 goto correct_result_in_carry;
5083 // signed comparison to a literal
5084 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5085 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5086 // signed left < 0x80000000? always false
5087 if (performedLt) emitCLRC; else emitSETC;
5088 goto correct_result_in_carry;
5089 } else if (lit == 0) {
5090 // compare left < 0; set CARRY if SIGNBIT(left) is set
5091 if (performedLt) emitSETC; else emitCLRC;
5092 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5093 if (performedLt) emitCLRC; else emitSETC;
5094 goto correct_result_in_carry;
5097 } // right is literal
5099 /*************************************************
5100 * perform a general case comparison *
5101 * make sure we get CARRY==1 <==> left >= right *
5102 *************************************************/
5103 // compare most significant bytes
5104 //DEBUGpc ("comparing bytes at offset %d", size);
5106 // unsigned comparison
5107 mov2w_regOrLit (AOP(right), lit, size);
5108 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5110 // signed comparison
5111 // (add 2^n to both operands then perform an unsigned comparison)
5112 if (isAOP_LIT(right)) {
5113 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5114 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5116 if (litbyte == 0x80) {
5117 // left >= 0x80 -- always true, but more bytes to come
5118 pic16_mov2w (AOP(left), size);
5119 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5122 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5123 pic16_mov2w (AOP(left), size);
5124 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5125 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5128 /* using PRODL as a temporary register here */
5129 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5130 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5131 pic16_mov2w (AOP(left), size);
5132 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5133 pic16_emitpcode (POC_MOVWF, pctemp);
5134 pic16_mov2w (AOP(right), size);
5135 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5136 pic16_emitpcode (POC_SUBFW, pctemp);
5137 //pic16_popReleaseTempReg(pctemp, 1);
5141 // compare remaining bytes (treat as unsigned case from above)
5142 templbl = newiTempLabel ( NULL );
5145 //DEBUGpc ("comparing bytes at offset %d", offs);
5146 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5147 mov2w_regOrLit (AOP(right), lit, offs);
5148 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5150 pic16_emitpLabel (templbl->key);
5151 goto result_in_carry;
5155 /****************************************************
5156 * now CARRY contains the result of the comparison: *
5157 * SUBWF sets CARRY iff *
5158 * F-W >= 0 <==> F >= W <==> !(F < W) *
5159 * (F=left, W=right) *
5160 ****************************************************/
5163 if (result && AOP_TYPE(result) != AOP_CRY) {
5164 // value will be stored
5167 // value wil only be used in the following genSkipc()
5168 rIfx.condition ^= 1;
5172 correct_result_in_carry:
5174 // assign result to variable (if neccessary)
5175 if (result && AOP_TYPE(result) != AOP_CRY) {
5176 //DEBUGpc ("assign result");
5177 size = AOP_SIZE(result);
5179 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5181 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5184 // perform conditional jump
5186 //DEBUGpc ("generate control flow");
5195 static void genCmp (operand *left,operand *right,
5196 operand *result, iCode *ifx, int sign)
5198 int size; //, offset = 0 ;
5199 unsigned long lit = 0L,i = 0;
5200 resolvedIfx rFalseIfx;
5201 // resolvedIfx rTrueIfx;
5203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5206 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5207 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5213 resolveIfx(&rFalseIfx,ifx);
5214 truelbl = newiTempLabel(NULL);
5215 size = max(AOP_SIZE(left),AOP_SIZE(right));
5217 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5221 /* if literal is on the right then swap with left */
5222 if ((AOP_TYPE(right) == AOP_LIT)) {
5223 operand *tmp = right ;
5224 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5225 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5228 lit = (lit - 1) & mask;
5231 rFalseIfx.condition ^= 1;
5234 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5235 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5239 //if(IC_TRUE(ifx) == NULL)
5240 /* if left & right are bit variables */
5241 if (AOP_TYPE(left) == AOP_CRY &&
5242 AOP_TYPE(right) == AOP_CRY ) {
5243 assert (0 && "bit variables used in genCmp");
5244 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5245 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5247 /* subtract right from left if at the
5248 end the carry flag is set then we know that
5249 left is greater than right */
5251 symbol *lbl = newiTempLabel(NULL);
5254 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5255 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5259 if(AOP_TYPE(right) == AOP_LIT) {
5261 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5263 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5270 genSkipCond(&rFalseIfx,left,size-1,7);
5272 /* no need to compare to 0...*/
5273 /* NOTE: this is a de-generate compare that most certainly
5274 * creates some dead code. */
5275 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5277 if(ifx) ifx->generated = 1;
5284 //i = (lit >> (size*8)) & 0xff;
5285 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5287 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5289 i = ((0-lit) & 0xff);
5292 /* lit is 0x7f, all signed chars are less than
5293 * this except for 0x7f itself */
5294 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5295 genSkipz2(&rFalseIfx,0);
5297 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5298 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5299 genSkipc(&rFalseIfx);
5304 genSkipz2(&rFalseIfx,1);
5306 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5307 genSkipc(&rFalseIfx);
5311 if(ifx) ifx->generated = 1;
5315 /* chars are out of the way. now do ints and longs */
5318 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5325 genSkipCond(&rFalseIfx,left,size,7);
5326 if(ifx) ifx->generated = 1;
5331 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5333 //rFalseIfx.condition ^= 1;
5334 //genSkipCond(&rFalseIfx,left,size,7);
5335 //rFalseIfx.condition ^= 1;
5337 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5338 if(rFalseIfx.condition)
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5341 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5343 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5344 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5345 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5348 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5350 if(rFalseIfx.condition) {
5352 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5358 genSkipc(&rFalseIfx);
5359 pic16_emitpLabel(truelbl->key);
5360 if(ifx) ifx->generated = 1;
5367 if( (lit & 0xff) == 0) {
5368 /* lower byte is zero */
5369 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5370 i = ((lit >> 8) & 0xff) ^0x80;
5371 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5372 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5373 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5374 genSkipc(&rFalseIfx);
5377 if(ifx) ifx->generated = 1;
5382 /* Special cases for signed longs */
5383 if( (lit & 0xffffff) == 0) {
5384 /* lower byte is zero */
5385 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5386 i = ((lit >> 8*3) & 0xff) ^0x80;
5387 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5388 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5389 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5390 genSkipc(&rFalseIfx);
5393 if(ifx) ifx->generated = 1;
5401 if(lit & (0x80 << (size*8))) {
5402 /* lit is negative */
5403 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5405 //genSkipCond(&rFalseIfx,left,size,7);
5407 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5409 if(rFalseIfx.condition)
5410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5412 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5416 /* lit is positive */
5417 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5418 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5419 if(rFalseIfx.condition)
5420 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5422 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5427 This works, but is only good for ints.
5428 It also requires a "known zero" register.
5429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5430 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5431 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5432 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5433 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5434 genSkipc(&rFalseIfx);
5436 pic16_emitpLabel(truelbl->key);
5437 if(ifx) ifx->generated = 1;
5441 /* There are no more special cases, so perform a general compare */
5443 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5444 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5448 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5450 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5452 //rFalseIfx.condition ^= 1;
5453 genSkipc(&rFalseIfx);
5455 pic16_emitpLabel(truelbl->key);
5457 if(ifx) ifx->generated = 1;
5464 /* sign is out of the way. So now do an unsigned compare */
5465 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5468 /* General case - compare to an unsigned literal on the right.*/
5470 i = (lit >> (size*8)) & 0xff;
5471 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5472 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5474 i = (lit >> (size*8)) & 0xff;
5477 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5479 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5481 /* this byte of the lit is zero,
5482 *if it's not the last then OR in the variable */
5484 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5489 pic16_emitpLabel(lbl->key);
5490 // pic16_emitpLabel(truelbl->key);
5491 //if(emitFinalCheck)
5492 genSkipc(&rFalseIfx);
5494 pic16_emitpLabel(truelbl->key);
5496 if(ifx) ifx->generated = 1;
5503 if(AOP_TYPE(left) == AOP_LIT) {
5504 //symbol *lbl = newiTempLabel(NULL);
5506 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5509 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5512 if((lit == 0) && (sign == 0)){
5515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5517 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5519 genSkipz2(&rFalseIfx,0);
5520 if(ifx) ifx->generated = 1;
5527 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5528 /* degenerate compare can never be true */
5529 if(rFalseIfx.condition == 0)
5530 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5532 if(ifx) ifx->generated = 1;
5537 /* signed comparisons to a literal byte */
5539 int lp1 = (lit+1) & 0xff;
5541 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5544 rFalseIfx.condition ^= 1;
5545 genSkipCond(&rFalseIfx,right,0,7);
5548 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5549 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5550 genSkipz2(&rFalseIfx,1);
5553 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5554 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5555 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5556 rFalseIfx.condition ^= 1;
5557 genSkipc(&rFalseIfx);
5561 /* unsigned comparisons to a literal byte */
5563 switch(lit & 0xff ) {
5565 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5566 genSkipz2(&rFalseIfx,0);
5569 rFalseIfx.condition ^= 1;
5570 genSkipCond(&rFalseIfx,right,0,7);
5574 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5575 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5576 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5577 rFalseIfx.condition ^= 1;
5578 if (AOP_TYPE(result) == AOP_CRY)
5579 genSkipc(&rFalseIfx);
5581 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5582 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5588 if(ifx) ifx->generated = 1;
5589 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5595 /* Size is greater than 1 */
5603 /* this means lit = 0xffffffff, or -1 */
5606 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5607 rFalseIfx.condition ^= 1;
5608 genSkipCond(&rFalseIfx,right,size,7);
5609 if(ifx) ifx->generated = 1;
5611 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5620 if(rFalseIfx.condition) {
5621 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5622 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5625 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5627 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5631 if(rFalseIfx.condition) {
5632 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5633 pic16_emitpLabel(truelbl->key);
5635 rFalseIfx.condition ^= 1;
5636 genSkipCond(&rFalseIfx,right,s,7);
5639 if(ifx) ifx->generated = 1;
5641 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5647 if((size == 1) && (0 == (lp1&0xff))) {
5648 /* lower byte of signed word is zero */
5649 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5650 i = ((lp1 >> 8) & 0xff) ^0x80;
5651 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5652 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5653 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5655 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5657 if(ifx) ifx->generated = 1;
5660 rFalseIfx.condition ^= 1;
5661 genSkipc(&rFalseIfx);
5662 if(ifx) ifx->generated = 1;
5668 if(lit & (0x80 << (size*8))) {
5669 /* Lit is less than zero */
5670 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5671 //rFalseIfx.condition ^= 1;
5672 //genSkipCond(&rFalseIfx,left,size,7);
5673 //rFalseIfx.condition ^= 1;
5674 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5675 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5677 if(rFalseIfx.condition)
5678 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5680 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5684 /* Lit is greater than or equal to zero */
5685 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5686 //rFalseIfx.condition ^= 1;
5687 //genSkipCond(&rFalseIfx,right,size,7);
5688 //rFalseIfx.condition ^= 1;
5690 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5691 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5693 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5694 if(rFalseIfx.condition)
5695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5697 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5702 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5708 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5710 rFalseIfx.condition ^= 1;
5711 //rFalseIfx.condition = 1;
5712 genSkipc(&rFalseIfx);
5714 pic16_emitpLabel(truelbl->key);
5716 if(ifx) ifx->generated = 1;
5719 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5726 /* compare word or long to an unsigned literal on the right.*/
5731 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5734 break; /* handled above */
5737 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5739 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5740 genSkipz2(&rFalseIfx,0);
5744 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5746 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5749 if(rFalseIfx.condition)
5750 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5752 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5755 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5756 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5758 rFalseIfx.condition ^= 1;
5759 genSkipc(&rFalseIfx);
5762 pic16_emitpLabel(truelbl->key);
5764 if(ifx) ifx->generated = 1;
5766 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5774 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5775 i = (lit >> (size*8)) & 0xff;
5777 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5778 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5781 i = (lit >> (size*8)) & 0xff;
5784 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5786 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5788 /* this byte of the lit is zero,
5789 * if it's not the last then OR in the variable */
5791 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5796 pic16_emitpLabel(lbl->key);
5798 rFalseIfx.condition ^= 1;
5800 genSkipc(&rFalseIfx);
5804 pic16_emitpLabel(truelbl->key);
5805 if(ifx) ifx->generated = 1;
5807 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5813 /* Compare two variables */
5815 DEBUGpic16_emitcode(";sign","%d",sign);
5819 /* Sigh. thus sucks... */
5823 pctemp = pic16_popGetTempReg(1);
5824 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5825 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5827 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5829 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830 pic16_popReleaseTempReg(pctemp, 1);
5832 /* Signed char comparison */
5833 /* Special thanks to Nikolai Golovchenko for this snippet */
5834 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5835 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5836 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5837 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5838 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5839 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5842 genSkipc(&rFalseIfx);
5844 if(ifx) ifx->generated = 1;
5846 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5854 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5855 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5859 /* The rest of the bytes of a multi-byte compare */
5863 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5866 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5867 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5872 pic16_emitpLabel(lbl->key);
5874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5875 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5876 (AOP_TYPE(result) == AOP_REG)) {
5877 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5878 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5880 genSkipc(&rFalseIfx);
5882 //genSkipc(&rFalseIfx);
5883 if(ifx) ifx->generated = 1;
5886 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5894 if ((AOP_TYPE(result) != AOP_CRY)
5895 && AOP_SIZE(result)) {
5896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5898 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5900 pic16_outBitC(result);
5902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5903 /* if the result is used in the next
5904 ifx conditional branch then generate
5905 code a little differently */
5907 genIfxJump (ifx,"c");
5909 pic16_outBitC(result);
5910 /* leave the result in acc */
5915 #elif 0 /* VR version of genCmp() */ /* } else { */
5917 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5918 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5919 operand *result, int offset, int invert_op)
5923 /* check condition, > or < ?? */
5924 if(rIfx->condition != 0)invert_op ^= 1;
5926 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5928 if(!ifx)invert_op ^= 1;
5930 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5931 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5934 if(!invert_op)return POC_CPFSGT;
5935 else return POC_CPFSLT;
5938 static int compareAopfirstpass=1;
5940 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5941 operand *oper, int offset, operand *result,
5942 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5948 /* invert if there is a result to be loaded, in order to fit,
5949 * SETC/CLRC sequence */
5950 if(AOP_SIZE(result))invert_op ^= 1;
5952 // if(sign && !offset)invert_op ^= 1;
5954 // if(sign)invert_op ^= 1;
5956 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5958 if(AOP_SIZE(result) && compareAopfirstpass) {
5961 pic16_emitpcode(POC_SETF, pcop2);
5966 pic16_emitpcode(POC_CLRF, pcop2);
5972 compareAopfirstpass = 0;
5974 /* there is a bug when comparing operands with size > 1,
5975 * because higher bytes can be equal and test should be performed
5976 * to the next lower byte, current algorithm, considers operands
5977 * inequal in these cases! -- VR 20041107 */
5981 pic16_emitpcode(op, pcop);
5983 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5986 if((!sign || !offset) && AOP_SIZE(result)) {
5989 pic16_emitpcode(POC_CLRF, pcop2);
5994 pic16_emitpcode(POC_SETF, pcop2);
5999 /* don't emit final branch (offset == 0) */
6003 pic16_emitpcode(POC_RRCF, pcop2);
6005 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6008 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6009 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6010 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6012 truelbl = newiTempLabel( NULL );
6013 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6014 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6015 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6017 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6018 pic16_emitpLabel(truelbl->key);
6020 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6025 static void genCmp (operand *left, operand *right,
6026 operand *result, iCode *ifx, int sign)
6030 resolvedIfx rFalseIfx;
6031 symbol *falselbl, *tlbl;
6035 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6037 resolveIfx(&rFalseIfx, ifx);
6038 size = max(AOP_SIZE(left), AOP_SIZE(right));
6040 /* if left & right are bit variables */
6041 if(AOP_TYPE(left) == AOP_CRY
6042 && AOP_TYPE(right) == AOP_CRY ) {
6044 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6045 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6047 werror(W_POSSBUG2, __FILE__, __LINE__);
6051 /* if literal is on the right then swap with left */
6052 if((AOP_TYPE(right) == AOP_LIT)) {
6053 operand *tmp = right ;
6054 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6056 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6058 // lit = (lit - 1) & mask;
6061 rFalseIfx.condition ^= 1; /* reverse compare */
6063 if ((AOP_TYPE(left) == AOP_LIT)) {
6064 /* float compares are handled by support functions */
6065 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6068 /* actual comparing algorithm */
6069 // size = AOP_SIZE( right );
6071 falselbl = newiTempLabel( NULL );
6072 if(AOP_TYPE(left) == AOP_LIT) {
6073 /* compare to literal */
6074 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6077 pCodeOp *pct, *pct2;
6080 /* signed compare */
6081 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6083 /* using PRODL:PRODH as a temporary register here */
6084 pct = pic16_popCopyReg(&pic16_pc_prodl);
6085 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6086 tlbl = newiTempLabel( NULL );
6088 /* first compare signs:
6089 * a. if both are positive, compare just like unsigned
6090 * b. if both are negative, invert cmpop, compare just like unsigned
6091 * c. if different signs, determine the result directly */
6097 tlbl1 = newiTempLabel( NULL );
6098 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6102 /* literal is zero or positive:
6103 * a. if carry is zero, too, continue compare,
6104 * b. if carry is set, then continue depending on cmpop ^ condition:
6105 * 1. '<' return false (literal < variable),
6106 * 2. '>' return true (literal > variable) */
6107 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6108 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6111 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6112 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6116 /* literal is negative:
6117 * a. if carry is set, too, continue compare,
6118 * b. if carry is zero, then continue depending on cmpop ^ condition:
6119 * 1. '<' return true (literal < variable),
6120 * 2. '>' return false (literal > variable) */
6121 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6122 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6124 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6125 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6130 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6132 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6133 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6138 pic16_emitpLabel( tlbl1->key );
6141 compareAopfirstpass=1;
6142 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6143 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6144 // pic16_emitpcode(POC_MOVWF, pct);
6146 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6147 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6148 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6149 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6153 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6154 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6155 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6156 // pic16_emitpcode(POC_MOVWF, pct);
6158 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6159 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6160 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6161 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6162 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6165 if(ifx)ifx->generated = 1;
6167 if(AOP_SIZE(result)) {
6168 pic16_emitpLabel(tlbl->key);
6169 pic16_emitpLabel(falselbl->key);
6170 pic16_outBitOp( result, pct2 );
6172 pic16_emitpLabel(tlbl->key);
6176 /* unsigned compare */
6177 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6179 compareAopfirstpass=1;
6182 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6183 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6186 if(ifx)ifx->generated = 1;
6188 if(AOP_SIZE(result)) {
6189 pic16_emitpLabel(falselbl->key);
6190 pic16_outBitC( result );
6195 /* compare registers */
6196 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6200 pCodeOp *pct, *pct2;
6202 /* signed compare */
6203 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6205 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6206 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6207 tlbl = newiTempLabel( NULL );
6209 compareAopfirstpass=1;
6212 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6213 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6214 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6215 pic16_emitpcode(POC_MOVWF, pct);
6217 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6218 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6219 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6221 /* WREG already holds left + 0x80 */
6222 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6225 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6226 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6228 pic16_emitpcode(POC_MOVWF, pct);
6230 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6231 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6232 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6234 /* WREG already holds left + 0x80 */
6235 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6236 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6239 if(ifx)ifx->generated = 1;
6241 if(AOP_SIZE(result)) {
6242 pic16_emitpLabel(tlbl->key);
6243 pic16_emitpLabel(falselbl->key);
6244 pic16_outBitOp( result, pct2 );
6246 pic16_emitpLabel(tlbl->key);
6250 /* unsigned compare */
6251 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6253 compareAopfirstpass=1;
6256 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6257 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6261 if(ifx)ifx->generated = 1;
6262 if(AOP_SIZE(result)) {
6264 pic16_emitpLabel(falselbl->key);
6265 pic16_outBitC( result );
6276 /*-----------------------------------------------------------------*/
6277 /* genCmpGt :- greater than comparison */
6278 /*-----------------------------------------------------------------*/
6279 static void genCmpGt (iCode *ic, iCode *ifx)
6281 operand *left, *right, *result;
6282 sym_link *letype , *retype;
6288 right= IC_RIGHT(ic);
6289 result = IC_RESULT(ic);
6291 letype = getSpec(operandType(left));
6292 retype =getSpec(operandType(right));
6293 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6294 /* assign the amsops */
6295 pic16_aopOp (left,ic,FALSE);
6296 pic16_aopOp (right,ic,FALSE);
6297 pic16_aopOp (result,ic,TRUE);
6299 genCmp(right, left, result, ifx, sign);
6301 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6302 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6303 pic16_freeAsmop(result,NULL,ic,TRUE);
6306 /*-----------------------------------------------------------------*/
6307 /* genCmpLt - less than comparisons */
6308 /*-----------------------------------------------------------------*/
6309 static void genCmpLt (iCode *ic, iCode *ifx)
6311 operand *left, *right, *result;
6312 sym_link *letype , *retype;
6318 right= IC_RIGHT(ic);
6319 result = IC_RESULT(ic);
6321 letype = getSpec(operandType(left));
6322 retype =getSpec(operandType(right));
6323 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6325 /* assign the amsops */
6326 pic16_aopOp (left,ic,FALSE);
6327 pic16_aopOp (right,ic,FALSE);
6328 pic16_aopOp (result,ic,TRUE);
6330 genCmp(left, right, result, ifx, sign);
6332 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6333 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6334 pic16_freeAsmop(result,NULL,ic,TRUE);
6339 // FIXME reenable literal optimisation when the pic16 port is stable
6341 /*-----------------------------------------------------------------*/
6342 /* genc16bit2lit - compare a 16 bit value to a literal */
6343 /*-----------------------------------------------------------------*/
6344 static void genc16bit2lit(operand *op, int lit, int offset)
6348 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6349 if( (lit&0xff) == 0)
6354 switch( BYTEofLONG(lit,i)) {
6356 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6362 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6365 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6366 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6371 switch( BYTEofLONG(lit,i)) {
6373 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6377 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6381 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6384 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6386 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6395 /*-----------------------------------------------------------------*/
6396 /* gencjneshort - compare and jump if not equal */
6397 /*-----------------------------------------------------------------*/
6398 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6400 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6402 int res_offset = 0; /* the result may be a different size then left or right */
6403 int res_size = AOP_SIZE(result);
6405 symbol *lbl, *lbl_done;
6407 unsigned long lit = 0L;
6408 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6410 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6411 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6413 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6414 resolveIfx(&rIfx,ifx);
6415 lbl = newiTempLabel(NULL);
6416 lbl_done = newiTempLabel(NULL);
6419 /* if the left side is a literal or
6420 if the right is in a pointer register and left
6422 if ((AOP_TYPE(left) == AOP_LIT) ||
6423 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6428 if(AOP_TYPE(right) == AOP_LIT)
6429 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6431 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6432 preserve_result = 1;
6434 if(result && !preserve_result)
6437 for(i = 0; i < AOP_SIZE(result); i++)
6438 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6442 /* if the right side is a literal then anything goes */
6443 if (AOP_TYPE(right) == AOP_LIT &&
6444 AOP_TYPE(left) != AOP_DIR ) {
6447 genc16bit2lit(left, lit, 0);
6449 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6452 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6455 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6456 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6458 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6462 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6464 if(res_offset < res_size-1)
6472 /* if the right side is in a register or in direct space or
6473 if the left is a pointer register & right is not */
6474 else if (AOP_TYPE(right) == AOP_REG ||
6475 AOP_TYPE(right) == AOP_DIR ||
6476 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6477 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6478 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6479 int lbl_key = lbl->key;
6482 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6483 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6485 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6486 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6487 __FUNCTION__,__LINE__);
6491 /* switch(size) { */
6493 /* genc16bit2lit(left, lit, 0); */
6495 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6500 if((AOP_TYPE(left) == AOP_DIR) &&
6501 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6503 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6506 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6508 switch (lit & 0xff) {
6510 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6514 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6515 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6519 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6520 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6521 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6526 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6527 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6532 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6535 if(AOP_TYPE(result) == AOP_CRY) {
6536 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6541 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6543 /* fix me. probably need to check result size too */
6544 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6549 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6550 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6557 if(res_offset < res_size-1)
6562 } else if(AOP_TYPE(right) == AOP_REG &&
6563 AOP_TYPE(left) != AOP_DIR){
6566 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6567 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6568 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6573 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6575 if(res_offset < res_size-1)
6580 /* right is a pointer reg need both a & b */
6582 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6584 pic16_emitcode("mov","b,%s",l);
6585 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6586 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6591 if(result && preserve_result)
6594 for(i = 0; i < AOP_SIZE(result); i++)
6595 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6598 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6600 if(result && preserve_result)
6601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6604 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6606 pic16_emitpLabel(lbl->key);
6608 if(result && preserve_result)
6611 for(i = 0; i < AOP_SIZE(result); i++)
6612 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6614 pic16_emitpLabel(lbl_done->key);
6617 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6625 /*-----------------------------------------------------------------*/
6626 /* gencjne - compare and jump if not equal */
6627 /*-----------------------------------------------------------------*/
6628 static void gencjne(operand *left, operand *right, iCode *ifx)
6630 symbol *tlbl = newiTempLabel(NULL);
6632 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6633 gencjneshort(left, right, lbl);
6635 pic16_emitcode("mov","a,%s",one);
6636 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6637 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6638 pic16_emitcode("clr","a");
6639 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6641 pic16_emitpLabel(lbl->key);
6642 pic16_emitpLabel(tlbl->key);
6648 /*-----------------------------------------------------------------*/
6649 /* is_LitOp - check if operand has to be treated as literal */
6650 /*-----------------------------------------------------------------*/
6651 static bool is_LitOp(operand *op)
6653 return ((AOP_TYPE(op) == AOP_LIT)
6654 || ( (AOP_TYPE(op) == AOP_PCODE)
6655 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6656 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6659 /*-----------------------------------------------------------------*/
6660 /* is_LitAOp - check if operand has to be treated as literal */
6661 /*-----------------------------------------------------------------*/
6662 static bool is_LitAOp(asmop *aop)
6664 return ((aop->type == AOP_LIT)
6665 || ( (aop->type == AOP_PCODE)
6666 && ( (aop->aopu.pcop->type == PO_LITERAL)
6667 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6672 /*-----------------------------------------------------------------*/
6673 /* genCmpEq - generates code for equal to */
6674 /*-----------------------------------------------------------------*/
6675 static void genCmpEq (iCode *ic, iCode *ifx)
6677 operand *left, *right, *result;
6678 symbol *falselbl = newiTempLabel(NULL);
6679 symbol *donelbl = newiTempLabel(NULL);
6681 int preserve_result = 0;
6682 int generate_result = 0;
6684 unsigned long lit = -1;
6688 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6689 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6690 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6692 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6694 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6696 werror(W_POSSBUG2, __FILE__, __LINE__);
6697 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6698 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6702 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6704 operand *tmp = right ;
6709 if (AOP_TYPE(right) == AOP_LIT) {
6710 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6713 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6714 preserve_result = 1;
6716 if(result && AOP_SIZE(result))
6717 generate_result = 1;
6719 if(generate_result && !preserve_result)
6721 for(i = 0; i < AOP_SIZE(result); i++)
6722 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6725 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6726 for(i=0; i < AOP_SIZE(left); i++)
6728 if(AOP_TYPE(left) != AOP_ACC)
6731 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6733 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6735 if(is_LitOp(right)) {
6736 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6737 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6740 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6742 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6747 if(generate_result && preserve_result)
6749 for(i = 0; i < AOP_SIZE(result); i++)
6750 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6754 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6756 if(generate_result && preserve_result)
6757 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6759 if(ifx && IC_TRUE(ifx))
6760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6762 if(ifx && IC_FALSE(ifx))
6763 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6765 pic16_emitpLabel(falselbl->key);
6769 if(ifx && IC_FALSE(ifx))
6770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6772 if(generate_result && preserve_result)
6774 for(i = 0; i < AOP_SIZE(result); i++)
6775 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6778 pic16_emitpLabel(donelbl->key);
6784 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6785 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6786 pic16_freeAsmop(result,NULL,ic,TRUE);
6792 // old version kept for reference
6794 /*-----------------------------------------------------------------*/
6795 /* genCmpEq - generates code for equal to */
6796 /*-----------------------------------------------------------------*/
6797 static void genCmpEq (iCode *ic, iCode *ifx)
6799 operand *left, *right, *result;
6800 unsigned long lit = 0L;
6802 symbol *falselbl = newiTempLabel(NULL);
6805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6808 DEBUGpic16_emitcode ("; ifx is non-null","");
6810 DEBUGpic16_emitcode ("; ifx is null","");
6812 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6813 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6814 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6816 size = max(AOP_SIZE(left),AOP_SIZE(right));
6818 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6820 /* if literal, literal on the right or
6821 if the right is in a pointer register and left
6823 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6824 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6825 operand *tmp = right ;
6831 if(ifx && !AOP_SIZE(result)){
6833 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6834 /* if they are both bit variables */
6835 if (AOP_TYPE(left) == AOP_CRY &&
6836 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6837 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6838 if(AOP_TYPE(right) == AOP_LIT){
6839 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6841 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842 pic16_emitcode("cpl","c");
6843 } else if(lit == 1L) {
6844 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6846 pic16_emitcode("clr","c");
6848 /* AOP_TYPE(right) == AOP_CRY */
6850 symbol *lbl = newiTempLabel(NULL);
6851 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6852 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6853 pic16_emitcode("cpl","c");
6854 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6856 /* if true label then we jump if condition
6858 tlbl = newiTempLabel(NULL);
6859 if ( IC_TRUE(ifx) ) {
6860 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6861 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6863 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6864 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6866 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6869 /* left and right are both bit variables, result is carry */
6872 resolveIfx(&rIfx,ifx);
6874 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6875 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6876 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6877 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6882 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6884 /* They're not both bit variables. Is the right a literal? */
6885 if(AOP_TYPE(right) == AOP_LIT) {
6886 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6891 switch(lit & 0xff) {
6893 if ( IC_TRUE(ifx) ) {
6894 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6896 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6898 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6903 if ( IC_TRUE(ifx) ) {
6904 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6906 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6908 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6913 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6915 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6920 /* end of size == 1 */
6924 genc16bit2lit(left,lit,offset);
6927 /* end of size == 2 */
6932 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6933 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6934 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6935 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6938 /* search for patterns that can be optimized */
6940 genc16bit2lit(left,lit,0);
6944 emitSKPZ; // if hi word unequal
6946 emitSKPNZ; // if hi word equal
6948 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6949 genc16bit2lit(left,lit,2);
6952 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6953 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6957 pic16_emitpLabel(falselbl->key);
6966 } else if(AOP_TYPE(right) == AOP_CRY ) {
6967 /* we know the left is not a bit, but that the right is */
6968 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6969 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6970 pic16_popGet(AOP(right),offset));
6971 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6973 /* if the two are equal, then W will be 0 and the Z bit is set
6974 * we could test Z now, or go ahead and check the high order bytes if
6975 * the variable we're comparing is larger than a byte. */
6978 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6980 if ( IC_TRUE(ifx) ) {
6982 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6983 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6986 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6987 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6991 /* They're both variables that are larger than bits */
6994 tlbl = newiTempLabel(NULL);
6997 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6998 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7000 if ( IC_TRUE(ifx) ) {
7004 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7006 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7007 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7011 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7015 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7020 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7022 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7023 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7027 if(s>1 && IC_TRUE(ifx)) {
7028 pic16_emitpLabel(tlbl->key);
7029 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7033 /* mark the icode as generated */
7038 /* if they are both bit variables */
7039 if (AOP_TYPE(left) == AOP_CRY &&
7040 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7041 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7042 if(AOP_TYPE(right) == AOP_LIT){
7043 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7045 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046 pic16_emitcode("cpl","c");
7047 } else if(lit == 1L) {
7048 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7050 pic16_emitcode("clr","c");
7052 /* AOP_TYPE(right) == AOP_CRY */
7054 symbol *lbl = newiTempLabel(NULL);
7055 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7056 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7057 pic16_emitcode("cpl","c");
7058 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7061 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7062 pic16_outBitC(result);
7066 genIfxJump (ifx,"c");
7069 /* if the result is used in an arithmetic operation
7070 then put the result in place */
7071 pic16_outBitC(result);
7074 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7075 gencjne(left,right,result,ifx);
7078 gencjne(left,right,newiTempLabel(NULL));
7080 if(IC_TRUE(ifx)->key)
7081 gencjne(left,right,IC_TRUE(ifx)->key);
7083 gencjne(left,right,IC_FALSE(ifx)->key);
7087 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7088 pic16_aopPut(AOP(result),"a",0);
7093 genIfxJump (ifx,"a");
7097 /* if the result is used in an arithmetic operation
7098 then put the result in place */
7100 if (AOP_TYPE(result) != AOP_CRY)
7101 pic16_outAcc(result);
7103 /* leave the result in acc */
7107 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7108 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7109 pic16_freeAsmop(result,NULL,ic,TRUE);
7113 /*-----------------------------------------------------------------*/
7114 /* ifxForOp - returns the icode containing the ifx for operand */
7115 /*-----------------------------------------------------------------*/
7116 static iCode *ifxForOp ( operand *op, iCode *ic )
7120 /* if true symbol then needs to be assigned */
7121 if (IS_TRUE_SYMOP(op))
7124 /* if this has register type condition and
7125 the next instruction is ifx with the same operand
7126 and live to of the operand is upto the ifx only then */
7128 && ic->next->op == IFX
7129 && IC_COND(ic->next)->key == op->key
7130 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7132 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7138 ic->next->op == IFX &&
7139 IC_COND(ic->next)->key == op->key) {
7140 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7145 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7147 ic->next->op == IFX)
7148 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7151 ic->next->op == IFX &&
7152 IC_COND(ic->next)->key == op->key) {
7153 DEBUGpic16_emitcode ("; "," key is okay");
7154 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7155 OP_SYMBOL(op)->liveTo,
7160 /* the code below is completely untested
7161 * it just allows ulong2fs.c compile -- VR */
7164 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7165 __FILE__, __FUNCTION__, __LINE__);
7167 /* if this has register type condition and
7168 the next instruction is ifx with the same operand
7169 and live to of the operand is upto the ifx only then */
7171 ic->next->op == IFX &&
7172 IC_COND(ic->next)->key == op->key &&
7173 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7177 ic->next->op == IFX &&
7178 IC_COND(ic->next)->key == op->key) {
7179 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7183 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7184 __FILE__, __FUNCTION__, __LINE__);
7186 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7191 /*-----------------------------------------------------------------*/
7192 /* genAndOp - for && operation */
7193 /*-----------------------------------------------------------------*/
7194 static void genAndOp (iCode *ic)
7196 operand *left,*right, *result;
7201 /* note here that && operations that are in an
7202 if statement are taken away by backPatchLabels
7203 only those used in arthmetic operations remain */
7204 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7205 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7206 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7208 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7210 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7211 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7212 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7214 /* if both are bit variables */
7215 /* if (AOP_TYPE(left) == AOP_CRY && */
7216 /* AOP_TYPE(right) == AOP_CRY ) { */
7217 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7218 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7219 /* pic16_outBitC(result); */
7221 /* tlbl = newiTempLabel(NULL); */
7222 /* pic16_toBoolean(left); */
7223 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7224 /* pic16_toBoolean(right); */
7225 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7226 /* pic16_outBitAcc(result); */
7229 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7230 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7231 pic16_freeAsmop(result,NULL,ic,TRUE);
7235 /*-----------------------------------------------------------------*/
7236 /* genOrOp - for || operation */
7237 /*-----------------------------------------------------------------*/
7240 modified this code, but it doesn't appear to ever get called
7243 static void genOrOp (iCode *ic)
7245 operand *left,*right, *result;
7250 /* note here that || operations that are in an
7251 if statement are taken away by backPatchLabels
7252 only those used in arthmetic operations remain */
7253 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7254 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7255 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7257 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7259 /* if both are bit variables */
7260 if (AOP_TYPE(left) == AOP_CRY &&
7261 AOP_TYPE(right) == AOP_CRY ) {
7262 pic16_emitcode("clrc","");
7263 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7264 AOP(left)->aopu.aop_dir,
7265 AOP(left)->aopu.aop_dir);
7266 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7267 AOP(right)->aopu.aop_dir,
7268 AOP(right)->aopu.aop_dir);
7269 pic16_emitcode("setc","");
7272 tlbl = newiTempLabel(NULL);
7273 pic16_toBoolean(left);
7275 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7276 pic16_toBoolean(right);
7277 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7279 pic16_outBitAcc(result);
7282 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7283 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7284 pic16_freeAsmop(result,NULL,ic,TRUE);
7287 /*-----------------------------------------------------------------*/
7288 /* isLiteralBit - test if lit == 2^n */
7289 /*-----------------------------------------------------------------*/
7290 static int isLiteralBit(unsigned long lit)
7292 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7293 0x100L,0x200L,0x400L,0x800L,
7294 0x1000L,0x2000L,0x4000L,0x8000L,
7295 0x10000L,0x20000L,0x40000L,0x80000L,
7296 0x100000L,0x200000L,0x400000L,0x800000L,
7297 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7298 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7302 for(idx = 0; idx < 32; idx++)
7308 /*-----------------------------------------------------------------*/
7309 /* continueIfTrue - */
7310 /*-----------------------------------------------------------------*/
7311 static void continueIfTrue (iCode *ic)
7315 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7319 /*-----------------------------------------------------------------*/
7321 /*-----------------------------------------------------------------*/
7322 static void jumpIfTrue (iCode *ic)
7326 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7330 /*-----------------------------------------------------------------*/
7331 /* jmpTrueOrFalse - */
7332 /*-----------------------------------------------------------------*/
7333 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7335 // ugly but optimized by peephole
7338 symbol *nlbl = newiTempLabel(NULL);
7339 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7340 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7341 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7342 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7344 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7345 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7350 /*-----------------------------------------------------------------*/
7351 /* genAnd - code for and */
7352 /*-----------------------------------------------------------------*/
7353 static void genAnd (iCode *ic, iCode *ifx)
7355 operand *left, *right, *result;
7357 unsigned long lit = 0L;
7363 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7364 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7365 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7367 resolveIfx(&rIfx,ifx);
7369 /* if left is a literal & right is not then exchange them */
7370 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7371 AOP_NEEDSACC(left)) {
7372 operand *tmp = right ;
7377 /* if result = right then exchange them */
7378 if(pic16_sameRegs(AOP(result),AOP(right))){
7379 operand *tmp = right ;
7384 /* if right is bit then exchange them */
7385 if (AOP_TYPE(right) == AOP_CRY &&
7386 AOP_TYPE(left) != AOP_CRY){
7387 operand *tmp = right ;
7391 if(AOP_TYPE(right) == AOP_LIT)
7392 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7394 size = AOP_SIZE(result);
7396 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7399 // result = bit & yy;
7400 if (AOP_TYPE(left) == AOP_CRY){
7401 // c = bit & literal;
7402 if(AOP_TYPE(right) == AOP_LIT){
7404 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7407 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7410 if(size && (AOP_TYPE(result) == AOP_CRY)){
7411 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7414 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7418 pic16_emitcode("clr","c");
7421 if (AOP_TYPE(right) == AOP_CRY){
7423 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7424 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7429 pic16_emitcode("rrc","a");
7430 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7436 pic16_outBitC(result);
7438 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7439 genIfxJump(ifx, "c");
7443 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7444 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7445 if((AOP_TYPE(right) == AOP_LIT) &&
7446 (AOP_TYPE(result) == AOP_CRY) &&
7447 (AOP_TYPE(left) != AOP_CRY)){
7448 int posbit = isLiteralBit(lit);
7452 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7455 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7461 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7462 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7464 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7465 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7468 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7469 size = AOP_SIZE(left);
7472 int bp = posbit, ofs=0;
7479 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7480 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7484 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7485 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7487 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7494 symbol *tlbl = newiTempLabel(NULL);
7495 int sizel = AOP_SIZE(left);
7501 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7503 /* patch provided by Aaron Colwell */
7504 if((posbit = isLiteralBit(bytelit)) != 0) {
7505 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7506 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7507 (posbit-1),0, PO_GPR_REGISTER));
7509 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7510 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7512 if (bytelit == 0xff) {
7513 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7514 * a peephole could optimize it out -- VR */
7515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7521 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7522 pic16_popGetLabel(tlbl->key));
7526 /* old code, left here for reference -- VR 09/2004 */
7527 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7529 if((posbit = isLiteralBit(bytelit)) != 0)
7530 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7532 if(bytelit != 0x0FFL)
7533 pic16_emitcode("anl","a,%s",
7534 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7535 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7541 // bit = left & literal
7544 pic16_emitpLabel(tlbl->key);
7546 // if(left & literal)
7549 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7552 pic16_emitpLabel(tlbl->key);
7557 pic16_outBitC(result);
7561 /* if left is same as result */
7562 if(pic16_sameRegs(AOP(result),AOP(left))){
7564 for(;size--; offset++,lit>>=8) {
7565 if(AOP_TYPE(right) == AOP_LIT){
7566 switch(lit & 0xff) {
7568 /* and'ing with 0 has clears the result */
7569 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7570 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7573 /* and'ing with 0xff is a nop when the result and left are the same */
7578 int p = pic16_my_powof2( (~lit) & 0xff );
7580 /* only one bit is set in the literal, so use a bcf instruction */
7581 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7582 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7585 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7586 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7587 if(know_W != (lit&0xff))
7588 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7590 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7595 if (AOP_TYPE(left) == AOP_ACC) {
7596 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7598 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7599 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7606 // left & result in different registers
7607 if(AOP_TYPE(result) == AOP_CRY){
7609 // if(size), result in bit
7610 // if(!size && ifx), conditional oper: if(left & right)
7611 symbol *tlbl = newiTempLabel(NULL);
7612 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7614 pic16_emitcode("setb","c");
7616 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7617 pic16_emitcode("anl","a,%s",
7618 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7619 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7624 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7625 pic16_outBitC(result);
7627 jmpTrueOrFalse(ifx, tlbl);
7629 for(;(size--);offset++) {
7631 // result = left & right
7632 if(AOP_TYPE(right) == AOP_LIT){
7633 int t = (lit >> (offset*8)) & 0x0FFL;
7636 pic16_emitcode("clrf","%s",
7637 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7638 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7641 pic16_emitcode("movf","%s,w",
7642 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7643 pic16_emitcode("movwf","%s",
7644 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7645 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7646 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7649 pic16_emitcode("movlw","0x%x",t);
7650 pic16_emitcode("andwf","%s,w",
7651 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7652 pic16_emitcode("movwf","%s",
7653 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7655 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7656 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7657 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7662 if (AOP_TYPE(left) == AOP_ACC) {
7663 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7664 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7666 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7667 pic16_emitcode("andwf","%s,w",
7668 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7669 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7670 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7672 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7673 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7679 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7681 pic16_freeAsmop(result,NULL,ic,TRUE);
7684 /*-----------------------------------------------------------------*/
7685 /* genOr - code for or */
7686 /*-----------------------------------------------------------------*/
7687 static void genOr (iCode *ic, iCode *ifx)
7689 operand *left, *right, *result;
7691 unsigned long lit = 0L;
7693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7695 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7696 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7697 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7699 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7701 /* if left is a literal & right is not then exchange them */
7702 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7703 AOP_NEEDSACC(left)) {
7704 operand *tmp = right ;
7709 /* if result = right then exchange them */
7710 if(pic16_sameRegs(AOP(result),AOP(right))){
7711 operand *tmp = right ;
7716 /* if right is bit then exchange them */
7717 if (AOP_TYPE(right) == AOP_CRY &&
7718 AOP_TYPE(left) != AOP_CRY){
7719 operand *tmp = right ;
7724 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7726 if(AOP_TYPE(right) == AOP_LIT)
7727 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7729 size = AOP_SIZE(result);
7733 if (AOP_TYPE(left) == AOP_CRY){
7734 if(AOP_TYPE(right) == AOP_LIT){
7735 // c = bit & literal;
7737 // lit != 0 => result = 1
7738 if(AOP_TYPE(result) == AOP_CRY){
7740 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7741 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7742 // AOP(result)->aopu.aop_dir,
7743 // AOP(result)->aopu.aop_dir);
7745 continueIfTrue(ifx);
7749 // lit == 0 => result = left
7750 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7752 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7755 if (AOP_TYPE(right) == AOP_CRY){
7756 if(pic16_sameRegs(AOP(result),AOP(left))){
7758 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7759 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7760 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7762 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7763 AOP(result)->aopu.aop_dir,
7764 AOP(result)->aopu.aop_dir);
7765 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7766 AOP(right)->aopu.aop_dir,
7767 AOP(right)->aopu.aop_dir);
7768 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7769 AOP(result)->aopu.aop_dir,
7770 AOP(result)->aopu.aop_dir);
7772 if( AOP_TYPE(result) == AOP_ACC) {
7773 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7774 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7775 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7776 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7780 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7781 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7782 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7783 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7785 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7786 AOP(result)->aopu.aop_dir,
7787 AOP(result)->aopu.aop_dir);
7788 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7789 AOP(right)->aopu.aop_dir,
7790 AOP(right)->aopu.aop_dir);
7791 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7792 AOP(left)->aopu.aop_dir,
7793 AOP(left)->aopu.aop_dir);
7794 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7795 AOP(result)->aopu.aop_dir,
7796 AOP(result)->aopu.aop_dir);
7801 symbol *tlbl = newiTempLabel(NULL);
7802 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7805 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7806 if( AOP_TYPE(right) == AOP_ACC) {
7807 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7809 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7810 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7815 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7816 pic16_emitcode(";XXX setb","c");
7817 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7818 AOP(left)->aopu.aop_dir,tlbl->key+100);
7819 pic16_toBoolean(right);
7820 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7821 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7822 jmpTrueOrFalse(ifx, tlbl);
7826 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7833 pic16_outBitC(result);
7835 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7836 genIfxJump(ifx, "c");
7840 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7841 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7842 if((AOP_TYPE(right) == AOP_LIT) &&
7843 (AOP_TYPE(result) == AOP_CRY) &&
7844 (AOP_TYPE(left) != AOP_CRY)){
7846 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7851 continueIfTrue(ifx);
7854 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7855 // lit = 0, result = boolean(left)
7857 pic16_emitcode(";XXX setb","c");
7858 pic16_toBoolean(right);
7860 symbol *tlbl = newiTempLabel(NULL);
7861 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7863 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7865 genIfxJump (ifx,"a");
7869 pic16_outBitC(result);
7873 /* if left is same as result */
7874 if(pic16_sameRegs(AOP(result),AOP(left))){
7876 for(;size--; offset++,lit>>=8) {
7877 if(AOP_TYPE(right) == AOP_LIT){
7878 if((lit & 0xff) == 0)
7879 /* or'ing with 0 has no effect */
7882 int p = pic16_my_powof2(lit & 0xff);
7884 /* only one bit is set in the literal, so use a bsf instruction */
7885 pic16_emitpcode(POC_BSF,
7886 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7888 if(know_W != (lit & 0xff))
7889 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7890 know_W = lit & 0xff;
7891 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7896 if (AOP_TYPE(left) == AOP_ACC) {
7897 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7898 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7900 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7901 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7903 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7910 // left & result in different registers
7911 if(AOP_TYPE(result) == AOP_CRY){
7913 // if(size), result in bit
7914 // if(!size && ifx), conditional oper: if(left | right)
7915 symbol *tlbl = newiTempLabel(NULL);
7916 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7917 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7921 pic16_emitcode(";XXX setb","c");
7923 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7924 pic16_emitcode(";XXX orl","a,%s",
7925 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7926 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7931 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7932 pic16_outBitC(result);
7934 jmpTrueOrFalse(ifx, tlbl);
7935 } else for(;(size--);offset++){
7937 // result = left & right
7938 if(AOP_TYPE(right) == AOP_LIT){
7939 int t = (lit >> (offset*8)) & 0x0FFL;
7942 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7945 // pic16_emitcode("movf","%s,w",
7946 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7947 // pic16_emitcode("movwf","%s",
7948 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7952 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7955 // pic16_emitcode("movlw","0x%x",t);
7956 // pic16_emitcode("iorwf","%s,w",
7957 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7958 // pic16_emitcode("movwf","%s",
7959 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7965 // faster than result <- left, anl result,right
7966 // and better if result is SFR
7967 if (AOP_TYPE(left) == AOP_ACC) {
7968 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7969 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7971 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7972 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7974 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7975 // pic16_emitcode("iorwf","%s,w",
7976 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7978 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7979 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7984 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7985 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7986 pic16_freeAsmop(result,NULL,ic,TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genXor - code for xclusive or */
7991 /*-----------------------------------------------------------------*/
7992 static void genXor (iCode *ic, iCode *ifx)
7994 operand *left, *right, *result;
7996 unsigned long lit = 0L;
7998 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8000 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8001 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8002 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8004 /* if left is a literal & right is not ||
8005 if left needs acc & right does not */
8006 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8007 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8008 operand *tmp = right ;
8013 /* if result = right then exchange them */
8014 if(pic16_sameRegs(AOP(result),AOP(right))){
8015 operand *tmp = right ;
8020 /* if right is bit then exchange them */
8021 if (AOP_TYPE(right) == AOP_CRY &&
8022 AOP_TYPE(left) != AOP_CRY){
8023 operand *tmp = right ;
8027 if(AOP_TYPE(right) == AOP_LIT)
8028 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8030 size = AOP_SIZE(result);
8034 if (AOP_TYPE(left) == AOP_CRY){
8035 if(AOP_TYPE(right) == AOP_LIT){
8036 // c = bit & literal;
8038 // lit>>1 != 0 => result = 1
8039 if(AOP_TYPE(result) == AOP_CRY){
8041 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8042 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8044 continueIfTrue(ifx);
8047 pic16_emitcode("setb","c");
8051 // lit == 0, result = left
8052 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8054 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8056 // lit == 1, result = not(left)
8057 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8058 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8059 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8060 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8063 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8064 pic16_emitcode("cpl","c");
8071 symbol *tlbl = newiTempLabel(NULL);
8072 if (AOP_TYPE(right) == AOP_CRY){
8074 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8077 int sizer = AOP_SIZE(right);
8079 // if val>>1 != 0, result = 1
8080 pic16_emitcode("setb","c");
8082 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8084 // test the msb of the lsb
8085 pic16_emitcode("anl","a,#0xfe");
8086 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8090 pic16_emitcode("rrc","a");
8092 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8093 pic16_emitcode("cpl","c");
8094 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8099 pic16_outBitC(result);
8101 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8102 genIfxJump(ifx, "c");
8106 if(pic16_sameRegs(AOP(result),AOP(left))){
8107 /* if left is same as result */
8108 for(;size--; offset++) {
8109 if(AOP_TYPE(right) == AOP_LIT){
8110 int t = (lit >> (offset*8)) & 0x0FFL;
8114 if (IS_AOP_PREG(left)) {
8115 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8117 pic16_aopPut(AOP(result),"a",offset);
8119 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8120 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8121 pic16_emitcode("xrl","%s,%s",
8122 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8123 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126 if (AOP_TYPE(left) == AOP_ACC)
8127 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8129 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8130 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8132 if (IS_AOP_PREG(left)) {
8133 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8134 pic16_aopPut(AOP(result),"a",offset);
8136 pic16_emitcode("xrl","%s,a",
8137 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8143 // left & result in different registers
8144 if(AOP_TYPE(result) == AOP_CRY){
8146 // if(size), result in bit
8147 // if(!size && ifx), conditional oper: if(left ^ right)
8148 symbol *tlbl = newiTempLabel(NULL);
8149 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8151 pic16_emitcode("setb","c");
8153 if((AOP_TYPE(right) == AOP_LIT) &&
8154 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8155 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8157 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8158 pic16_emitcode("xrl","a,%s",
8159 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8161 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8166 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8167 pic16_outBitC(result);
8169 jmpTrueOrFalse(ifx, tlbl);
8170 } else for(;(size--);offset++){
8172 // result = left & right
8173 if(AOP_TYPE(right) == AOP_LIT){
8174 int t = (lit >> (offset*8)) & 0x0FFL;
8177 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179 pic16_emitcode("movf","%s,w",
8180 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181 pic16_emitcode("movwf","%s",
8182 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8187 pic16_emitcode("comf","%s,w",
8188 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189 pic16_emitcode("movwf","%s",
8190 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8194 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8195 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8196 pic16_emitcode("movlw","0x%x",t);
8197 pic16_emitcode("xorwf","%s,w",
8198 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199 pic16_emitcode("movwf","%s",
8200 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8206 // faster than result <- left, anl result,right
8207 // and better if result is SFR
8208 if (AOP_TYPE(left) == AOP_ACC) {
8209 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8210 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8212 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8213 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8214 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8215 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8217 if ( AOP_TYPE(result) != AOP_ACC){
8218 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8219 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8225 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8226 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8227 pic16_freeAsmop(result,NULL,ic,TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genInline - write the inline code out */
8232 /*-----------------------------------------------------------------*/
8233 static void genInline (iCode *ic)
8235 char *buffer, *bp, *bp1;
8237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8239 _G.inLine += (!options.asmpeep);
8241 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8242 strcpy(buffer,IC_INLINE(ic));
8244 while((bp1=strstr(bp, "\\n"))) {
8252 /* This is an experimental code for #pragma inline
8253 and is temporarily disabled for 2.5.0 release */
8261 cbuf = Safe_strdup(buffer);
8262 cblen = strlen(buffer)+1;
8263 memset(cbuf, 0, cblen);
8268 if(*bp != '%')*bp1++ = *bp++;
8274 if(i>elementsInSet(asmInlineMap))break;
8277 s = indexSet(asmInlineMap, i);
8278 DEBUGpc("searching symbol s = `%s'", s);
8279 sym = findSym(SymbolTab, NULL, s);
8282 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8284 strcat(bp1, sym->rname);
8290 if(strlen(bp1) > cblen - 16) {
8291 int i = strlen(cbuf);
8293 cbuf = realloc(cbuf, cblen);
8294 memset(cbuf+i, 0, 50);
8300 buffer = Safe_strdup( cbuf );
8307 /* emit each line as a code */
8313 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8321 /* print label, use this special format with NULL directive
8322 * to denote that the argument should not be indented with tab */
8323 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326 /* advance to end of line (prevent splitting of comments at ':' */
8327 while (*bp && *bp != '\n') {
8335 if ((bp1 != bp) && *bp1)
8336 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8341 _G.inLine -= (!options.asmpeep);
8344 /*-----------------------------------------------------------------*/
8345 /* genRRC - rotate right with carry */
8346 /*-----------------------------------------------------------------*/
8347 static void genRRC (iCode *ic)
8349 operand *left , *result ;
8350 int size, offset = 0, same;
8352 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8354 /* rotate right with carry */
8356 result=IC_RESULT(ic);
8357 pic16_aopOp (left,ic,FALSE);
8358 pic16_aopOp (result,ic,TRUE);
8360 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8362 same = pic16_sameRegs(AOP(result),AOP(left));
8364 size = AOP_SIZE(result);
8366 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8368 /* get the lsb and put it into the carry */
8369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8376 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8378 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8385 pic16_freeAsmop(left,NULL,ic,TRUE);
8386 pic16_freeAsmop(result,NULL,ic,TRUE);
8389 /*-----------------------------------------------------------------*/
8390 /* genRLC - generate code for rotate left with carry */
8391 /*-----------------------------------------------------------------*/
8392 static void genRLC (iCode *ic)
8394 operand *left , *result ;
8395 int size, offset = 0;
8398 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8399 /* rotate right with carry */
8401 result=IC_RESULT(ic);
8402 pic16_aopOp (left,ic,FALSE);
8403 pic16_aopOp (result,ic,TRUE);
8405 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8407 same = pic16_sameRegs(AOP(result),AOP(left));
8409 /* move it to the result */
8410 size = AOP_SIZE(result);
8412 /* get the msb and put it into the carry */
8413 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8420 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8422 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8423 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8430 pic16_freeAsmop(left,NULL,ic,TRUE);
8431 pic16_freeAsmop(result,NULL,ic,TRUE);
8435 /* gpasm can get the highest order bit with HIGH/UPPER
8436 * so the following probably is not needed -- VR */
8438 /*-----------------------------------------------------------------*/
8439 /* genGetHbit - generates code get highest order bit */
8440 /*-----------------------------------------------------------------*/
8441 static void genGetHbit (iCode *ic)
8443 operand *left, *result;
8445 result=IC_RESULT(ic);
8446 pic16_aopOp (left,ic,FALSE);
8447 pic16_aopOp (result,ic,FALSE);
8449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8450 /* get the highest order byte into a */
8451 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8452 if(AOP_TYPE(result) == AOP_CRY){
8453 pic16_emitcode("rlc","a");
8454 pic16_outBitC(result);
8457 pic16_emitcode("rl","a");
8458 pic16_emitcode("anl","a,#0x01");
8459 pic16_outAcc(result);
8463 pic16_freeAsmop(left,NULL,ic,TRUE);
8464 pic16_freeAsmop(result,NULL,ic,TRUE);
8468 /*-----------------------------------------------------------------*/
8469 /* AccRol - rotate left accumulator by known count */
8470 /*-----------------------------------------------------------------*/
8471 static void AccRol (int shCount)
8473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8474 shCount &= 0x0007; // shCount : 0..7
8479 pic16_emitcode("rl","a");
8482 pic16_emitcode("rl","a");
8483 pic16_emitcode("rl","a");
8486 pic16_emitcode("swap","a");
8487 pic16_emitcode("rr","a");
8490 pic16_emitcode("swap","a");
8493 pic16_emitcode("swap","a");
8494 pic16_emitcode("rl","a");
8497 pic16_emitcode("rr","a");
8498 pic16_emitcode("rr","a");
8501 pic16_emitcode("rr","a");
8507 /*-----------------------------------------------------------------*/
8508 /* AccLsh - left shift accumulator by known count */
8509 /*-----------------------------------------------------------------*/
8510 static void AccLsh (int shCount, int doMask)
8512 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8518 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8526 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8532 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8533 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8537 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8540 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544 /* no masking is required in genPackBits */
8545 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8549 /*-----------------------------------------------------------------*/
8550 /* AccRsh - right shift accumulator by known count */
8551 /*-----------------------------------------------------------------*/
8552 static void AccRsh (int shCount, int andmask)
8554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8559 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8573 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8574 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8577 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8578 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8581 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8586 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8588 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8592 /*-----------------------------------------------------------------*/
8593 /* AccSRsh - signed right shift accumulator by known count */
8594 /*-----------------------------------------------------------------*/
8595 static void AccSRsh (int shCount)
8598 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8601 pic16_emitcode("mov","c,acc.7");
8602 pic16_emitcode("rrc","a");
8603 } else if(shCount == 2){
8604 pic16_emitcode("mov","c,acc.7");
8605 pic16_emitcode("rrc","a");
8606 pic16_emitcode("mov","c,acc.7");
8607 pic16_emitcode("rrc","a");
8609 tlbl = newiTempLabel(NULL);
8610 /* rotate right accumulator */
8611 AccRol(8 - shCount);
8612 /* and kill the higher order bits */
8613 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8614 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8615 pic16_emitcode("orl","a,#0x%02x",
8616 (unsigned char)~SRMask[shCount]);
8617 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8623 /*-----------------------------------------------------------------*/
8624 /* shiftR1Left2Result - shift right one byte from left to result */
8625 /*-----------------------------------------------------------------*/
8626 static void shiftR1Left2ResultSigned (operand *left, int offl,
8627 operand *result, int offr,
8632 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8634 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8638 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8640 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8649 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8651 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8653 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8654 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8656 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8657 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8663 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8665 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8666 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8670 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8673 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8674 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8681 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8682 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8683 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8688 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8694 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8695 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8696 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8703 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8705 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8707 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8711 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8713 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8719 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8720 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8722 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8724 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8725 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8726 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8734 /*-----------------------------------------------------------------*/
8735 /* shiftR1Left2Result - shift right one byte from left to result */
8736 /*-----------------------------------------------------------------*/
8737 static void shiftR1Left2Result (operand *left, int offl,
8738 operand *result, int offr,
8739 int shCount, int sign)
8743 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8745 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8747 /* Copy the msb into the carry if signed. */
8749 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8759 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8761 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8779 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8786 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8793 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8794 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8798 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8799 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8800 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8802 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8807 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8808 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8809 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8810 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8811 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8816 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8817 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8818 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8827 /*-----------------------------------------------------------------*/
8828 /* shiftL1Left2Result - shift left one byte from left to result */
8829 /*-----------------------------------------------------------------*/
8830 static void shiftL1Left2Result (operand *left, int offl,
8831 operand *result, int offr, int shCount)
8836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8838 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8839 DEBUGpic16_emitcode ("; ***","same = %d",same);
8840 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8842 /* shift left accumulator */
8843 //AccLsh(shCount, 1); // don't comment out just yet...
8844 // pic16_aopPut(AOP(result),"a",offr);
8848 /* Shift left 1 bit position */
8849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8851 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8858 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8859 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8860 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8861 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8865 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8866 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8873 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8877 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8878 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8883 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8884 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8886 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8889 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8890 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8895 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8900 /*-----------------------------------------------------------------*/
8901 /* movLeft2Result - move byte from left to result */
8902 /*-----------------------------------------------------------------*/
8903 static void movLeft2Result (operand *left, int offl,
8904 operand *result, int offr)
8907 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8908 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8909 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8911 if (*l == '@' && (IS_AOP_PREG(result))) {
8912 pic16_emitcode("mov","a,%s",l);
8913 pic16_aopPut(AOP(result),"a",offr);
8915 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8916 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8921 /*-----------------------------------------------------------------*/
8922 /* shiftL2Left2Result - shift left two bytes from left to result */
8923 /*-----------------------------------------------------------------*/
8924 static void shiftL2Left2Result (operand *left, int offl,
8925 operand *result, int offr, int shCount)
8927 int same = pic16_sameRegs(AOP(result), AOP(left));
8930 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8932 if (same && (offl != offr)) { // shift bytes
8935 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8936 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8938 } else { // just treat as different later on
8951 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8964 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8965 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8972 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8977 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8980 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8982 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8983 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8984 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8985 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8989 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8990 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8991 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8992 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9003 /* note, use a mov/add for the shift since the mov has a
9004 chance of getting optimized out */
9005 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9008 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9013 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9020 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9021 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9026 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9036 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9037 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9039 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9042 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9045 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9046 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9051 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9052 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9053 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9054 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9060 /*-----------------------------------------------------------------*/
9061 /* shiftR2Left2Result - shift right two bytes from left to result */
9062 /*-----------------------------------------------------------------*/
9063 static void shiftR2Left2Result (operand *left, int offl,
9064 operand *result, int offr,
9065 int shCount, int sign)
9067 int same = pic16_sameRegs(AOP(result), AOP(left));
9069 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9071 if (same && (offl != offr)) { // shift right bytes
9074 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9075 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9077 } else { // just treat as different later on
9089 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9094 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9095 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9098 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9099 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9100 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9108 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9109 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9117 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9121 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9122 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9123 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9126 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9127 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9129 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9130 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9131 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9132 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9133 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9138 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9142 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9143 pic16_emitpcode(POC_BTFSC,
9144 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9145 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9154 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9161 pic16_emitpcode(POC_BTFSC,
9162 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9163 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9165 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9166 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9167 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9168 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9170 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9171 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9172 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9175 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9177 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9179 pic16_emitpcode(POC_BTFSC,
9180 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9181 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9183 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9184 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9192 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9193 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9194 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9197 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9199 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9204 /*-----------------------------------------------------------------*/
9205 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9206 /*-----------------------------------------------------------------*/
9207 static void shiftLLeftOrResult (operand *left, int offl,
9208 operand *result, int offr, int shCount)
9210 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9212 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9213 /* shift left accumulator */
9215 /* or with result */
9216 /* back to result */
9217 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9220 /*-----------------------------------------------------------------*/
9221 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9222 /*-----------------------------------------------------------------*/
9223 static void shiftRLeftOrResult (operand *left, int offl,
9224 operand *result, int offr, int shCount)
9226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9228 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9229 /* shift right accumulator */
9231 /* or with result */
9232 /* back to result */
9233 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9236 /*-----------------------------------------------------------------*/
9237 /* genlshOne - left shift a one byte quantity by known count */
9238 /*-----------------------------------------------------------------*/
9239 static void genlshOne (operand *result, operand *left, int shCount)
9241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9242 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9245 /*-----------------------------------------------------------------*/
9246 /* genlshTwo - left shift two bytes by known amount != 0 */
9247 /*-----------------------------------------------------------------*/
9248 static void genlshTwo (operand *result,operand *left, int shCount)
9252 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9253 size = pic16_getDataSize(result);
9255 /* if shCount >= 8 */
9261 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9263 movLeft2Result(left, LSB, result, MSB16);
9265 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9268 /* 1 <= shCount <= 7 */
9271 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9273 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9277 /*-----------------------------------------------------------------*/
9278 /* shiftLLong - shift left one long from left to result */
9279 /* offr = LSB or MSB16 */
9280 /*-----------------------------------------------------------------*/
9281 static void shiftLLong (operand *left, operand *result, int offr )
9283 int size = AOP_SIZE(result);
9284 int same = pic16_sameRegs(AOP(left),AOP(result));
9287 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9289 if (same && (offr == MSB16)) { //shift one byte
9290 for(i=size-1;i>=MSB16;i--) {
9291 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9295 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9298 if (size > LSB+offr ){
9300 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9302 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9303 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9307 if(size > MSB16+offr){
9309 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9311 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9312 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9316 if(size > MSB24+offr){
9318 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9320 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9321 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9325 if(size > MSB32+offr){
9327 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9329 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9330 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9334 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9338 /*-----------------------------------------------------------------*/
9339 /* genlshFour - shift four byte by a known amount != 0 */
9340 /*-----------------------------------------------------------------*/
9341 static void genlshFour (operand *result, operand *left, int shCount)
9345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9346 size = AOP_SIZE(result);
9348 /* if shifting more that 3 bytes */
9349 if (shCount >= 24 ) {
9352 /* lowest order of left goes to the highest
9353 order of the destination */
9354 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9356 movLeft2Result(left, LSB, result, MSB32);
9358 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9359 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9360 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9365 /* more than two bytes */
9366 else if ( shCount >= 16 ) {
9367 /* lower order two bytes goes to higher order two bytes */
9369 /* if some more remaining */
9371 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9373 movLeft2Result(left, MSB16, result, MSB32);
9374 movLeft2Result(left, LSB, result, MSB24);
9376 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9377 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9381 /* if more than 1 byte */
9382 else if ( shCount >= 8 ) {
9383 /* lower order three bytes goes to higher order three bytes */
9387 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9389 movLeft2Result(left, LSB, result, MSB16);
9391 else{ /* size = 4 */
9393 movLeft2Result(left, MSB24, result, MSB32);
9394 movLeft2Result(left, MSB16, result, MSB24);
9395 movLeft2Result(left, LSB, result, MSB16);
9396 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9398 else if(shCount == 1)
9399 shiftLLong(left, result, MSB16);
9401 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9402 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9403 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9404 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9409 /* 1 <= shCount <= 7 */
9410 else if(shCount <= 3)
9412 shiftLLong(left, result, LSB);
9413 while(--shCount >= 1)
9414 shiftLLong(result, result, LSB);
9416 /* 3 <= shCount <= 7, optimize */
9418 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9419 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9420 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9424 /*-----------------------------------------------------------------*/
9425 /* genLeftShiftLiteral - left shifting by known count */
9426 /*-----------------------------------------------------------------*/
9427 void pic16_genLeftShiftLiteral (operand *left,
9432 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9436 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9437 pic16_freeAsmop(right,NULL,ic,TRUE);
9439 pic16_aopOp(left,ic,FALSE);
9440 pic16_aopOp(result,ic,TRUE);
9442 size = getSize(operandType(result));
9445 pic16_emitcode("; shift left ","result %d, left %d",size,
9449 /* I suppose that the left size >= result size */
9452 movLeft2Result(left, size, result, size);
9456 else if(shCount >= (size * 8))
9458 pic16_aopPut(AOP(result),zero,size);
9462 genlshOne (result,left,shCount);
9467 genlshTwo (result,left,shCount);
9471 genlshFour (result,left,shCount);
9475 pic16_freeAsmop(left,NULL,ic,TRUE);
9476 pic16_freeAsmop(result,NULL,ic,TRUE);
9479 /*-----------------------------------------------------------------*
9480 * genMultiAsm - repeat assembly instruction for size of register.
9481 * if endian == 1, then the high byte (i.e base address + size of
9482 * register) is used first else the low byte is used first;
9483 *-----------------------------------------------------------------*/
9484 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9502 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9508 #if !(USE_GENERIC_SIGNED_SHIFT)
9509 /*-----------------------------------------------------------------*/
9510 /* genLeftShift - generates code for left shifting */
9511 /*-----------------------------------------------------------------*/
9512 static void genLeftShift (iCode *ic)
9514 operand *left,*right, *result;
9517 symbol *tlbl , *tlbl1;
9520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 right = IC_RIGHT(ic);
9524 result = IC_RESULT(ic);
9526 pic16_aopOp(right,ic,FALSE);
9528 /* if the shift count is known then do it
9529 as efficiently as possible */
9530 if (AOP_TYPE(right) == AOP_LIT) {
9531 pic16_genLeftShiftLiteral (left,right,result,ic);
9535 /* shift count is unknown then we have to form
9536 * a loop. Get the loop count in WREG : Note: we take
9537 * only the lower order byte since shifting
9538 * more than 32 bits make no sense anyway, ( the
9539 * largest size of an object can be only 32 bits ) */
9541 pic16_aopOp(left,ic,FALSE);
9542 pic16_aopOp(result,ic,FALSE);
9544 /* now move the left to the result if they are not the
9545 * same, and if size > 1,
9546 * and if right is not same to result (!!!) -- VR */
9547 if (!pic16_sameRegs(AOP(left),AOP(result))
9548 && (AOP_SIZE(result) > 1)) {
9550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9552 size = AOP_SIZE(result);
9557 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9558 if (*l == '@' && (IS_AOP_PREG(result))) {
9560 pic16_emitcode("mov","a,%s",l);
9561 pic16_aopPut(AOP(result),"a",offset);
9565 /* we don't know if left is a literal or a register, take care -- VR */
9566 pic16_mov2f(AOP(result), AOP(left), offset);
9572 size = AOP_SIZE(result);
9574 /* if it is only one byte then */
9576 if(optimized_for_speed) {
9577 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9578 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9579 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9581 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9582 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9583 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9584 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9585 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9586 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9587 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9588 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9591 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9593 tlbl = newiTempLabel(NULL);
9596 /* this is already done, why change it? */
9597 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9598 pic16_mov2f(AOP(result), AOP(left), 0);
9602 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9603 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9604 pic16_emitpLabel(tlbl->key);
9605 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9606 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9608 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9613 if (pic16_sameRegs(AOP(left),AOP(result))) {
9615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9617 tlbl = newiTempLabel(NULL);
9618 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9619 genMultiAsm(POC_RRCF, result, size,1);
9620 pic16_emitpLabel(tlbl->key);
9621 genMultiAsm(POC_RLCF, result, size,0);
9622 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9624 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9628 //tlbl = newiTempLabel(NULL);
9630 //tlbl1 = newiTempLabel(NULL);
9632 //reAdjustPreg(AOP(result));
9634 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9635 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9636 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9638 //pic16_emitcode("add","a,acc");
9639 //pic16_aopPut(AOP(result),"a",offset++);
9641 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9643 // pic16_emitcode("rlc","a");
9644 // pic16_aopPut(AOP(result),"a",offset++);
9646 //reAdjustPreg(AOP(result));
9648 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9649 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9652 tlbl = newiTempLabel(NULL);
9653 tlbl1= newiTempLabel(NULL);
9655 size = AOP_SIZE(result);
9658 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9660 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9662 /* offset should be 0, 1 or 3 */
9664 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9666 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9668 pic16_emitpcode(POC_MOVWF, pctemp);
9671 pic16_emitpLabel(tlbl->key);
9674 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9676 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9678 pic16_emitpcode(POC_DECFSZ, pctemp);
9679 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9680 pic16_emitpLabel(tlbl1->key);
9682 pic16_popReleaseTempReg(pctemp,1);
9686 pic16_freeAsmop (right,NULL,ic,TRUE);
9687 pic16_freeAsmop(left,NULL,ic,TRUE);
9688 pic16_freeAsmop(result,NULL,ic,TRUE);
9694 #error old code (left here for reference)
9695 /*-----------------------------------------------------------------*/
9696 /* genLeftShift - generates code for left shifting */
9697 /*-----------------------------------------------------------------*/
9698 static void genLeftShift (iCode *ic)
9700 operand *left,*right, *result;
9703 symbol *tlbl , *tlbl1;
9706 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9708 right = IC_RIGHT(ic);
9710 result = IC_RESULT(ic);
9712 pic16_aopOp(right,ic,FALSE);
9714 /* if the shift count is known then do it
9715 as efficiently as possible */
9716 if (AOP_TYPE(right) == AOP_LIT) {
9717 pic16_genLeftShiftLiteral (left,right,result,ic);
9721 /* shift count is unknown then we have to form
9722 a loop get the loop count in B : Note: we take
9723 only the lower order byte since shifting
9724 more that 32 bits make no sense anyway, ( the
9725 largest size of an object can be only 32 bits ) */
9728 pic16_aopOp(left,ic,FALSE);
9729 pic16_aopOp(result,ic,FALSE);
9731 /* now move the left to the result if they are not the
9733 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9734 AOP_SIZE(result) > 1) {
9736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9738 size = AOP_SIZE(result);
9741 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9742 if (*l == '@' && (IS_AOP_PREG(result))) {
9744 pic16_emitcode("mov","a,%s",l);
9745 pic16_aopPut(AOP(result),"a",offset);
9748 /* we don't know if left is a literal or a register, take care -- VR */
9749 pic16_mov2f(AOP(result), AOP(left), offset);
9755 size = AOP_SIZE(result);
9757 /* if it is only one byte then */
9759 if(optimized_for_speed) {
9760 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9762 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9765 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9766 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9767 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9768 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9769 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9770 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9771 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9776 tlbl = newiTempLabel(NULL);
9777 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9778 pic16_mov2f(AOP(result), AOP(left), 0);
9780 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9781 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9784 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9785 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9786 pic16_emitpLabel(tlbl->key);
9787 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9788 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9790 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9795 if (pic16_sameRegs(AOP(left),AOP(result))) {
9797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9799 tlbl = newiTempLabel(NULL);
9800 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9801 genMultiAsm(POC_RRCF, result, size,1);
9802 pic16_emitpLabel(tlbl->key);
9803 genMultiAsm(POC_RLCF, result, size,0);
9804 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9806 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9810 //tlbl = newiTempLabel(NULL);
9812 //tlbl1 = newiTempLabel(NULL);
9814 //reAdjustPreg(AOP(result));
9816 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9817 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9818 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9820 //pic16_emitcode("add","a,acc");
9821 //pic16_aopPut(AOP(result),"a",offset++);
9823 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9825 // pic16_emitcode("rlc","a");
9826 // pic16_aopPut(AOP(result),"a",offset++);
9828 //reAdjustPreg(AOP(result));
9830 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9831 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9834 tlbl = newiTempLabel(NULL);
9835 tlbl1= newiTempLabel(NULL);
9837 size = AOP_SIZE(result);
9840 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9842 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9844 /* offset should be 0, 1 or 3 */
9846 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9848 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9850 pic16_emitpcode(POC_MOVWF, pctemp);
9853 pic16_emitpLabel(tlbl->key);
9856 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9860 pic16_emitpcode(POC_DECFSZ, pctemp);
9861 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9862 pic16_emitpLabel(tlbl1->key);
9864 pic16_popReleaseTempReg(pctemp,1);
9868 pic16_freeAsmop (right,NULL,ic,TRUE);
9869 pic16_freeAsmop(left,NULL,ic,TRUE);
9870 pic16_freeAsmop(result,NULL,ic,TRUE);
9874 /*-----------------------------------------------------------------*/
9875 /* genrshOne - right shift a one byte quantity by known count */
9876 /*-----------------------------------------------------------------*/
9877 static void genrshOne (operand *result, operand *left,
9878 int shCount, int sign)
9880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9881 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9884 /*-----------------------------------------------------------------*/
9885 /* genrshTwo - right shift two bytes by known amount != 0 */
9886 /*-----------------------------------------------------------------*/
9887 static void genrshTwo (operand *result,operand *left,
9888 int shCount, int sign)
9890 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9891 /* if shCount >= 8 */
9895 shiftR1Left2Result(left, MSB16, result, LSB,
9898 movLeft2Result(left, MSB16, result, LSB);
9900 pic16_addSign (result, 1, sign);
9903 /* 1 <= shCount <= 7 */
9905 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9908 /*-----------------------------------------------------------------*/
9909 /* shiftRLong - shift right one long from left to result */
9910 /* offl = LSB or MSB16 */
9911 /*-----------------------------------------------------------------*/
9912 static void shiftRLong (operand *left, int offl,
9913 operand *result, int sign)
9915 int size = AOP_SIZE(result);
9916 int same = pic16_sameRegs(AOP(left),AOP(result));
9918 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9920 if (same && (offl == MSB16)) { //shift one byte right
9921 for(i=MSB16;i<size;i++) {
9922 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9923 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9928 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9934 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9936 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9941 /* add sign of "a" */
9942 pic16_addSign(result, MSB32, sign);
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9953 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9955 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9960 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9963 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9969 /*-----------------------------------------------------------------*/
9970 /* genrshFour - shift four byte by a known amount != 0 */
9971 /*-----------------------------------------------------------------*/
9972 static void genrshFour (operand *result, operand *left,
9973 int shCount, int sign)
9975 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9976 /* if shifting more that 3 bytes */
9977 if(shCount >= 24 ) {
9980 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9982 movLeft2Result(left, MSB32, result, LSB);
9984 pic16_addSign(result, MSB16, sign);
9986 else if(shCount >= 16){
9989 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9991 movLeft2Result(left, MSB24, result, LSB);
9992 movLeft2Result(left, MSB32, result, MSB16);
9994 pic16_addSign(result, MSB24, sign);
9996 else if(shCount >= 8){
9999 shiftRLong(left, MSB16, result, sign);
10000 else if(shCount == 0){
10001 movLeft2Result(left, MSB16, result, LSB);
10002 movLeft2Result(left, MSB24, result, MSB16);
10003 movLeft2Result(left, MSB32, result, MSB24);
10004 pic16_addSign(result, MSB32, sign);
10006 else{ //shcount >= 2
10007 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10008 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10009 /* the last shift is signed */
10010 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10011 pic16_addSign(result, MSB32, sign);
10014 else{ /* 1 <= shCount <= 7 */
10016 shiftRLong(left, LSB, result, sign);
10018 shiftRLong(result, LSB, result, sign);
10021 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10022 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10023 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10028 /*-----------------------------------------------------------------*/
10029 /* genRightShiftLiteral - right shifting by known count */
10030 /*-----------------------------------------------------------------*/
10031 static void genRightShiftLiteral (operand *left,
10037 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10038 int lsize,res_size;
10040 pic16_freeAsmop(right,NULL,ic,TRUE);
10042 pic16_aopOp(left,ic,FALSE);
10043 pic16_aopOp(result,ic,TRUE);
10045 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10048 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10052 lsize = pic16_getDataSize(left);
10053 res_size = pic16_getDataSize(result);
10054 /* test the LEFT size !!! */
10056 /* I suppose that the left size >= result size */
10058 assert (res_size <= lsize);
10059 while (res_size--) {
10060 pic16_mov2f (AOP(result), AOP(left), res_size);
10064 else if(shCount >= (lsize * 8)){
10066 if(res_size == 1) {
10067 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10069 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10075 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10076 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10077 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10084 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10089 switch (res_size) {
10091 genrshOne (result,left,shCount,sign);
10095 genrshTwo (result,left,shCount,sign);
10099 genrshFour (result,left,shCount,sign);
10107 pic16_freeAsmop(left,NULL,ic,TRUE);
10108 pic16_freeAsmop(result,NULL,ic,TRUE);
10111 #if !(USE_GENERIC_SIGNED_SHIFT)
10112 /*-----------------------------------------------------------------*/
10113 /* genSignedRightShift - right shift of signed number */
10114 /*-----------------------------------------------------------------*/
10115 static void genSignedRightShift (iCode *ic)
10117 operand *right, *left, *result;
10120 symbol *tlbl, *tlbl1 ;
10123 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10125 /* we do it the hard way put the shift count in b
10126 and loop thru preserving the sign */
10127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10129 right = IC_RIGHT(ic);
10130 left = IC_LEFT(ic);
10131 result = IC_RESULT(ic);
10133 pic16_aopOp(right,ic,FALSE);
10134 pic16_aopOp(left,ic,FALSE);
10135 pic16_aopOp(result,ic,FALSE);
10138 if ( AOP_TYPE(right) == AOP_LIT) {
10139 genRightShiftLiteral (left,right,result,ic,1);
10142 /* shift count is unknown then we have to form
10143 a loop get the loop count in B : Note: we take
10144 only the lower order byte since shifting
10145 more that 32 bits make no sense anyway, ( the
10146 largest size of an object can be only 32 bits ) */
10148 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10149 //pic16_emitcode("inc","b");
10150 //pic16_freeAsmop (right,NULL,ic,TRUE);
10151 //pic16_aopOp(left,ic,FALSE);
10152 //pic16_aopOp(result,ic,FALSE);
10154 /* now move the left to the result if they are not the
10156 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10157 AOP_SIZE(result) > 1) {
10159 size = AOP_SIZE(result);
10163 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10164 if (*l == '@' && IS_AOP_PREG(result)) {
10166 pic16_emitcode("mov","a,%s",l);
10167 pic16_aopPut(AOP(result),"a",offset);
10169 pic16_aopPut(AOP(result),l,offset);
10171 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10172 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10178 /* mov the highest order bit to OVR */
10179 tlbl = newiTempLabel(NULL);
10180 tlbl1= newiTempLabel(NULL);
10182 size = AOP_SIZE(result);
10185 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10187 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10189 /* offset should be 0, 1 or 3 */
10190 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10192 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10194 pic16_emitpcode(POC_MOVWF, pctemp);
10197 pic16_emitpLabel(tlbl->key);
10199 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10200 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10203 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10206 pic16_emitpcode(POC_DECFSZ, pctemp);
10207 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10208 pic16_emitpLabel(tlbl1->key);
10210 pic16_popReleaseTempReg(pctemp,1);
10212 size = AOP_SIZE(result);
10214 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10215 pic16_emitcode("rlc","a");
10216 pic16_emitcode("mov","ov,c");
10217 /* if it is only one byte then */
10219 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10221 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10222 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10223 pic16_emitcode("mov","c,ov");
10224 pic16_emitcode("rrc","a");
10225 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10226 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10227 pic16_aopPut(AOP(result),"a",0);
10231 reAdjustPreg(AOP(result));
10232 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10233 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10234 pic16_emitcode("mov","c,ov");
10236 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10238 pic16_emitcode("rrc","a");
10239 pic16_aopPut(AOP(result),"a",offset--);
10241 reAdjustPreg(AOP(result));
10242 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10243 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10248 pic16_freeAsmop(left,NULL,ic,TRUE);
10249 pic16_freeAsmop(result,NULL,ic,TRUE);
10250 pic16_freeAsmop(right,NULL,ic,TRUE);
10254 #if !(USE_GENERIC_SIGNED_SHIFT)
10255 #warning This implementation of genRightShift() is incomplete!
10256 /*-----------------------------------------------------------------*/
10257 /* genRightShift - generate code for right shifting */
10258 /*-----------------------------------------------------------------*/
10259 static void genRightShift (iCode *ic)
10261 operand *right, *left, *result;
10265 symbol *tlbl, *tlbl1 ;
10267 /* if signed then we do it the hard way preserve the
10268 sign bit moving it inwards */
10269 letype = getSpec(operandType(IC_LEFT(ic)));
10270 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10272 if (!SPEC_USIGN(letype)) {
10273 genSignedRightShift (ic);
10277 /* signed & unsigned types are treated the same : i.e. the
10278 signed is NOT propagated inwards : quoting from the
10279 ANSI - standard : "for E1 >> E2, is equivalent to division
10280 by 2**E2 if unsigned or if it has a non-negative value,
10281 otherwise the result is implementation defined ", MY definition
10282 is that the sign does not get propagated */
10284 right = IC_RIGHT(ic);
10285 left = IC_LEFT(ic);
10286 result = IC_RESULT(ic);
10288 pic16_aopOp(right,ic,FALSE);
10290 /* if the shift count is known then do it
10291 as efficiently as possible */
10292 if (AOP_TYPE(right) == AOP_LIT) {
10293 genRightShiftLiteral (left,right,result,ic, 0);
10297 /* shift count is unknown then we have to form
10298 a loop get the loop count in B : Note: we take
10299 only the lower order byte since shifting
10300 more that 32 bits make no sense anyway, ( the
10301 largest size of an object can be only 32 bits ) */
10303 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10304 pic16_emitcode("inc","b");
10305 pic16_aopOp(left,ic,FALSE);
10306 pic16_aopOp(result,ic,FALSE);
10308 /* now move the left to the result if they are not the
10310 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10311 AOP_SIZE(result) > 1) {
10313 size = AOP_SIZE(result);
10316 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10317 if (*l == '@' && IS_AOP_PREG(result)) {
10319 pic16_emitcode("mov","a,%s",l);
10320 pic16_aopPut(AOP(result),"a",offset);
10322 pic16_aopPut(AOP(result),l,offset);
10327 tlbl = newiTempLabel(NULL);
10328 tlbl1= newiTempLabel(NULL);
10329 size = AOP_SIZE(result);
10332 /* if it is only one byte then */
10335 tlbl = newiTempLabel(NULL);
10336 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10337 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10338 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10341 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10342 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10343 pic16_emitpLabel(tlbl->key);
10344 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10345 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10347 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10352 reAdjustPreg(AOP(result));
10353 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10354 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10357 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10359 pic16_emitcode("rrc","a");
10360 pic16_aopPut(AOP(result),"a",offset--);
10362 reAdjustPreg(AOP(result));
10364 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10365 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10368 pic16_freeAsmop(left,NULL,ic,TRUE);
10369 pic16_freeAsmop (right,NULL,ic,TRUE);
10370 pic16_freeAsmop(result,NULL,ic,TRUE);
10374 #if (USE_GENERIC_SIGNED_SHIFT)
10375 /*-----------------------------------------------------------------*/
10376 /* genGenericShift - generates code for left or right shifting */
10377 /*-----------------------------------------------------------------*/
10378 static void genGenericShift (iCode *ic, int isShiftLeft) {
10379 operand *left,*right, *result;
10381 int sign, signedCount;
10382 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10383 PIC_OPCODE pos_shift, neg_shift;
10387 right = IC_RIGHT(ic);
10388 left = IC_LEFT(ic);
10389 result = IC_RESULT(ic);
10391 pic16_aopOp(right,ic,FALSE);
10392 pic16_aopOp(left,ic,FALSE);
10393 pic16_aopOp(result,ic,TRUE);
10395 sign = !SPEC_USIGN(operandType (left));
10396 signedCount = !SPEC_USIGN(operandType (right));
10398 /* if the shift count is known then do it
10399 as efficiently as possible */
10400 if (AOP_TYPE(right) == AOP_LIT) {
10401 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10402 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10403 // we should modify right->aopu.aop_lit here!
10404 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10405 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10407 pic16_genLeftShiftLiteral (left,right,result,ic);
10409 genRightShiftLiteral (left,right,result,ic, sign);
10412 } // if (right is literal)
10414 /* shift count is unknown then we have to form a loop.
10415 * Note: we take only the lower order byte since shifting
10416 * more than 32 bits make no sense anyway, ( the
10417 * largest size of an object can be only 32 bits )
10418 * Note: we perform arithmetic shifts if the left operand is
10419 * signed and we do an (effective) right shift, i. e. we
10420 * shift in the sign bit from the left. */
10422 label_complete = newiTempLabel ( NULL );
10423 label_loop_pos = newiTempLabel ( NULL );
10424 label_loop_neg = NULL;
10425 label_negative = NULL;
10426 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10427 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10430 // additional labels needed
10431 label_loop_neg = newiTempLabel ( NULL );
10432 label_negative = newiTempLabel ( NULL );
10435 // copy source to result -- this will effectively truncate the left operand to the size of result!
10436 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10437 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10438 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10439 pic16_mov2f (AOP(result),AOP(left), offset);
10442 // if result is longer than left, fill with zeros (or sign)
10443 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10444 if (sign && AOP_SIZE(left) > 0) {
10445 // shift signed operand -- fill with sign
10446 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10447 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10448 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10449 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10450 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10453 // shift unsigned operand -- fill result with zeros
10454 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10455 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10458 } // if (size mismatch)
10460 pic16_mov2w (AOP(right), 0);
10461 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10462 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10465 // perform a shift by one (shift count is positive)
10466 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10467 // 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])
10468 pic16_emitpLabel (label_loop_pos->key);
10470 if (sign && (pos_shift == POC_RRCF)) {
10471 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10474 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10475 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10476 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10478 // perform a shift by one (shift count is positive)
10479 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10480 // 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])
10481 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10482 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10484 pic16_emitpLabel (label_loop_pos->key);
10485 if (sign && (pos_shift == POC_RRCF)) {
10486 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10489 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10490 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10491 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10492 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10496 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10498 pic16_emitpLabel (label_negative->key);
10499 // perform a shift by -1 (shift count is negative)
10500 // 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)
10502 pic16_emitpLabel (label_loop_neg->key);
10503 if (sign && (neg_shift == POC_RRCF)) {
10504 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10507 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10508 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10509 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10510 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10511 } // if (signedCount)
10513 pic16_emitpLabel (label_complete->key);
10516 pic16_freeAsmop (right,NULL,ic,TRUE);
10517 pic16_freeAsmop(left,NULL,ic,TRUE);
10518 pic16_freeAsmop(result,NULL,ic,TRUE);
10521 static void genLeftShift (iCode *ic) {
10522 genGenericShift (ic, 1);
10525 static void genRightShift (iCode *ic) {
10526 genGenericShift (ic, 0);
10531 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10532 void pic16_loadFSR0(operand *op, int lit)
10534 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10535 if (AOP_TYPE(op) == AOP_LIT) {
10536 /* handle 12 bit integers correctly */
10537 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10538 if ((val & 0x0fff) != val) {
10539 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10540 val, (val & 0x0fff) );
10543 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10545 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10548 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10549 // set up FSR0 with address of result
10550 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10551 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10555 /*----------------------------------------------------------------*/
10556 /* pic16_derefPtr - move one byte from the location ptr points to */
10557 /* to WREG (doWrite == 0) or one byte from WREG */
10558 /* to the location ptr points to (doWrite != 0) */
10559 /*----------------------------------------------------------------*/
10560 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10562 if (!IS_PTR(operandType(ptr)))
10564 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10565 else pic16_mov2w (AOP(ptr), 0);
10569 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10570 /* We might determine pointer type right here: */
10571 p_type = DCL_TYPE(operandType(ptr));
10576 if (!fsr0_setup || !*fsr0_setup)
10578 pic16_loadFSR0( ptr, 0 );
10579 if (fsr0_setup) *fsr0_setup = 1;
10582 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10584 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10588 if (AOP(ptr)->aopu.aop_reg[2]) {
10589 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10590 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10591 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10592 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10593 pic16_mov2w(AOP(ptr), 2);
10594 pic16_callGenericPointerRW(doWrite, 1);
10596 // data pointer (just 2 byte given)
10597 if (!fsr0_setup || !*fsr0_setup)
10599 pic16_loadFSR0( ptr, 0 );
10600 if (fsr0_setup) *fsr0_setup = 1;
10603 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10605 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10610 assert (0 && "invalid pointer type specified");
10615 /*-----------------------------------------------------------------*/
10616 /* genUnpackBits - generates code for unpacking bits */
10617 /*-----------------------------------------------------------------*/
10618 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10621 sym_link *etype, *letype;
10622 int blen=0, bstr=0;
10627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10628 etype = getSpec(operandType(result));
10629 letype = getSpec(operandType(left));
10631 // if(IS_BITFIELD(etype)) {
10632 blen = SPEC_BLEN(etype);
10633 bstr = SPEC_BSTR(etype);
10636 lbstr = SPEC_BSTR( letype );
10638 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10639 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10642 if((blen == 1) && (bstr < 8)
10643 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10644 /* it is a single bit, so use the appropriate bit instructions */
10645 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10647 same = pic16_sameRegs(AOP(left),AOP(result));
10648 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10649 pic16_emitpcode(POC_CLRF, op);
10651 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10652 /* workaround to reduce the extra lfsr instruction */
10653 pic16_emitpcode(POC_BTFSC,
10654 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10656 assert (PIC_IS_DATA_PTR (operandType(left)));
10657 pic16_loadFSR0 (left, 0);
10658 pic16_emitpcode(POC_BTFSC,
10659 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10662 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10663 /* unsigned bitfields result in either 0 or 1 */
10664 pic16_emitpcode(POC_INCF, op);
10666 /* signed bitfields result in either 0 or -1 */
10667 pic16_emitpcode(POC_DECF, op);
10670 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10673 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10679 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10680 // access symbol directly
10681 pic16_mov2w (AOP(left), 0);
10683 pic16_derefPtr (left, ptype, 0, NULL);
10686 /* if we have bitdisplacement then it fits */
10687 /* into this byte completely or if length is */
10688 /* less than a byte */
10689 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10691 /* shift right acc */
10694 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10695 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10697 /* VR -- normally I would use the following, but since we use the hack,
10698 * to avoid the masking from AccRsh, why not mask it right now? */
10701 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10704 /* extend signed bitfields to 8 bits */
10705 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10707 assert (blen + bstr > 0);
10708 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10709 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10712 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10714 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10718 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10719 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10726 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10728 int size, offset = 0, leoffset=0 ;
10730 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10731 pic16_aopOp(result, ic, TRUE);
10735 size = AOP_SIZE(result);
10736 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10740 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10741 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10742 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10747 if(AOP(left)->aopu.pcop->type == PO_DIR)
10748 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10750 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10753 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10755 // pic16_DumpOp("(result)",result);
10756 if(is_LitAOp(AOP(result))) {
10757 pic16_mov2w(AOP(left), offset); // patch 8
10758 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10760 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10761 pic16_popGet(AOP(left), offset), //patch 8
10762 pic16_popGet(AOP(result), offset)));
10770 pic16_freeAsmop(result,NULL,ic,TRUE);
10775 /*-----------------------------------------------------------------*/
10776 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10777 /*-----------------------------------------------------------------*/
10778 static void genNearPointerGet (operand *left,
10782 // asmop *aop = NULL;
10783 //regs *preg = NULL ;
10784 sym_link *rtype, *retype;
10785 sym_link *ltype, *letype;
10789 rtype = operandType(result);
10790 retype= getSpec(rtype);
10791 ltype = operandType(left);
10792 letype= getSpec(ltype);
10794 pic16_aopOp(left,ic,FALSE);
10796 // pic16_DumpOp("(left)",left);
10797 // pic16_DumpOp("(result)",result);
10799 /* if left is rematerialisable and
10800 * result is not bit variable type and
10801 * the left is pointer to data space i.e
10802 * lower 128 bytes of space */
10804 if (AOP_TYPE(left) == AOP_PCODE
10805 && !IS_BITFIELD(retype)
10806 && DCL_TYPE(ltype) == POINTER) {
10808 genDataPointerGet (left,result,ic);
10809 pic16_freeAsmop(left, NULL, ic, TRUE);
10813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10814 pic16_aopOp (result,ic,TRUE);
10816 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10819 if(IS_BITFIELD( retype )
10820 && (SPEC_BLEN(operandType(result))==1)
10824 int bitstrt, bytestrt;
10826 /* if this is bitfield of size 1, see if we are checking the value
10827 * of a single bit in an if-statement,
10828 * if yes, then don't generate usual code, but execute the
10829 * genIfx directly -- VR */
10833 /* CHECK: if next iCode is IFX
10834 * and current result operand is nextic's conditional operand
10835 * and current result operand live ranges ends at nextic's key number
10837 if((nextic->op == IFX)
10838 && (result == IC_COND(nextic))
10839 && (OP_LIVETO(result) == nextic->seq)
10840 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10842 /* everything is ok then */
10843 /* find a way to optimize the genIfx iCode */
10845 bytestrt = SPEC_BSTR(operandType(result))/8;
10846 bitstrt = SPEC_BSTR(operandType(result))%8;
10848 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10850 genIfxpCOpJump(nextic, jop);
10852 pic16_freeAsmop(left, NULL, ic, TRUE);
10853 pic16_freeAsmop(result, NULL, ic, TRUE);
10859 /* if bitfield then unpack the bits */
10860 if (IS_BITFIELD(letype))
10861 genUnpackBits (result, left, NULL, POINTER);
10863 /* we have can just get the values */
10864 int size = AOP_SIZE(result);
10867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10869 pic16_loadFSR0( left, 0 );
10873 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10874 pic16_popGet(AOP(result), offset++)));
10876 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10877 pic16_popGet(AOP(result), offset++)));
10883 /* now some housekeeping stuff */
10885 /* we had to allocate for this iCode */
10886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10887 pic16_freeAsmop(NULL,aop,ic,TRUE);
10889 /* we did not allocate which means left
10890 * already in a pointer register, then
10891 * if size > 0 && this could be used again
10892 * we have to point it back to where it
10894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10895 if (AOP_SIZE(result) > 1
10896 && !OP_SYMBOL(left)->remat
10897 && ( OP_SYMBOL(left)->liveTo > ic->seq
10899 // int size = AOP_SIZE(result) - 1;
10901 // pic16_emitcode("dec","%s",rname);
10907 pic16_freeAsmop(left,NULL,ic,TRUE);
10908 pic16_freeAsmop(result,NULL,ic,TRUE);
10911 /*-----------------------------------------------------------------*/
10912 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10913 /*-----------------------------------------------------------------*/
10914 static void genPagedPointerGet (operand *left,
10919 regs *preg = NULL ;
10921 sym_link *rtype, *retype;
10923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10925 rtype = operandType(result);
10926 retype= getSpec(rtype);
10928 pic16_aopOp(left,ic,FALSE);
10930 /* if the value is already in a pointer register
10931 then don't need anything more */
10932 if (!AOP_INPREG(AOP(left))) {
10933 /* otherwise get a free pointer register */
10935 preg = getFreePtr(ic,&aop,FALSE);
10936 pic16_emitcode("mov","%s,%s",
10938 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10939 rname = preg->name ;
10941 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10943 pic16_freeAsmop(left,NULL,ic,TRUE);
10944 pic16_aopOp (result,ic,TRUE);
10946 /* if bitfield then unpack the bits */
10947 if (IS_BITFIELD(retype))
10948 genUnpackBits (result,left,rname,PPOINTER);
10950 /* we have can just get the values */
10951 int size = AOP_SIZE(result);
10956 pic16_emitcode("movx","a,@%s",rname);
10957 pic16_aopPut(AOP(result),"a",offset);
10962 pic16_emitcode("inc","%s",rname);
10966 /* now some housekeeping stuff */
10968 /* we had to allocate for this iCode */
10969 pic16_freeAsmop(NULL,aop,ic,TRUE);
10971 /* we did not allocate which means left
10972 already in a pointer register, then
10973 if size > 0 && this could be used again
10974 we have to point it back to where it
10976 if (AOP_SIZE(result) > 1 &&
10977 !OP_SYMBOL(left)->remat &&
10978 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10980 int size = AOP_SIZE(result) - 1;
10982 pic16_emitcode("dec","%s",rname);
10987 pic16_freeAsmop(result,NULL,ic,TRUE);
10993 /* This code is not adjusted to PIC16 and fails utterly.
10994 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10996 /*-----------------------------------------------------------------*/
10997 /* genFarPointerGet - gget value from far space */
10998 /*-----------------------------------------------------------------*/
10999 static void genFarPointerGet (operand *left,
11000 operand *result, iCode *ic)
11003 sym_link *retype = getSpec(operandType(result));
11005 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11007 pic16_aopOp(left,ic,FALSE);
11009 /* if the operand is already in dptr
11010 then we do nothing else we move the value to dptr */
11011 if (AOP_TYPE(left) != AOP_STR) {
11012 /* if this is remateriazable */
11013 if (AOP_TYPE(left) == AOP_IMMD)
11014 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11015 else { /* we need to get it byte by byte */
11016 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11017 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11018 if (options.model == MODEL_FLAT24)
11020 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11024 /* so dptr know contains the address */
11025 pic16_freeAsmop(left,NULL,ic,TRUE);
11026 pic16_aopOp(result,ic,TRUE);
11028 /* if bit then unpack */
11029 if (IS_BITFIELD(retype))
11030 genUnpackBits(result,left,"dptr",FPOINTER);
11032 size = AOP_SIZE(result);
11036 pic16_emitcode("movx","a,@dptr");
11037 pic16_aopPut(AOP(result),"a",offset++);
11039 pic16_emitcode("inc","dptr");
11043 pic16_freeAsmop(result,NULL,ic,TRUE);
11048 /*-----------------------------------------------------------------*/
11049 /* genCodePointerGet - get value from code space */
11050 /*-----------------------------------------------------------------*/
11051 static void genCodePointerGet (operand *left,
11052 operand *result, iCode *ic)
11055 sym_link *retype = getSpec(operandType(result));
11057 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11059 pic16_aopOp(left,ic,FALSE);
11061 /* if the operand is already in dptr
11062 then we do nothing else we move the value to dptr */
11063 if (AOP_TYPE(left) != AOP_STR) {
11064 /* if this is remateriazable */
11065 if (AOP_TYPE(left) == AOP_IMMD)
11066 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11067 else { /* we need to get it byte by byte */
11068 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11069 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11070 if (options.model == MODEL_FLAT24)
11072 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11076 /* so dptr know contains the address */
11077 pic16_freeAsmop(left,NULL,ic,TRUE);
11078 pic16_aopOp(result,ic,FALSE);
11080 /* if bit then unpack */
11081 if (IS_BITFIELD(retype))
11082 genUnpackBits(result,left,"dptr",CPOINTER);
11084 size = AOP_SIZE(result);
11088 pic16_emitcode("clr","a");
11089 pic16_emitcode("movc","a,@a+dptr");
11090 pic16_aopPut(AOP(result),"a",offset++);
11092 pic16_emitcode("inc","dptr");
11096 pic16_freeAsmop(result,NULL,ic,TRUE);
11101 /*-----------------------------------------------------------------*/
11102 /* genGenPointerGet - gget value from generic pointer space */
11103 /*-----------------------------------------------------------------*/
11104 static void genGenPointerGet (operand *left,
11105 operand *result, iCode *ic)
11107 int size, offset, lit;
11108 sym_link *retype = getSpec(operandType(result));
11110 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11111 pic16_aopOp(left,ic,FALSE);
11112 pic16_aopOp(result,ic,FALSE);
11113 size = AOP_SIZE(result);
11115 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11117 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11119 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11120 // load FSR0 from immediate
11121 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11123 // pic16_loadFSR0( left );
11128 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11130 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11137 else { /* we need to get it byte by byte */
11138 // set up FSR0 with address from left
11139 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11140 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11146 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11148 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11155 /* if bit then unpack */
11156 if (IS_BITFIELD(retype))
11157 genUnpackBits(result,left,"BAD",GPOINTER);
11160 pic16_freeAsmop(left,NULL,ic,TRUE);
11161 pic16_freeAsmop(result,NULL,ic,TRUE);
11167 /*-----------------------------------------------------------------*/
11168 /* genGenPointerGet - gget value from generic pointer space */
11169 /*-----------------------------------------------------------------*/
11170 static void genGenPointerGet (operand *left,
11171 operand *result, iCode *ic)
11173 int size, offset, lit;
11174 sym_link *letype = getSpec(operandType(left));
11176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11177 pic16_aopOp(left,ic,FALSE);
11178 pic16_aopOp(result,ic,TRUE);
11179 size = AOP_SIZE(result);
11181 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11183 /* if bit then unpack */
11184 if (IS_BITFIELD(letype)) {
11185 genUnpackBits(result,left,"BAD",GPOINTER);
11189 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11191 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11192 // load FSR0 from immediate
11193 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11195 werror(W_POSSBUG2, __FILE__, __LINE__);
11200 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11202 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11209 } else { /* we need to get it byte by byte */
11211 /* set up WREG:PRODL:FSR0L with address from left */
11212 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11213 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11214 pic16_mov2w(AOP(left), 2);
11215 pic16_callGenericPointerRW(0, size);
11217 assignResultValue(result, 1);
11223 pic16_freeAsmop(left,NULL,ic,TRUE);
11224 pic16_freeAsmop(result,NULL,ic,TRUE);
11227 /*-----------------------------------------------------------------*/
11228 /* genConstPointerGet - get value from const generic pointer space */
11229 /*-----------------------------------------------------------------*/
11230 static void genConstPointerGet (operand *left,
11231 operand *result, iCode *ic)
11233 //sym_link *retype = getSpec(operandType(result));
11234 // symbol *albl = newiTempLabel(NULL); // patch 15
11235 // symbol *blbl = newiTempLabel(NULL); //
11236 // PIC_OPCODE poc; // patch 15
11240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11241 pic16_aopOp(left,ic,FALSE);
11242 pic16_aopOp(result,ic,TRUE);
11243 size = AOP_SIZE(result);
11245 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11247 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11249 // set up table pointer
11250 if( (AOP_TYPE(left) == AOP_PCODE)
11251 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11252 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11254 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11255 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11256 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11257 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11258 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11261 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11262 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11263 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11267 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11272 pic16_freeAsmop(left,NULL,ic,TRUE);
11273 pic16_freeAsmop(result,NULL,ic,TRUE);
11277 /*-----------------------------------------------------------------*/
11278 /* genPointerGet - generate code for pointer get */
11279 /*-----------------------------------------------------------------*/
11280 static void genPointerGet (iCode *ic)
11282 operand *left, *result ;
11283 sym_link *type, *etype;
11288 left = IC_LEFT(ic);
11289 result = IC_RESULT(ic) ;
11291 /* depending on the type of pointer we need to
11292 move it to the correct pointer register */
11293 type = operandType(left);
11294 etype = getSpec(type);
11297 if (IS_PTR_CONST(type))
11299 if (IS_CODEPTR(type))
11301 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11303 /* if left is of type of pointer then it is simple */
11304 if (IS_PTR(type) && !IS_FUNC(type->next))
11305 p_type = DCL_TYPE(type);
11307 /* we have to go by the storage class */
11308 p_type = PTR_TYPE(SPEC_OCLS(etype));
11310 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11312 if (SPEC_OCLS(etype)->codesp ) {
11313 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11314 //p_type = CPOINTER ;
11316 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11317 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11318 /*p_type = FPOINTER ;*/
11320 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11321 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11322 /* p_type = PPOINTER; */
11324 if (SPEC_OCLS(etype) == idata ) {
11325 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11326 /* p_type = IPOINTER; */
11328 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11329 /* p_type = POINTER ; */
11333 /* now that we have the pointer type we assign
11334 the pointer values */
11339 genNearPointerGet (left,result,ic);
11343 genPagedPointerGet(left,result,ic);
11347 /* PICs do not support FAR pointers... */
11348 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11350 genFarPointerGet (left,result,ic);
11355 genConstPointerGet (left,result,ic);
11356 //pic16_emitcodePointerGet (left,result,ic);
11361 if (IS_PTR_CONST(type))
11362 genConstPointerGet (left,result,ic);
11365 genGenPointerGet (left,result,ic);
11369 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11370 "genPointerGet: illegal pointer type");
11375 /*-----------------------------------------------------------------*/
11376 /* genPackBits - generates code for packed bit storage */
11377 /*-----------------------------------------------------------------*/
11378 static void genPackBits (sym_link *etype , operand *result,
11380 char *rname, int p_type)
11386 int shifted_and_masked = 0;
11387 unsigned long lit = (unsigned long)-1;
11390 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11391 blen = SPEC_BLEN(etype);
11392 bstr = SPEC_BSTR(etype);
11394 retype = getSpec(operandType(right));
11396 if(AOP_TYPE(right) == AOP_LIT) {
11397 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11399 if((blen == 1) && (bstr < 8)) {
11400 /* it is a single bit, so use the appropriate bit instructions */
11402 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11404 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11405 /* workaround to reduce the extra lfsr instruction */
11407 pic16_emitpcode(POC_BSF,
11408 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11410 pic16_emitpcode(POC_BCF,
11411 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11414 if (PIC_IS_DATA_PTR(operandType(result))) {
11415 pic16_loadFSR0(result, 0);
11416 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11417 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11419 /* get old value */
11420 pic16_derefPtr (result, p_type, 0, NULL);
11421 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11422 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11423 /* write back new value */
11424 pic16_derefPtr (result, p_type, 1, NULL);
11430 /* IORLW below is more efficient */
11431 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11432 lit = (lit & ((1UL << blen) - 1)) << bstr;
11433 shifted_and_masked = 1;
11436 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11437 && IS_BITFIELD(retype)
11438 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11442 rblen = SPEC_BLEN( retype );
11443 rbstr = SPEC_BSTR( retype );
11445 if(IS_BITFIELD(etype)) {
11446 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11447 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11449 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11452 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11454 if(IS_BITFIELD(etype)) {
11455 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11457 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11460 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11464 /* move right to W */
11465 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11468 /* if the bit length is less than or */
11469 /* it exactly fits a byte then */
11470 if((shCnt=SPEC_BSTR(etype))
11471 || SPEC_BLEN(etype) <= 8 ) {
11472 int fsr0_setup = 0;
11474 if (blen != 8 || bstr != 0) {
11475 // we need to combine the value with the old value
11476 if(!shifted_and_masked)
11478 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11480 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11481 SPEC_BSTR(etype), SPEC_BLEN(etype));
11483 /* shift left acc, do NOT mask the result again */
11486 /* using PRODH as a temporary register here */
11487 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11490 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11491 || IS_DIRECT(result)) {
11492 /* access symbol directly */
11493 pic16_mov2w (AOP(result), 0);
11495 /* get old value */
11496 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11499 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11500 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11501 (unsigned char)(0xff >> (8-bstr))) ));
11502 if (!shifted_and_masked) {
11503 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11505 /* We have the shifted and masked (literal) right value in `lit' */
11507 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11509 } // if (blen != 8 || bstr != 0)
11511 /* write new value back */
11512 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11513 || IS_DIRECT(result)) {
11514 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11516 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11525 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11526 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11531 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11532 rLen = SPEC_BLEN(etype)-8;
11534 /* now generate for lengths greater than one byte */
11538 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11544 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11550 pic16_emitcode("movx","@dptr,a");
11555 DEBUGpic16_emitcode(";lcall","__gptrput");
11563 pic16_mov2w(AOP(right), offset++);
11566 /* last last was not complete */
11568 /* save the byte & read byte */
11571 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11572 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11577 pic16_emitcode ("mov","b,a");
11578 pic16_emitcode("movx","a,@dptr");
11582 pic16_emitcode ("push","b");
11583 pic16_emitcode ("push","acc");
11584 pic16_emitcode ("lcall","__gptrget");
11585 pic16_emitcode ("pop","b");
11591 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11592 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11593 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11594 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11595 // pic16_emitcode ("orl","a,b");
11598 // if (p_type == GPOINTER)
11599 // pic16_emitcode("pop","b");
11604 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11605 // pic16_emitcode("mov","@%s,a",rname);
11609 pic16_emitcode("movx","@dptr,a");
11613 DEBUGpic16_emitcode(";lcall","__gptrput");
11620 // pic16_freeAsmop(right, NULL, ic, TRUE);
11623 /*-----------------------------------------------------------------*/
11624 /* genDataPointerSet - remat pointer to data space */
11625 /*-----------------------------------------------------------------*/
11626 static void genDataPointerSet(operand *right,
11630 int size, offset = 0, resoffset=0 ;
11632 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11633 pic16_aopOp(right,ic,FALSE);
11635 size = AOP_SIZE(right);
11637 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11640 if ( AOP_TYPE(result) == AOP_PCODE) {
11641 fprintf(stderr,"genDataPointerSet %s, %d\n",
11642 AOP(result)->aopu.pcop->name,
11643 (AOP(result)->aopu.pcop->type == PO_DIR)?
11644 PCOR(AOP(result)->aopu.pcop)->instance:
11645 PCOI(AOP(result)->aopu.pcop)->offset);
11649 if(AOP(result)->aopu.pcop->type == PO_DIR)
11650 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11653 if (AOP_TYPE(right) == AOP_LIT) {
11656 if(!IS_FLOAT(operandType( right )))
11657 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11660 unsigned long lit_int;
11664 /* take care if literal is a float */
11665 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11666 lit = info.lit_int;
11668 lit = lit >> (8*offset);
11669 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11671 pic16_mov2w(AOP(right), offset);
11672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11678 pic16_freeAsmop(right,NULL,ic,TRUE);
11683 /*-----------------------------------------------------------------*/
11684 /* genNearPointerSet - pic16_emitcode for near pointer put */
11685 /*-----------------------------------------------------------------*/
11686 static void genNearPointerSet (operand *right,
11692 sym_link *ptype = operandType(result);
11693 sym_link *resetype;
11695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11696 retype= getSpec(operandType(right));
11697 resetype = getSpec(operandType(result));
11699 pic16_aopOp(result,ic,FALSE);
11701 /* if the result is rematerializable &
11702 * in data space & not a bit variable */
11704 /* and result is not a bit variable */
11705 if (AOP_TYPE(result) == AOP_PCODE
11706 // && AOP_TYPE(result) == AOP_IMMD
11707 && DCL_TYPE(ptype) == POINTER
11708 && !IS_BITFIELD(retype)
11709 && !IS_BITFIELD(resetype)) {
11711 genDataPointerSet (right,result,ic);
11712 pic16_freeAsmop(result,NULL,ic,TRUE);
11716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11717 pic16_aopOp(right,ic,FALSE);
11718 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11720 /* if bitfield then unpack the bits */
11721 if (IS_BITFIELD(resetype)) {
11722 genPackBits (resetype, result, right, NULL, POINTER);
11724 /* we have can just get the values */
11725 int size = AOP_SIZE(right);
11728 pic16_loadFSR0(result, 0);
11730 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11732 if (AOP_TYPE(right) == AOP_LIT) {
11733 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11735 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11737 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11739 } else { // no literal
11741 pic16_emitpcode(POC_MOVFF,
11742 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11743 pic16_popCopyReg(&pic16_pc_postinc0)));
11745 pic16_emitpcode(POC_MOVFF,
11746 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11747 pic16_popCopyReg(&pic16_pc_indf0)));
11755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11756 /* now some housekeeping stuff */
11758 /* we had to allocate for this iCode */
11759 pic16_freeAsmop(NULL,aop,ic,TRUE);
11761 /* we did not allocate which means left
11762 * already in a pointer register, then
11763 * if size > 0 && this could be used again
11764 * we have to point it back to where it
11766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11767 if (AOP_SIZE(right) > 1
11768 && !OP_SYMBOL(result)->remat
11769 && ( OP_SYMBOL(result)->liveTo > ic->seq
11772 int size = AOP_SIZE(right) - 1;
11775 pic16_emitcode("decf","fsr0,f");
11776 //pic16_emitcode("dec","%s",rname);
11780 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11783 pic16_freeAsmop(right,NULL,ic,TRUE);
11784 pic16_freeAsmop(result,NULL,ic,TRUE);
11787 /*-----------------------------------------------------------------*/
11788 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11789 /*-----------------------------------------------------------------*/
11790 static void genPagedPointerSet (operand *right,
11795 regs *preg = NULL ;
11799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11801 retype= getSpec(operandType(right));
11803 pic16_aopOp(result,ic,FALSE);
11805 /* if the value is already in a pointer register
11806 then don't need anything more */
11807 if (!AOP_INPREG(AOP(result))) {
11808 /* otherwise get a free pointer register */
11810 preg = getFreePtr(ic,&aop,FALSE);
11811 pic16_emitcode("mov","%s,%s",
11813 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11814 rname = preg->name ;
11816 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11818 pic16_freeAsmop(result,NULL,ic,TRUE);
11819 pic16_aopOp (right,ic,FALSE);
11821 /* if bitfield then unpack the bits */
11822 if (IS_BITFIELD(retype))
11823 genPackBits (retype,result,right,rname,PPOINTER);
11825 /* we have can just get the values */
11826 int size = AOP_SIZE(right);
11830 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11833 pic16_emitcode("movx","@%s,a",rname);
11836 pic16_emitcode("inc","%s",rname);
11842 /* now some housekeeping stuff */
11844 /* we had to allocate for this iCode */
11845 pic16_freeAsmop(NULL,aop,ic,TRUE);
11847 /* we did not allocate which means left
11848 already in a pointer register, then
11849 if size > 0 && this could be used again
11850 we have to point it back to where it
11852 if (AOP_SIZE(right) > 1 &&
11853 !OP_SYMBOL(result)->remat &&
11854 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11856 int size = AOP_SIZE(right) - 1;
11858 pic16_emitcode("dec","%s",rname);
11863 pic16_freeAsmop(right,NULL,ic,TRUE);
11869 /* This code is not adjusted to PIC16 and fails utterly...
11870 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11872 /*-----------------------------------------------------------------*/
11873 /* genFarPointerSet - set value from far space */
11874 /*-----------------------------------------------------------------*/
11875 static void genFarPointerSet (operand *right,
11876 operand *result, iCode *ic)
11879 sym_link *retype = getSpec(operandType(right));
11881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11882 pic16_aopOp(result,ic,FALSE);
11884 /* if the operand is already in dptr
11885 then we do nothing else we move the value to dptr */
11886 if (AOP_TYPE(result) != AOP_STR) {
11887 /* if this is remateriazable */
11888 if (AOP_TYPE(result) == AOP_IMMD)
11889 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11890 else { /* we need to get it byte by byte */
11891 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11892 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11893 if (options.model == MODEL_FLAT24)
11895 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11899 /* so dptr know contains the address */
11900 pic16_freeAsmop(result,NULL,ic,TRUE);
11901 pic16_aopOp(right,ic,FALSE);
11903 /* if bit then unpack */
11904 if (IS_BITFIELD(retype))
11905 genPackBits(retype,result,right,"dptr",FPOINTER);
11907 size = AOP_SIZE(right);
11911 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11913 pic16_emitcode("movx","@dptr,a");
11915 pic16_emitcode("inc","dptr");
11919 pic16_freeAsmop(right,NULL,ic,TRUE);
11923 /*-----------------------------------------------------------------*/
11924 /* genGenPointerSet - set value from generic pointer space */
11925 /*-----------------------------------------------------------------*/
11927 static void genGenPointerSet (operand *right,
11928 operand *result, iCode *ic)
11930 int i, size, offset, lit;
11931 sym_link *retype = getSpec(operandType(right));
11933 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11935 pic16_aopOp(result,ic,FALSE);
11936 pic16_aopOp(right,ic,FALSE);
11937 size = AOP_SIZE(right);
11940 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11942 /* if the operand is already in dptr
11943 then we do nothing else we move the value to dptr */
11944 if (AOP_TYPE(result) != AOP_STR) {
11945 /* if this is remateriazable */
11946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11947 // WARNING: anythig until "else" is untested!
11948 if (AOP_TYPE(result) == AOP_IMMD) {
11949 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11950 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11951 // load FSR0 from immediate
11952 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11956 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11958 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11964 else { /* we need to get it byte by byte */
11965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11966 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11968 // set up FSR0 with address of result
11969 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11970 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11972 /* hack hack! see if this the FSR. If so don't load W */
11973 if(AOP_TYPE(right) != AOP_ACC) {
11975 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11977 if(AOP_TYPE(right) == AOP_LIT)
11980 // note: pic16_popGet handles sign extension
11981 for(i=0;i<size;i++) {
11982 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11984 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11986 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11991 for(i=0;i<size;i++) {
11993 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11994 pic16_popCopyReg(&pic16_pc_postinc0)));
11996 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11997 pic16_popCopyReg(&pic16_pc_indf0)));
12003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12004 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12006 } // if (AOP_TYPE(result) != AOP_IMMD)
12008 } // if (AOP_TYPE(result) != AOP_STR)
12009 /* so dptr know contains the address */
12012 /* if bit then unpack */
12013 if (IS_BITFIELD(retype))
12014 genPackBits(retype,result,right,"dptr",GPOINTER);
12016 size = AOP_SIZE(right);
12019 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12021 // set up FSR0 with address of result
12022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12026 if (AOP_TYPE(right) == AOP_LIT) {
12027 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12029 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12031 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12033 } else { // no literal
12035 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12037 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12045 pic16_freeAsmop(right,NULL,ic,TRUE);
12046 pic16_freeAsmop(result,NULL,ic,TRUE);
12050 static void genGenPointerSet (operand *right,
12051 operand *result, iCode *ic)
12054 sym_link *retype = getSpec(operandType(result));
12056 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12058 pic16_aopOp(result,ic,FALSE);
12059 pic16_aopOp(right,ic,FALSE);
12060 size = AOP_SIZE(right);
12062 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12065 /* if bit then unpack */
12066 if (IS_BITFIELD(retype)) {
12067 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12068 genPackBits(retype,result,right,"dptr",GPOINTER);
12072 size = AOP_SIZE(right);
12074 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12077 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12079 /* value of right+0 is placed on stack, which will be retrieved
12080 * by the support function thus restoring the stack. The important
12081 * thing is that there is no need to manually restore stack pointer
12083 pushaop(AOP(right), 0);
12084 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12085 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12086 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12087 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12089 /* load address to write to in WREG:FSR0H:FSR0L */
12090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12091 pic16_popCopyReg(&pic16_pc_fsr0l)));
12092 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12093 pic16_popCopyReg(&pic16_pc_prodl)));
12094 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12096 pic16_callGenericPointerRW(1, size);
12099 pic16_freeAsmop(right,NULL,ic,TRUE);
12100 pic16_freeAsmop(result,NULL,ic,TRUE);
12103 /*-----------------------------------------------------------------*/
12104 /* genPointerSet - stores the value into a pointer location */
12105 /*-----------------------------------------------------------------*/
12106 static void genPointerSet (iCode *ic)
12108 operand *right, *result ;
12109 sym_link *type, *etype;
12114 right = IC_RIGHT(ic);
12115 result = IC_RESULT(ic) ;
12117 /* depending on the type of pointer we need to
12118 move it to the correct pointer register */
12119 type = operandType(result);
12120 etype = getSpec(type);
12122 /* if left is of type of pointer then it is simple */
12123 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12124 p_type = DCL_TYPE(type);
12127 /* we have to go by the storage class */
12128 p_type = PTR_TYPE(SPEC_OCLS(etype));
12130 /* if (SPEC_OCLS(etype)->codesp ) { */
12131 /* p_type = CPOINTER ; */
12134 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12135 /* p_type = FPOINTER ; */
12137 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12138 /* p_type = PPOINTER ; */
12140 /* if (SPEC_OCLS(etype) == idata ) */
12141 /* p_type = IPOINTER ; */
12143 /* p_type = POINTER ; */
12146 /* now that we have the pointer type we assign
12147 the pointer values */
12152 genNearPointerSet (right,result,ic);
12156 genPagedPointerSet (right,result,ic);
12160 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12162 genFarPointerSet (right,result,ic);
12167 genGenPointerSet (right,result,ic);
12171 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12172 "genPointerSet: illegal pointer type");
12176 /*-----------------------------------------------------------------*/
12177 /* genIfx - generate code for Ifx statement */
12178 /*-----------------------------------------------------------------*/
12179 static void genIfx (iCode *ic, iCode *popIc)
12181 operand *cond = IC_COND(ic);
12186 pic16_aopOp(cond,ic,FALSE);
12188 /* get the value into acc */
12189 if (AOP_TYPE(cond) != AOP_CRY)
12190 pic16_toBoolean(cond);
12193 /* the result is now in the accumulator */
12194 pic16_freeAsmop(cond,NULL,ic,TRUE);
12196 /* if there was something to be popped then do it */
12200 /* if the condition is a bit variable */
12201 if (isbit && IS_ITEMP(cond) &&
12203 genIfxJump(ic,"c");
12204 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12206 if (isbit && !IS_ITEMP(cond))
12207 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12209 genIfxJump(ic,"a");
12214 /*-----------------------------------------------------------------*/
12215 /* genAddrOf - generates code for address of */
12216 /*-----------------------------------------------------------------*/
12217 static void genAddrOf (iCode *ic)
12219 operand *result, *left;
12221 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12222 pCodeOp *pcop0, *pcop1, *pcop2;
12226 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12228 sym = OP_SYMBOL( IC_LEFT(ic) );
12231 /* get address of symbol on stack */
12232 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12234 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12235 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12238 // operands on stack are accessible via "FSR2 + index" with index
12239 // starting at 2 for arguments and growing from 0 downwards for
12240 // local variables (index == 0 is not assigned so we add one here)
12242 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12245 assert (soffs < 0);
12249 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12250 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12251 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12252 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12253 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12254 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12255 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12261 // if(pic16_debug_verbose) {
12262 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12263 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12266 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12267 size = AOP_SIZE(IC_RESULT(ic));
12269 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12270 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12271 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12274 pic16_emitpcode(POC_MOVLW, pcop0);
12275 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12276 pic16_emitpcode(POC_MOVLW, pcop1);
12277 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12278 pic16_emitpcode(POC_MOVLW, pcop2);
12279 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12282 pic16_emitpcode(POC_MOVLW, pcop0);
12283 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12284 pic16_emitpcode(POC_MOVLW, pcop1);
12285 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12287 pic16_emitpcode(POC_MOVLW, pcop0);
12288 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12291 pic16_freeAsmop(left, NULL, ic, FALSE);
12293 pic16_freeAsmop(result,NULL,ic,TRUE);
12298 /*-----------------------------------------------------------------*/
12299 /* genFarFarAssign - assignment when both are in far space */
12300 /*-----------------------------------------------------------------*/
12301 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12303 int size = AOP_SIZE(right);
12306 /* first push the right side on to the stack */
12308 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12310 pic16_emitcode ("push","acc");
12313 pic16_freeAsmop(right,NULL,ic,FALSE);
12314 /* now assign DPTR to result */
12315 pic16_aopOp(result,ic,FALSE);
12316 size = AOP_SIZE(result);
12318 pic16_emitcode ("pop","acc");
12319 pic16_aopPut(AOP(result),"a",--offset);
12321 pic16_freeAsmop(result,NULL,ic,FALSE);
12326 /*-----------------------------------------------------------------*/
12327 /* genAssign - generate code for assignment */
12328 /*-----------------------------------------------------------------*/
12329 static void genAssign (iCode *ic)
12331 operand *result, *right;
12332 sym_link *restype, *rtype;
12333 int size, offset,know_W;
12334 unsigned long lit = 0L;
12336 result = IC_RESULT(ic);
12337 right = IC_RIGHT(ic) ;
12341 /* if they are the same */
12342 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12345 /* reversed order operands are aopOp'ed so that result operand
12346 * is effective in case right is a stack symbol. This maneauver
12347 * allows to use the _G.resDirect flag later */
12348 pic16_aopOp(result,ic,TRUE);
12349 pic16_aopOp(right,ic,FALSE);
12351 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12353 /* if they are the same registers */
12354 if (pic16_sameRegs(AOP(right),AOP(result)))
12357 /* if the result is a bit */
12358 if (AOP_TYPE(result) == AOP_CRY) {
12359 /* if the right size is a literal then
12360 we know what the value is */
12361 if (AOP_TYPE(right) == AOP_LIT) {
12363 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12364 pic16_popGet(AOP(result),0));
12366 if (((int) operandLitValue(right)))
12367 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12368 AOP(result)->aopu.aop_dir,
12369 AOP(result)->aopu.aop_dir);
12371 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12372 AOP(result)->aopu.aop_dir,
12373 AOP(result)->aopu.aop_dir);
12378 /* the right is also a bit variable */
12379 if (AOP_TYPE(right) == AOP_CRY) {
12380 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12381 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12382 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12387 /* we need to or */
12388 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12389 pic16_toBoolean(right);
12391 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12392 //pic16_aopPut(AOP(result),"a",0);
12396 /* bit variables done */
12398 size = AOP_SIZE(result);
12401 /* bit variables done */
12403 size = AOP_SIZE(result);
12404 restype = operandType(result);
12405 rtype = operandType(right);
12408 if(AOP_TYPE(right) == AOP_LIT) {
12409 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12411 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12413 /* patch tag for literals that are cast to pointers */
12414 if (IS_CODEPTR(restype)) {
12415 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12416 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12418 if (IS_GENPTR(restype))
12420 if (IS_CODEPTR(rtype)) {
12421 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12422 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12423 } else if (PIC_IS_DATA_PTR(rtype)) {
12424 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12425 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12426 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12427 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12428 } else if (IS_PTR(rtype)) {
12429 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12430 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12436 unsigned long lit_int;
12441 if(IS_FIXED16X16(operandType(right))) {
12442 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12444 /* take care if literal is a float */
12445 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12446 lit = info.lit_int;
12451 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12452 // sizeof(unsigned long int), sizeof(float));
12455 if (AOP_TYPE(right) == AOP_REG) {
12456 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12458 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12463 /* when do we have to read the program memory?
12464 * - if right itself is a symbol in code space
12465 * (we don't care what it points to if it's a pointer)
12466 * - AND right is not a function (we would want its address)
12468 if(AOP_TYPE(right) != AOP_LIT
12469 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12470 && !IS_FUNC(OP_SYM_TYPE(right))
12471 && !IS_ITEMP(right)) {
12473 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12474 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12476 // set up table pointer
12477 if(is_LitOp(right)) {
12478 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12479 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12480 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12481 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12482 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12483 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12484 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12486 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12487 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12488 pic16_popCopyReg(&pic16_pc_tblptrl)));
12489 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12490 pic16_popCopyReg(&pic16_pc_tblptrh)));
12491 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12492 pic16_popCopyReg(&pic16_pc_tblptru)));
12495 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12496 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12498 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12499 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12500 pic16_popGet(AOP(result),offset)));
12504 /* FIXME: for pointers we need to extend differently (according
12505 * to pointer type DATA/CODE/EEPROM/... :*/
12506 size = getSize(OP_SYM_TYPE(right));
12507 if(AOP_SIZE(result) > size) {
12508 size = AOP_SIZE(result) - size;
12510 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12518 /* VR - What is this?! */
12519 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12522 if(aopIdx(AOP(result),0) == 4) {
12523 /* this is a workaround to save value of right into wreg too,
12524 * value of wreg is going to be used later */
12525 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12526 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12531 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12537 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12538 if(AOP_TYPE(right) == AOP_LIT) {
12540 if(know_W != (lit&0xff))
12541 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12543 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12545 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12549 } else if (AOP_TYPE(right) == AOP_CRY) {
12550 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12552 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12553 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12554 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12556 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12557 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12558 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12560 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12562 if(!_G.resDirect) { /* use this aopForSym feature */
12563 if(AOP_TYPE(result) == AOP_ACC) {
12564 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12566 if(AOP_TYPE(right) == AOP_ACC) {
12567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12569 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12578 pic16_freeAsmop (right,NULL,ic,FALSE);
12579 pic16_freeAsmop (result,NULL,ic,TRUE);
12582 /*-----------------------------------------------------------------*/
12583 /* genJumpTab - generates code for jump table */
12584 /*-----------------------------------------------------------------*/
12585 static void genJumpTab (iCode *ic)
12590 pCodeOp *jt_offs_hi;
12595 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12596 /* get the condition into accumulator */
12597 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12599 /* multiply by three */
12600 pic16_emitcode("add","a,acc");
12601 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12603 jtab = newiTempLabel(NULL);
12604 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12605 pic16_emitcode("jmp","@a+dptr");
12606 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12609 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12610 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12612 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12613 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12614 pic16_emitpLabel(jtab->key);
12618 jt_offs = pic16_popGetTempReg(0);
12619 jt_offs_hi = pic16_popGetTempReg(1);
12620 jt_label = pic16_popGetLabel (jtab->key);
12621 //fprintf (stderr, "Creating jump table...\n");
12623 // calculate offset into jump table (idx * sizeof (GOTO))
12624 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12625 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12626 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12627 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12628 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12629 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12630 pic16_emitpcode(POC_MOVWF , jt_offs);
12632 // prepare PCLATx (set to first entry in jump table)
12633 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12634 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12635 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12636 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12637 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12639 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12640 pic16_emitpcode(POC_ADDWF , jt_offs);
12641 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12642 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12644 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12646 // release temporaries and prepare jump into table (new PCL --> WREG)
12647 pic16_emitpcode(POC_MOVFW , jt_offs);
12648 pic16_popReleaseTempReg (jt_offs_hi, 1);
12649 pic16_popReleaseTempReg (jt_offs, 0);
12651 // jump into the table
12652 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12654 pic16_emitpLabelFORCE(jtab->key);
12657 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12658 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12660 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12661 /* now generate the jump labels */
12662 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12663 jtab = setNextItem(IC_JTLABELS(ic))) {
12664 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12665 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12668 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12672 /*-----------------------------------------------------------------*/
12673 /* genMixedOperation - gen code for operators between mixed types */
12674 /*-----------------------------------------------------------------*/
12676 TSD - Written for the PIC port - but this unfortunately is buggy.
12677 This routine is good in that it is able to efficiently promote
12678 types to different (larger) sizes. Unfortunately, the temporary
12679 variables that are optimized out by this routine are sometimes
12680 used in other places. So until I know how to really parse the
12681 iCode tree, I'm going to not be using this routine :(.
12683 static int genMixedOperation (iCode *ic)
12686 operand *result = IC_RESULT(ic);
12687 sym_link *ctype = operandType(IC_LEFT(ic));
12688 operand *right = IC_RIGHT(ic);
12694 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12696 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12702 nextright = IC_RIGHT(nextic);
12703 nextleft = IC_LEFT(nextic);
12704 nextresult = IC_RESULT(nextic);
12706 pic16_aopOp(right,ic,FALSE);
12707 pic16_aopOp(result,ic,FALSE);
12708 pic16_aopOp(nextright, nextic, FALSE);
12709 pic16_aopOp(nextleft, nextic, FALSE);
12710 pic16_aopOp(nextresult, nextic, FALSE);
12712 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12714 operand *t = right;
12718 pic16_emitcode(";remove right +","");
12720 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12722 operand *t = right;
12726 pic16_emitcode(";remove left +","");
12730 big = AOP_SIZE(nextleft);
12731 small = AOP_SIZE(nextright);
12733 switch(nextic->op) {
12736 pic16_emitcode(";optimize a +","");
12737 /* if unsigned or not an integral type */
12738 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12739 pic16_emitcode(";add a bit to something","");
12742 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12744 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12745 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12746 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12748 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12756 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12757 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12758 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12761 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12763 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12764 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12765 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12766 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12767 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12770 pic16_emitcode("rlf","known_zero,w");
12777 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12778 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12779 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12781 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12791 pic16_freeAsmop(right,NULL,ic,TRUE);
12792 pic16_freeAsmop(result,NULL,ic,TRUE);
12793 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12794 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12796 nextic->generated = 1;
12803 /*-----------------------------------------------------------------*/
12804 /* genCast - gen code for casting */
12805 /*-----------------------------------------------------------------*/
12806 static void genCast (iCode *ic)
12808 operand *result = IC_RESULT(ic);
12809 sym_link *ctype = operandType(IC_LEFT(ic));
12810 sym_link *rtype = operandType(IC_RIGHT(ic));
12811 sym_link *restype = operandType(IC_RESULT(ic));
12812 operand *right = IC_RIGHT(ic);
12818 /* if they are equivalent then do nothing */
12819 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12822 pic16_aopOp(result,ic,FALSE);
12823 pic16_aopOp(right,ic,FALSE) ;
12825 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12828 /* if the result is a bit */
12829 if (AOP_TYPE(result) == AOP_CRY) {
12831 /* if the right size is a literal then
12832 * we know what the value is */
12833 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12835 if (AOP_TYPE(right) == AOP_LIT) {
12836 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12837 pic16_popGet(AOP(result),0));
12839 if (((int) operandLitValue(right)))
12840 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12841 AOP(result)->aopu.aop_dir,
12842 AOP(result)->aopu.aop_dir);
12844 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12845 AOP(result)->aopu.aop_dir,
12846 AOP(result)->aopu.aop_dir);
12850 /* the right is also a bit variable */
12851 if (AOP_TYPE(right) == AOP_CRY) {
12853 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12855 pic16_emitcode("clrc","");
12856 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12857 AOP(right)->aopu.aop_dir,
12858 AOP(right)->aopu.aop_dir);
12859 pic16_aopPut(AOP(result),"c",0);
12863 /* we need to or */
12864 if (AOP_TYPE(right) == AOP_REG) {
12865 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12866 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12867 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12869 pic16_toBoolean(right);
12870 pic16_aopPut(AOP(result),"a",0);
12874 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12877 size = AOP_SIZE(result);
12879 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12881 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12882 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12883 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12886 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12891 if(IS_BITFIELD(getSpec(restype))
12892 && IS_BITFIELD(getSpec(rtype))) {
12893 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12896 /* port from pic14 to cope with generic pointers */
12897 if (PIC_IS_TAGGED(restype))
12899 operand *result = IC_RESULT(ic);
12900 //operand *left = IC_LEFT(ic);
12901 operand *right = IC_RIGHT(ic);
12904 /* copy common part */
12905 int max, size = AOP_SIZE(result);
12906 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12907 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12912 pic16_mov2w (AOP(right), size);
12913 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12916 /* upcast into generic pointer type? */
12917 if (IS_GENPTR(restype)
12918 && !PIC_IS_TAGGED(rtype)
12919 && (AOP_SIZE(result) > max))
12921 /* determine appropriate tag for right */
12922 if (PIC_IS_DATA_PTR(rtype))
12923 tag = GPTR_TAG_DATA;
12924 else if (IS_CODEPTR(rtype))
12925 tag = GPTR_TAG_CODE;
12926 else if (PIC_IS_DATA_PTR(ctype)) {
12927 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12928 tag = GPTR_TAG_DATA;
12929 } else if (IS_CODEPTR(ctype)) {
12930 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12931 tag = GPTR_TAG_CODE;
12932 } else if (IS_PTR(rtype)) {
12933 PERFORM_ONCE(weirdcast,
12934 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12936 tag = GPTR_TAG_DATA;
12938 PERFORM_ONCE(weirdcast,
12939 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12941 tag = GPTR_TAG_DATA;
12944 assert (AOP_SIZE(result) == 3);
12945 /* zero-extend address... */
12946 for (size = max; size < AOP_SIZE(result)-1; size++)
12947 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12948 /* ...and add tag */
12949 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12950 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12951 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12952 for (size = max; size < AOP_SIZE(result)-1; size++)
12953 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12954 /* add __code tag */
12955 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12956 } else if (AOP_SIZE(result) > max) {
12957 /* extend non-pointers */
12958 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12959 pic16_addSign(result, max, 0);
12964 /* if they are the same size : or less */
12965 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12967 /* if they are in the same place */
12968 if (pic16_sameRegs(AOP(right),AOP(result)))
12971 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12973 if (IS_PTR_CONST(rtype))
12975 if (IS_CODEPTR(rtype))
12977 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12980 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12982 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12984 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12987 if(AOP_TYPE(right) == AOP_IMMD) {
12988 pCodeOp *pcop0, *pcop1, *pcop2;
12989 symbol *sym = OP_SYMBOL( right );
12991 size = AOP_SIZE(result);
12993 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12995 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12997 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13000 pic16_emitpcode(POC_MOVLW, pcop0);
13001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13002 pic16_emitpcode(POC_MOVLW, pcop1);
13003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13004 pic16_emitpcode(POC_MOVLW, pcop2);
13005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13008 pic16_emitpcode(POC_MOVLW, pcop0);
13009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13010 pic16_emitpcode(POC_MOVLW, pcop1);
13011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13013 pic16_emitpcode(POC_MOVLW, pcop0);
13014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13018 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13019 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13021 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13023 if(AOP_SIZE(result) <2)
13024 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13026 /* if they in different places then copy */
13027 size = AOP_SIZE(result);
13030 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13031 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13038 /* if the result is of type pointer */
13039 if (IS_PTR(ctype)) {
13041 sym_link *type = operandType(right);
13042 sym_link *etype = getSpec(type);
13044 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13046 /* pointer to generic pointer */
13047 if (IS_GENPTR(ctype)) {
13051 p_type = DCL_TYPE(type);
13053 /* we have to go by the storage class */
13054 p_type = PTR_TYPE(SPEC_OCLS(etype));
13056 /* if (SPEC_OCLS(etype)->codesp ) */
13057 /* p_type = CPOINTER ; */
13059 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13060 /* p_type = FPOINTER ; */
13062 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13063 /* p_type = PPOINTER; */
13065 /* if (SPEC_OCLS(etype) == idata ) */
13066 /* p_type = IPOINTER ; */
13068 /* p_type = POINTER ; */
13071 /* the first two bytes are known */
13072 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13073 size = GPTRSIZE - 1;
13076 if(offset < AOP_SIZE(right)) {
13077 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13078 pic16_mov2f(AOP(result), AOP(right), offset);
13080 if ((AOP_TYPE(right) == AOP_PCODE) &&
13081 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13082 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13083 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13086 pic16_aopPut(AOP(result),
13087 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13092 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13095 /* the last byte depending on type */
13100 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13104 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13108 pic16_emitcode(";BUG!? ","%d",__LINE__);
13113 if (GPTRSIZE > AOP_SIZE(right)) {
13114 // assume __data pointer... THIS MIGHT BE WRONG!
13115 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13117 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13122 /* this should never happen */
13123 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13124 "got unknown pointer type");
13127 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13133 /* just copy the pointers */
13134 size = AOP_SIZE(result);
13137 pic16_aopPut(AOP(result),
13138 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13147 /* so we now know that the size of destination is greater
13148 than the size of the source.
13149 Now, if the next iCode is an operator then we might be
13150 able to optimize the operation without performing a cast.
13152 if(genMixedOperation(ic))
13155 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13157 /* we move to result for the size of source */
13158 size = AOP_SIZE(right);
13163 pic16_mov2f(AOP(result), AOP(right), offset);
13167 /* now depending on the sign of the destination */
13168 size = AOP_SIZE(result) - AOP_SIZE(right);
13169 /* if unsigned or not an integral type */
13170 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13172 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13174 /* we need to extend the sign :( */
13177 /* Save one instruction of casting char to int */
13178 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13179 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13180 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13182 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13185 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13187 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13189 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13192 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13197 pic16_freeAsmop(right,NULL,ic,TRUE);
13198 pic16_freeAsmop(result,NULL,ic,TRUE);
13202 /*-----------------------------------------------------------------*/
13203 /* genDjnz - generate decrement & jump if not zero instrucion */
13204 /*-----------------------------------------------------------------*/
13205 static int genDjnz (iCode *ic, iCode *ifx)
13207 symbol *lbl, *lbl1;
13208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13213 /* if the if condition has a false label
13214 then we cannot save */
13218 /* if the minus is not of the form
13220 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13221 !IS_OP_LITERAL(IC_RIGHT(ic)))
13224 if (operandLitValue(IC_RIGHT(ic)) != 1)
13227 /* if the size of this greater than one then no
13229 if (getSize(operandType(IC_RESULT(ic))) > 1)
13232 /* otherwise we can save BIG */
13233 lbl = newiTempLabel(NULL);
13234 lbl1= newiTempLabel(NULL);
13236 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13238 if (IS_AOP_PREG(IC_RESULT(ic))) {
13239 pic16_emitcode("dec","%s",
13240 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13241 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13242 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13246 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13247 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13249 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13250 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13254 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13255 ifx->generated = 1;
13259 /*-----------------------------------------------------------------*/
13260 /* genReceive - generate code for a receive iCode */
13261 /*-----------------------------------------------------------------*/
13262 static void genReceive (iCode *ic)
13268 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13269 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13271 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13273 if (isOperandInFarSpace(IC_RESULT(ic))
13274 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13275 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13277 int size = getSize(operandType(IC_RESULT(ic)));
13278 int offset = pic16_fReturnSizePic - size;
13282 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13283 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13287 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13289 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13290 size = AOP_SIZE(IC_RESULT(ic));
13293 pic16_emitcode ("pop","acc");
13294 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13297 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13299 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13302 /* set pseudo stack pointer to where it should be - dw*/
13303 GpsuedoStkPtr = ic->parmBytes;
13305 /* setting GpsuedoStkPtr has side effects here: */
13306 assignResultValue(IC_RESULT(ic), 0);
13309 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13312 /*-----------------------------------------------------------------*/
13313 /* genDummyRead - generate code for dummy read of volatiles */
13314 /*-----------------------------------------------------------------*/
13316 genDummyRead (iCode * ic)
13322 if (op && IS_SYMOP(op)) {
13323 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13324 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13327 pic16_aopOp (op, ic, FALSE);
13328 for (i=0; i < AOP_SIZE(op); i++) {
13329 // may need to protect this from the peepholer -- this is not nice but works...
13330 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13331 pic16_mov2w (AOP(op),i);
13332 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13334 pic16_freeAsmop (op, NULL, ic, TRUE);
13336 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13340 /*-----------------------------------------------------------------*/
13341 /* genpic16Code - generate code for pic16 based controllers */
13342 /*-----------------------------------------------------------------*/
13344 * At this point, ralloc.c has gone through the iCode and attempted
13345 * to optimize in a way suitable for a PIC. Now we've got to generate
13346 * PIC instructions that correspond to the iCode.
13348 * Once the instructions are generated, we'll pass through both the
13349 * peep hole optimizer and the pCode optimizer.
13350 *-----------------------------------------------------------------*/
13352 void genpic16Code (iCode *lic)
13357 lineHead = lineCurr = NULL;
13359 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13360 pic16_addpBlock(pb);
13363 /* if debug information required */
13364 if (options.debug && currFunc) {
13366 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13371 for (ic = lic ; ic ; ic = ic->next ) {
13373 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13374 if ( cln != ic->lineno ) {
13375 if ( options.debug ) {
13376 debugFile->writeCLine (ic);
13379 if(!options.noCcodeInAsm) {
13380 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13381 printCLine(ic->filename, ic->lineno)));
13387 if(options.iCodeInAsm) {
13390 /* insert here code to print iCode as comment */
13391 l = Safe_strdup(printILine(ic));
13392 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13395 /* if the result is marked as
13396 * spilt and rematerializable or code for
13397 * this has already been generated then
13399 if (resultRemat(ic) || ic->generated )
13402 /* depending on the operation */
13421 /* IPOP happens only when trying to restore a
13422 * spilt live range, if there is an ifx statement
13423 * following this pop then the if statement might
13424 * be using some of the registers being popped which
13425 * would destroy the contents of the register so
13426 * we need to check for this condition and handle it */
13428 && ic->next->op == IFX
13429 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13430 genIfx (ic->next,ic);
13448 genEndFunction (ic);
13464 pic16_genPlus (ic) ;
13468 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13469 pic16_genMinus (ic);
13485 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13489 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13495 /* note these two are xlated by algebraic equivalence
13496 * during parsing SDCC.y */
13497 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13498 "got '>=' or '<=' shouldn't have come here");
13502 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13514 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13518 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13522 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13546 genRightShift (ic);
13549 case GET_VALUE_AT_ADDRESS:
13554 if (POINTER_SET(ic))
13581 addSet(&_G.sendSet,ic);
13584 case DUMMY_READ_VOLATILE:
13594 /* now we are ready to call the
13595 peep hole optimizer */
13596 if (!options.nopeep)
13597 peepHole (&lineHead);
13599 /* now do the actual printing */
13600 printLine (lineHead, codeOutFile);
13603 DFPRINTF((stderr,"printing pBlock\n\n"));
13604 pic16_printpBlock(stdout,pb);