1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10 Bug Fixes - Raphael Neider <rneider AT web.de> (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
66 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
68 /* If you change these, you also have to update the library files
69 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
70 #define GPTR_TAG_DATA 0x80
71 #define GPTR_TAG_EEPROM 0x40
72 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
74 /* Wrapper to execute `code' at most once. */
75 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
77 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
79 void pic16_genMult8X8_8 (operand *, operand *,operand *);
80 void pic16_genMult16X16_16(operand *, operand *, operand *);
81 void pic16_genMult32X32_32(operand *, operand *, operand *);
82 pCode *pic16_AssembleLine(char *line, int peeps);
83 extern void pic16_printpBlock(FILE *of, pBlock *pb);
84 static asmop *newAsmop (short type);
85 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
86 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
87 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
88 static pCodeOp *pic16_popRegFromIdx(int rIdx);
90 //static int aopIdx (asmop *aop, int offset);
92 int pic16_labelOffset=0;
93 extern int pic16_debug_verbose;
94 #if !(USE_GENERIC_SIGNED_SHIFT)
95 static int optimized_for_speed = 0;
104 /* max_key keeps track of the largest label number used in
105 a function. This is then used to adjust the label offset
106 for the next function.
108 static int max_key=0;
109 static int GpsuedoStkPtr=0;
111 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
113 unsigned int pic16aopLiteral (value *val, int offset);
114 const char *pic16_AopType(short type);
115 static iCode *ifxForOp ( operand *op, iCode *ic );
117 void pic16_pushpCodeOp(pCodeOp *pcop);
118 void pic16_poppCodeOp(pCodeOp *pcop);
120 static bool is_LitOp(operand *op);
121 static bool is_LitAOp(asmop *aop);
124 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
126 /* set the following macro to 1 to enable passing the
127 * first byte of functions parameters via WREG */
128 #define USE_WREG_IN_FUNC_PARAMS 0
131 /* this is the down and dirty file with all kinds of
132 kludgy & hacky stuff. This is what it is all about
133 CODE GENERATION for a specific MCU . some of the
134 routines may be reusable, will have to see */
136 static char *zero = "#0x00";
137 static char *one = "#0x01";
138 //static char *spname = "sp";
142 * Function return value policy (MSB-->LSB):
144 * 16 bits -> PRODL:WREG
145 * 24 bits -> PRODH:PRODL:WREG
146 * 32 bits -> FSR0L:PRODH:PRODL:WREG
147 * >32 bits -> on stack, and FSR0 points to the beginning
152 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
153 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
154 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
155 static char **fReturn = fReturnpic16;
157 static char *accUse[] = {"WREG"};
159 //static short rbank = -1;
173 bitVect *fregsUsed; /* registers used in function */
175 set *sregsAllocSet; /* registers used to store stack variables */
176 int stack_lat; /* stack offset latency */
178 int useWreg; /* flag when WREG is used to pass function parameter */
181 extern int pic16_ptrRegReq ;
182 extern int pic16_nRegs;
183 extern FILE *codeOutFile;
184 //static void saverbank (int, iCode *,bool);
186 static lineNode *lineHead = NULL;
187 static lineNode *lineCurr = NULL;
189 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
190 0xE0, 0xC0, 0x80, 0x00};
191 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
192 0x07, 0x03, 0x01, 0x00};
196 /*-----------------------------------------------------------------*/
197 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
198 /* exponent of 2 is returned, otherwise -1 is */
200 /* note that this is similar to the function `powof2' in SDCCsymt */
204 /*-----------------------------------------------------------------*/
205 int pic16_my_powof2 (unsigned long num)
208 if( (num & (num-1)) == 0) {
221 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
223 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
225 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
226 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
227 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
228 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
229 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
230 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
231 ((result) ? AOP_SIZE(result) : 0));
234 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
237 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
239 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
240 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
241 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
242 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
243 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
244 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
248 void pic16_emitpcomment (char *fmt, ...)
251 char lb[INITIAL_INLINEASM];
252 unsigned char *lbp = (unsigned char *)lb;
257 vsprintf(lb+1,fmt,ap);
259 while (isspace(*lbp)) lbp++;
262 lineCurr = (lineCurr ?
263 connectLine(lineCurr,newLineNode(lb)) :
264 (lineHead = newLineNode(lb)));
265 lineCurr->isInline = _G.inLine;
266 lineCurr->isDebug = _G.debugLine;
268 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
271 // fprintf(stderr, "%s\n", lb);
274 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
277 char lb[INITIAL_INLINEASM];
278 unsigned char *lbp = (unsigned char *)lb;
280 if(!pic16_debug_verbose)
287 sprintf(lb,"%s\t",inst);
289 sprintf(lb,"%s",inst);
290 vsprintf(lb+(strlen(lb)),fmt,ap);
294 while (isspace(*lbp)) lbp++;
297 lineCurr = (lineCurr ?
298 connectLine(lineCurr,newLineNode(lb)) :
299 (lineHead = newLineNode(lb)));
300 lineCurr->isInline = _G.inLine;
301 lineCurr->isDebug = _G.debugLine;
303 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
306 // fprintf(stderr, "%s\n", lb);
311 void pic16_emitpLabel(int key)
313 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
316 void pic16_emitpLabelFORCE(int key)
318 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322 * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
327 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
329 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
335 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
337 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
343 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
349 #define pic16_emitcode DEBUGpic16_emitcode
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
357 char lb[INITIAL_INLINEASM];
358 unsigned char *lbp = lb;
364 sprintf(lb,"%s\t",inst);
366 sprintf(lb,"%s",inst);
367 vsprintf(lb+(strlen(lb)),fmt,ap);
371 while (isspace(*lbp)) lbp++;
374 lineCurr = (lineCurr ?
375 connectLine(lineCurr,newLineNode(lb)) :
376 (lineHead = newLineNode(lb)));
377 lineCurr->isInline = _G.inLine;
378 lineCurr->isDebug = _G.debugLine;
380 // VR fprintf(stderr, "lb = <%s>\n", lbp);
382 // if(pic16_debug_verbose)
383 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location */
392 /* with a debugger symbol */
393 /*-----------------------------------------------------------------*/
395 pic16_emitDebuggerSymbol (char * debugSym)
398 pic16_emitcode (";", "%s ==.", debugSym);
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
408 // bool r0iu = FALSE , r1iu = FALSE;
409 // bool r0ou = FALSE , r1ou = FALSE;
410 bool fsr0iu = FALSE, fsr0ou;
411 bool fsr2iu = FALSE, fsr2ou;
413 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
416 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
419 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
422 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
427 if(!fsr0iu && !fsr0ou) {
428 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429 (*aopp)->type = AOP_FSR0;
431 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
433 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
437 /* no usage of FSR2 */
438 if(!fsr2iu && !fsr2ou) {
439 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440 (*aopp)->type = AOP_FSR2;
442 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
446 /* now we know they both have usage */
447 /* if fsr0 not used in this instruction */
449 if (!_G.fsr0Pushed) {
450 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
455 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456 (*aopp)->type = AOP_FSR0;
458 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
460 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
464 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
469 /* the logic: if r0 & r1 used in the instruction
470 then we are in trouble otherwise */
472 /* first check if r0 & r1 are used by this
473 instruction, in which case we are in trouble */
474 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
480 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
483 /* if no usage of r0 then return it */
484 if (!r0iu && !r0ou) {
485 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486 (*aopp)->type = AOP_R0;
488 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491 /* if no usage of r1 then return it */
492 if (!r1iu && !r1ou) {
493 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494 (*aopp)->type = AOP_R1;
496 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
499 /* now we know they both have usage */
500 /* if r0 not used in this instruction */
502 /* push it if not already pushed */
504 //pic16_emitcode ("push","%s",
505 // pic16_regWithIdx(R0_IDX)->dname);
509 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510 (*aopp)->type = AOP_R0;
512 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
515 /* if r1 not used then */
518 /* push it if not already pushed */
520 //pic16_emitcode ("push","%s",
521 // pic16_regWithIdx(R1_IDX)->dname);
525 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526 (*aopp)->type = AOP_R1;
527 return pic16_regWithIdx(R1_IDX);
531 /* I said end of world but not quite end of world yet */
532 /* if this is a result then we can push it on the stack*/
534 (*aopp)->type = AOP_STK;
538 /* other wise this is true end of the world */
539 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540 "getFreePtr should never reach here");
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
552 aop = Safe_calloc(1,sizeof(asmop));
557 static void genSetDPTR(int n)
561 pic16_emitcode(";", "Select standard DPTR");
562 pic16_emitcode("mov", "dps, #0x00");
566 pic16_emitcode(";", "Select alternate DPTR");
567 pic16_emitcode("mov", "dps, #0x01");
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for */
573 /* generating code */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
579 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585 resIfx->condition = 1; /* assume that the ifx is true */
586 resIfx->generated = 0; /* indicate that the ifx has not been used */
589 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
592 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593 __FUNCTION__,__LINE__,resIfx->lbl->key);
598 resIfx->lbl = IC_TRUE(ifx);
600 resIfx->lbl = IC_FALSE(ifx);
601 resIfx->condition = 0;
606 DEBUGpic16_emitcode("; +++","ifx true is non-null");
608 DEBUGpic16_emitcode("; +++","ifx true is null");
610 DEBUGpic16_emitcode("; +++","ifx false is non-null");
612 DEBUGpic16_emitcode("; +++","ifx false is null");
616 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
626 return PTR_TYPE(SPEC_OCLS(etype));
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
636 symbol *sym=OP_SYMBOL(op);
638 memmap *space= SPEC_OCLS(sym->etype);
642 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
644 // sym = OP_SYMBOL(op);
646 /* if already has one */
648 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
653 /* if symbol was initially placed onStack then we must re-place it
654 * to direct memory, since pic16 does not have a specific stack */
656 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
664 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
666 sym->aop = aop = newAsmop (AOP_PAGED);
667 aop->aopu.aop_dir = sym->rname ;
668 aop->size = getSize(sym->type);
669 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670 pic16_allocDirReg( IC_LEFT(ic) );
678 /* assign depending on the storage class */
679 /* if it is on the stack or indirectly addressable */
680 /* space we need to assign either r0 or r1 to it */
681 if (sym->onStack) // || sym->iaccess)
686 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
689 /* acquire a temporary register -- it is saved in function */
691 sym->aop = aop = newAsmop(AOP_STA);
692 aop->aopu.stk.stk = sym->stack;
693 aop->size = getSize(sym->type);
696 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
701 for(i=0;i<aop->size;i++)
702 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
705 if(1 && ic->op == SEND) {
707 /* if SEND do the send here */
710 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
711 for(i=0;i<aop->size;i++) {
712 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
713 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
718 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
721 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
723 // we do not need to load the value if it is to be defined...
724 if (result) return aop;
727 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730 for(i=0;i<aop->size;i++) {
732 /* initialise for stack access via frame pointer */
733 // operands on stack are accessible via "{FRAME POINTER} + index" with index
734 // starting at 2 for arguments and growing from 0 downwards for
735 // local variables (index == 0 is not assigned so we add one here)
737 int soffs = sym->stack;
743 if(1 && ic->op == SEND) {
744 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
745 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
746 pic16_popCopyReg( pic16_frame_plusw ),
747 pic16_popCopyReg(pic16_stack_postdec )));
749 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
750 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
757 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
764 /* now assign the address of the variable to
765 the pointer register */
766 if (aop->type != AOP_STK) {
770 pic16_emitcode("push","acc");
772 pic16_emitcode("mov","a,_bp");
773 pic16_emitcode("add","a,#0x%02x",
775 ((char)(sym->stack - _G.nRegsSaved )) :
776 ((char)sym->stack)) & 0xff);
777 pic16_emitcode("mov","%s,a",
778 aop->aopu.aop_ptr->name);
781 pic16_emitcode("pop","acc");
783 pic16_emitcode("mov","%s,#%s",
784 aop->aopu.aop_ptr->name,
786 aop->paged = space->paged;
788 aop->aopu.aop_stk = sym->stack;
796 if (sym->onStack && options.stack10bit)
798 /* It's on the 10 bit stack, which is located in
802 //DEBUGpic16_emitcode(";","%d",__LINE__);
805 pic16_emitcode("push","acc");
807 pic16_emitcode("mov","a,_bp");
808 pic16_emitcode("add","a,#0x%02x",
810 ((char)(sym->stack - _G.nRegsSaved )) :
811 ((char)sym->stack)) & 0xff);
814 pic16_emitcode ("mov","dpx1,#0x40");
815 pic16_emitcode ("mov","dph1,#0x00");
816 pic16_emitcode ("mov","dpl1, a");
820 pic16_emitcode("pop","acc");
822 sym->aop = aop = newAsmop(AOP_DPTR2);
823 aop->size = getSize(sym->type);
829 /* special case for a function */
830 if (IS_FUNC(sym->type)) {
831 sym->aop = aop = newAsmop(AOP_PCODE);
832 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
833 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
834 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
835 PCOI(aop->aopu.pcop)->index = 0;
836 aop->size = FPTRSIZE;
837 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
844 //DEBUGpic16_emitcode(";","%d",__LINE__);
845 /* if in bit space */
846 if (IN_BITSPACE(space)) {
847 sym->aop = aop = newAsmop (AOP_CRY);
848 aop->aopu.aop_dir = sym->rname ;
849 aop->size = getSize(sym->type);
850 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853 /* if it is in direct space */
854 if (IN_DIRSPACE(space)) {
855 if(!strcmp(sym->rname, "_WREG")) {
856 sym->aop = aop = newAsmop (AOP_ACC);
857 aop->size = getSize(sym->type); /* should always be 1 */
858 assert(aop->size == 1);
859 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
862 sym->aop = aop = newAsmop (AOP_DIR);
863 aop->aopu.aop_dir = sym->rname ;
864 aop->size = getSize(sym->type);
865 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
866 pic16_allocDirReg( IC_LEFT(ic) );
871 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
872 sym->aop = aop = newAsmop (AOP_DIR);
873 aop->aopu.aop_dir = sym->rname ;
874 aop->size = getSize(sym->type);
875 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
876 pic16_allocDirReg( IC_LEFT(ic) );
881 /* only remaining is far space */
882 sym->aop = aop = newAsmop(AOP_PCODE);
884 /* change the next if to 1 to revert to good old immediate code */
885 if(IN_CODESPACE(space)) {
886 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
887 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
888 PCOI(aop->aopu.pcop)->index = 0;
890 /* try to allocate via direct register */
891 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
892 // aop->size = getSize( sym->type );
895 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
896 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
899 if(!pic16_allocDirReg (IC_LEFT(ic)))
903 if(IN_DIRSPACE( space ))
905 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
906 aop->size = FPTRSIZE;
907 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
908 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
909 else if(sym->onStack) {
912 if(SPEC_SCLS(sym->etype) == S_PDATA) {
913 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
914 aop->size = FPTRSIZE;
919 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
921 /* if it is in code space */
922 if (IN_CODESPACE(space))
928 /*-----------------------------------------------------------------*/
929 /* aopForRemat - rematerialzes an object */
930 /*-----------------------------------------------------------------*/
931 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
933 symbol *sym = OP_SYMBOL(op);
935 iCode *ic = NULL, *oldic;
936 asmop *aop = newAsmop(AOP_PCODE);
943 ic = sym->rematiCode;
945 if(IS_OP_POINTER(op)) {
946 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
949 // if(!result) /* fixme-vr */
953 // pic16_emitpcomment("ic: %s\n", printILine(ic));
956 val += (int) operandLitValue(IC_RIGHT(ic));
957 } else if (ic->op == '-') {
958 val -= (int) operandLitValue(IC_RIGHT(ic));
962 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
965 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
968 if(!op->isaddr)viaimmd++; else viaimmd=0;
970 /* set the following if to 1 to revert to good old immediate code */
971 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
974 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
976 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
979 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
981 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
984 PCOI(aop->aopu.pcop)->index = val;
986 aop->size = getSize( sym->type );
988 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
990 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
991 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
993 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
997 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
998 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1000 val, IS_PTR_CONST(operandType(op)));
1002 val, IS_CODEPTR(operandType(op)));
1005 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1007 pic16_allocDirReg (IC_LEFT(ic));
1009 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1016 static int aopIdx (asmop *aop, int offset)
1021 if(aop->type != AOP_REG)
1024 return aop->aopu.aop_reg[offset]->rIdx;
1029 /*-----------------------------------------------------------------*/
1030 /* regsInCommon - two operands have some registers in common */
1031 /*-----------------------------------------------------------------*/
1032 static bool regsInCommon (operand *op1, operand *op2)
1034 symbol *sym1, *sym2;
1037 /* if they have registers in common */
1038 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1041 sym1 = OP_SYMBOL(op1);
1042 sym2 = OP_SYMBOL(op2);
1044 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1047 for (i = 0 ; i < sym1->nRegs ; i++) {
1052 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1056 if (sym2->regs[j] == sym1->regs[i])
1064 /*-----------------------------------------------------------------*/
1065 /* operandsEqu - equivalent */
1066 /*-----------------------------------------------------------------*/
1067 static bool operandsEqu ( operand *op1, operand *op2)
1069 symbol *sym1, *sym2;
1071 /* if they not symbols */
1072 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1075 sym1 = OP_SYMBOL(op1);
1076 sym2 = OP_SYMBOL(op2);
1078 /* if both are itemps & one is spilt
1079 and the other is not then false */
1080 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1081 sym1->isspilt != sym2->isspilt )
1084 /* if they are the same */
1088 if (sym1->rname[0] && sym2->rname[0]
1089 && strcmp (sym1->rname, sym2->rname) == 0)
1093 /* if left is a tmp & right is not */
1094 if (IS_ITEMP(op1) &&
1097 (sym1->usl.spillLoc == sym2))
1100 if (IS_ITEMP(op2) &&
1104 (sym2->usl.spillLoc == sym1))
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_sameRegs - two asmops have the same registers */
1112 /*-----------------------------------------------------------------*/
1113 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1120 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1121 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1123 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1125 if (aop1->type != AOP_REG ||
1126 aop2->type != AOP_REG )
1129 /* This is a bit too restrictive if one is a subset of the other...
1130 if (aop1->size != aop2->size )
1134 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1135 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1137 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1138 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1145 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1147 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1148 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1150 if(aop1 == aop2)return TRUE;
1151 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1153 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1159 /*-----------------------------------------------------------------*/
1160 /* pic16_aopOp - allocates an asmop for an operand : */
1161 /*-----------------------------------------------------------------*/
1162 void pic16_aopOp (operand *op, iCode *ic, bool result)
1171 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1173 /* if this a literal */
1174 if (IS_OP_LITERAL(op)) {
1175 op->aop = aop = newAsmop(AOP_LIT);
1176 aop->aopu.aop_lit = op->operand.valOperand;
1177 aop->size = getSize(operandType(op));
1182 sym_link *type = operandType(op);
1184 if(IS_PTR_CONST(type))
1186 if(IS_CODEPTR(type))
1188 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1191 /* if already has a asmop then continue */
1195 /* if the underlying symbol has a aop */
1196 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1197 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1198 op->aop = OP_SYMBOL(op)->aop;
1202 /* if this is a true symbol */
1203 if (IS_TRUE_SYMOP(op)) {
1204 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1205 op->aop = aopForSym(ic, op, result);
1209 /* this is a temporary : this has
1215 e) can be a return use only */
1217 sym = OP_SYMBOL(op);
1219 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1220 /* if the type is a conditional */
1221 if (sym->regType == REG_CND) {
1222 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1227 /* if it is spilt then two situations
1229 b) has a spill location */
1230 if (sym->isspilt || sym->nRegs == 0) {
1232 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1233 DEBUGpic16_emitcode(";","%d",__LINE__);
1234 /* rematerialize it NOW */
1237 sym->aop = op->aop = aop = aopForRemat (op, result);
1238 // aop->size = getSize(sym->type);
1239 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1246 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1247 aop->size = getSize(sym->type);
1248 for ( i = 0 ; i < 1 ; i++ ) {
1249 aop->aopu.aop_str[i] = accUse[i];
1250 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1252 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1253 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1261 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1262 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1263 //pic16_allocDirReg (IC_LEFT(ic));
1264 aop->size = getSize(sym->type);
1269 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1270 aop->size = getSize(sym->type);
1271 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1272 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1274 DEBUGpic16_emitcode(";","%d",__LINE__);
1278 /* else spill location */
1279 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1280 /* force a new aop if sizes differ */
1281 sym->usl.spillLoc->aop = NULL;
1285 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1286 __FUNCTION__,__LINE__,
1287 sym->usl.spillLoc->rname,
1288 sym->rname, sym->usl.spillLoc->offset);
1291 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1292 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1293 /* Don't reuse the new aop */
1294 sym->usl.spillLoc->aop = NULL;
1296 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1297 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1298 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1300 sym->usl.spillLoc->offset, op);
1302 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1303 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1304 assert (getSize(sym->type) <= 1);
1305 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1307 aop->size = getSize(sym->type);
1313 sym_link *type = operandType(op);
1315 if(IS_PTR_CONST(type))
1317 if(IS_CODEPTR(type))
1319 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1322 /* must be in a register */
1323 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1324 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1325 aop->size = sym->nRegs;
1326 for ( i = 0 ; i < sym->nRegs ;i++)
1327 aop->aopu.aop_reg[i] = sym->regs[i];
1330 /*-----------------------------------------------------------------*/
1331 /* pic16_freeAsmop - free up the asmop given to an operand */
1332 /*----------------------------------------------------------------*/
1333 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1350 /* depending on the asmop type only three cases need work AOP_RO
1351 , AOP_R1 && AOP_STK */
1353 switch (aop->type) {
1355 if (_G.fsr0Pushed ) {
1357 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1358 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1359 // pic16_emitcode ("pop","ar0");
1363 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1367 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1373 pic16_emitcode ("pop","ar0");
1377 bitVectUnSetBit(ic->rUsed,R0_IDX);
1383 pic16_emitcode ("pop","ar1");
1387 bitVectUnSetBit(ic->rUsed,R1_IDX);
1394 /* we must store the result on stack */
1395 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1396 // operands on stack are accessible via "FSR2 + index" with index
1397 // starting at 2 for arguments and growing from 0 downwards for
1398 // local variables (index == 0 is not assigned so we add one here)
1399 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1404 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1405 for(i=0;i<aop->size;i++) {
1406 /* initialise for stack access via frame pointer */
1407 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1408 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1409 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1412 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1416 for(i=0;i<aop->size;i++) {
1417 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1419 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1420 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1421 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1428 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1429 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1430 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1431 deleteSetItem( &_G.sregsAllocSet, sr );
1442 int stk = aop->aopu.aop_stk + aop->size;
1443 bitVectUnSetBit(ic->rUsed,R0_IDX);
1444 bitVectUnSetBit(ic->rUsed,R1_IDX);
1446 getFreePtr(ic,&aop,FALSE);
1448 if (options.stack10bit)
1450 /* I'm not sure what to do here yet... */
1453 "*** Warning: probably generating bad code for "
1454 "10 bit stack mode.\n");
1458 pic16_emitcode ("mov","a,_bp");
1459 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1460 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1462 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1466 pic16_emitcode("pop","acc");
1467 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1469 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1472 pic16_freeAsmop(op,NULL,ic,TRUE);
1474 pic16_emitcode("pop","ar0");
1479 pic16_emitcode("pop","ar1");
1489 /* all other cases just dealloc */
1493 OP_SYMBOL(op)->aop = NULL;
1494 /* if the symbol has a spill */
1496 SPIL_LOC(op)->aop = NULL;
1501 /*-----------------------------------------------------------------*/
1502 /* pic16_aopGet - for fetching value of the aop */
1503 /*-----------------------------------------------------------------*/
1504 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1509 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1511 /* offset is greater than size then zero */
1512 if (offset > (aop->size - 1) &&
1513 aop->type != AOP_LIT)
1516 /* depending on type */
1517 switch (aop->type) {
1521 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1522 rs = Safe_calloc(1, strlen(s)+1);
1527 /* if we need to increment it */
1528 while (offset > aop->coff)
1530 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1534 while (offset < aop->coff)
1536 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1542 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1543 return (dname ? "acc" : "a");
1545 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1546 rs = Safe_calloc (1, strlen (s) + 1);
1554 sprintf (s,"%s",aop->aopu.aop_immd);
1557 sprintf(s,"(%s >> %d)",
1562 aop->aopu.aop_immd);
1563 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1564 rs = Safe_calloc(1,strlen(s)+1);
1570 sprintf(s,"(%s + %d)",
1573 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1575 sprintf(s,"%s",aop->aopu.aop_dir);
1576 rs = Safe_calloc(1,strlen(s)+1);
1581 return aop->aopu.aop_reg[offset]->name;
1584 return aop->aopu.aop_dir;
1587 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1588 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1590 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1591 rs = Safe_strdup("WREG");
1595 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1596 rs = Safe_calloc(1,strlen(s)+1);
1601 aop->coff = offset ;
1603 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1606 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1607 aop->type = AOP_ACC;
1608 return Safe_strdup("_WREG");
1610 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1612 return aop->aopu.aop_str[offset];
1616 pCodeOp *pcop = aop->aopu.pcop;
1617 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1619 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1620 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1622 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1624 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1627 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1630 rs = Safe_calloc(1,strlen(s)+1);
1636 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1638 sprintf(s,"(%s + %d)",
1642 sprintf(s,"%s",aop->aopu.aop_dir);
1643 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644 rs = Safe_calloc(1,strlen(s)+1);
1650 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1654 // pCodeOp *pcop = aop->aop
1659 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1660 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1661 "aopget got unsupported aop->type");
1667 /* lock has the following meaning: When allocating temporary registers
1668 * for stack variables storage, the value of the temporary register is
1669 * saved on stack. Its value is restored at the end. This procedure is
1670 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1671 * a possibility that before a call to pic16_aopOp, a temporary register
1672 * is allocated for a while and it is freed after some time, this will
1673 * mess the stack and values will not be restored properly. So use lock=1
1674 * to allocate temporary registers used internally by the programmer, and
1675 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1676 * to inform the compiler developer about a possible bug. This is an internal
1677 * feature for developing the compiler -- VR */
1679 int _TempReg_lock = 0;
1680 /*-----------------------------------------------------------------*/
1681 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1682 /*-----------------------------------------------------------------*/
1683 pCodeOp *pic16_popGetTempReg(int lock)
1688 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1690 // werror(W_POSSBUG2, __FILE__, __LINE__);
1693 _TempReg_lock += lock;
1703 /* this code might seem better but it does the *same* job with
1704 * the old code, it all depends on ralloc.c to get a free/unused
1708 while(i < pic16_nRegs) {
1709 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1710 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1711 if((!rr || (rr && rr->isFree))
1712 && !bitVectBitValue(cfunc->regsUsed, i)) {
1713 pcop = pic16_newpCodeOpReg( i );
1714 PCOR(pcop)->r->wasUsed = 1;
1715 PCOR(pcop)->r->isFree = 0;
1722 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1726 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1727 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1728 PCOR(pcop)->r->wasUsed=1;
1729 PCOR(pcop)->r->isFree=0;
1731 /* push value on stack */
1732 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741 /*-----------------------------------------------------------------*/
1742 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1743 /* is not part of f, but don't save if */
1745 /*-----------------------------------------------------------------*/
1746 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1752 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1755 // werror(W_POSSBUG2, __FILE__, __LINE__);
1758 _TempReg_lock += lock;
1763 i = bitVectFirstBit(f);
1766 /* bypass registers that are used by function */
1767 if(!bitVectBitValue(f, i)) {
1769 /* bypass registers that are already allocated for stack access */
1770 if(!bitVectBitValue(v, i)) {
1772 // debugf("getting register rIdx = %d\n", i);
1773 /* ok, get the operand */
1774 pcop = pic16_newpCodeOpReg( i );
1776 /* should never by NULL */
1777 assert( pcop != NULL );
1781 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1784 PCOR(pcop)->r->wasUsed=1;
1785 PCOR(pcop)->r->isFree=0;
1791 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1793 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1794 /* already used in previous steps, break */
1801 /* caller takes care of the following */
1802 // bitVectSetBit(v, i);
1805 /* push value on stack */
1806 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1807 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1823 /*-----------------------------------------------------------------*/
1824 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1825 /*-----------------------------------------------------------------*/
1826 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1830 _TempReg_lock -= lock;
1832 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1833 PCOR(pcop)->r->isFree = 1;
1835 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1840 /*-----------------------------------------------------------------*/
1841 pCodeOp *pic16_popGetLabel(int key)
1844 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1849 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popCopyReg - copy a pcode operator */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1859 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1860 memcpy (pcor, pc, sizeof (pCodeOpReg));
1861 pcor->r->wasUsed = 1;
1863 //pcor->pcop.type = pc->pcop.type;
1865 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1866 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1868 pcor->pcop.name = NULL;
1871 //pcor->rIdx = pc->rIdx;
1872 //pcor->r->wasUsed=1;
1873 //pcor->instance = pc->instance;
1875 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1880 /*-----------------------------------------------------------------*/
1881 /* pic16_popGetLit - asm operator to pcode operator conversion */
1882 /*-----------------------------------------------------------------*/
1883 pCodeOp *pic16_popGetLit(int lit)
1885 return pic16_newpCodeOpLit(lit);
1888 /* Allow for 12 bit literals (LFSR x, <here!>). */
1889 pCodeOp *pic16_popGetLit12(int lit)
1891 return pic16_newpCodeOpLit12(lit);
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1899 return pic16_newpCodeOpLit2(lit, arg2);
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1908 return pic16_newpCodeOpImmd(name, offset,index, 0);
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGet - asm operator to pcode operator conversion */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetWithString(char *str)
1921 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1925 pcop = pic16_newpCodeOp(str,PO_STR);
1930 /*-----------------------------------------------------------------*/
1931 /* pic16_popRegFromString - */
1932 /*-----------------------------------------------------------------*/
1933 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1936 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1937 pcop->type = PO_DIR;
1939 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1940 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1945 pcop->name = Safe_calloc(1,strlen(str)+1);
1946 strcpy(pcop->name,str);
1948 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1950 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1951 // PCOR(pcop)->r->wasUsed = 1;
1953 /* make sure that register doesn't exist,
1954 * and operand isn't NULL
1955 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1956 if((PCOR(pcop)->r == NULL)
1958 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1959 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1960 // __FUNCTION__, __LINE__, str, size, offset);
1962 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1963 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1966 PCOR(pcop)->instance = offset;
1971 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1975 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1976 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1978 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1979 PCOR(pcop)->rIdx = rIdx;
1980 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1982 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1984 PCOR(pcop)->r->isFree = 0;
1985 PCOR(pcop)->r->wasUsed = 1;
1987 pcop->type = PCOR(pcop)->r->pc_type;
1992 /*---------------------------------------------------------------------------------*/
1993 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1995 /*---------------------------------------------------------------------------------*/
1996 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2001 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
2003 /* comment the following check, so errors to throw up */
2004 // if(!pcop2)return NULL;
2006 temp = pic16_popGet(aop_dst, offset);
2007 pcop2->pcop2 = temp;
2014 /*--------------------------------------------------------------------------------.-*/
2015 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2016 /* VR 030601 , adapted by Hans Dorn */
2017 /*--------------------------------------------------------------------------------.-*/
2018 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2022 pcop2 = (pCodeOpReg2 *)src;
2030 /*---------------------------------------------------------------------------------*/
2031 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2032 /* movff instruction */
2033 /*---------------------------------------------------------------------------------*/
2034 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2039 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2040 pcop2->pcop2 = pic16_popCopyReg(dst);
2042 /* the pCodeOp may be already allocated */
2043 pcop2 = (pCodeOpReg2 *)(src);
2044 pcop2->pcop2 = (pCodeOp *)(dst);
2051 /*-----------------------------------------------------------------*/
2052 /* pic16_popGet - asm operator to pcode operator conversion */
2053 /*-----------------------------------------------------------------*/
2054 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2056 // char *s = buffer ;
2061 /* offset is greater than
2064 // if (offset > (aop->size - 1) &&
2065 // aop->type != AOP_LIT)
2066 // return NULL; //zero;
2068 /* depending on type */
2069 switch (aop->type) {
2074 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2075 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2081 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2082 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2083 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2084 PCOR(pcop)->r->wasUsed = 1;
2085 PCOR(pcop)->r->isFree = 0;
2087 PCOR(pcop)->instance = offset;
2088 pcop->type = PCOR(pcop)->r->pc_type;
2092 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2093 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2096 /* pCodeOp is already allocated from aopForSym */
2097 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2098 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2103 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2105 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2107 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2109 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2110 PCOR(pcop)->rIdx = rIdx;
2111 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2112 PCOR(pcop)->r->wasUsed=1;
2113 PCOR(pcop)->r->isFree=0;
2115 PCOR(pcop)->instance = offset;
2116 pcop->type = PCOR(pcop)->r->pc_type;
2117 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2121 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2122 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2128 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2129 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2133 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2134 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2140 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2141 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2143 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2145 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2146 // pcop->type = PO_GPR_REGISTER;
2147 PCOR(pcop)->rIdx = rIdx;
2148 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2149 PCOR(pcop)->r->wasUsed=1;
2150 PCOR(pcop)->r->isFree=0;
2152 PCOR(pcop)->instance = offset;
2153 pcop->type = PCOR(pcop)->r->pc_type;
2155 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2156 // rs = aop->aopu.aop_reg[offset]->name;
2157 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2162 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2164 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2165 PCOR(pcop)->instance = offset;
2166 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2167 //if(PCOR(pcop)->r == NULL)
2168 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2172 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2173 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2176 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2177 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2180 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2181 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2182 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2183 pcop->type = PCOR(pcop)->r->pc_type;
2184 pcop->name = PCOR(pcop)->r->name;
2190 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2192 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2193 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2194 switch( aop->aopu.pcop->type ) {
2195 case PO_DIR: PCOR(pcop)->instance += offset; break;
2196 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2201 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2202 assert( 0 ); /* should never reach here */;
2207 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2208 "pic16_popGet got unsupported aop->type");
2211 /*-----------------------------------------------------------------*/
2212 /* pic16_aopPut - puts a string for a aop */
2213 /*-----------------------------------------------------------------*/
2214 void pic16_aopPut (asmop *aop, char *s, int offset)
2221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2223 if (aop->size && offset > ( aop->size - 1)) {
2224 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2225 "pic16_aopPut got offset > aop->size");
2229 /* will assign value to value */
2230 /* depending on where it is ofcourse */
2231 switch (aop->type) {
2234 sprintf(d,"(%s + %d)",
2235 aop->aopu.aop_dir,offset);
2236 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2239 sprintf(d,"%s",aop->aopu.aop_dir);
2242 DEBUGpic16_emitcode(";","%d",__LINE__);
2244 pic16_emitcode("movf","%s,w",s);
2245 pic16_emitcode("movwf","%s",d);
2248 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2249 if(offset >= aop->size) {
2250 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2253 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2256 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2263 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2264 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2267 strcmp(s,"r0") == 0 ||
2268 strcmp(s,"r1") == 0 ||
2269 strcmp(s,"r2") == 0 ||
2270 strcmp(s,"r3") == 0 ||
2271 strcmp(s,"r4") == 0 ||
2272 strcmp(s,"r5") == 0 ||
2273 strcmp(s,"r6") == 0 ||
2274 strcmp(s,"r7") == 0 )
2275 pic16_emitcode("mov","%s,%s ; %d",
2276 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2280 if(strcmp(s,"W")==0 )
2281 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2283 pic16_emitcode("movwf","%s",
2284 aop->aopu.aop_reg[offset]->name);
2286 if(strcmp(s,zero)==0) {
2287 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2289 } else if(strcmp(s,"W")==0) {
2290 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2291 pcop->type = PO_GPR_REGISTER;
2293 PCOR(pcop)->rIdx = -1;
2294 PCOR(pcop)->r = NULL;
2296 DEBUGpic16_emitcode(";","%d",__LINE__);
2297 pcop->name = Safe_strdup(s);
2298 pic16_emitpcode(POC_MOVFW,pcop);
2299 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2300 } else if(strcmp(s,one)==0) {
2301 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2302 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2304 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2312 if (aop->type == AOP_DPTR2)
2318 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2319 "pic16_aopPut writting to code space");
2323 while (offset > aop->coff) {
2325 pic16_emitcode ("inc","dptr");
2328 while (offset < aop->coff) {
2330 pic16_emitcode("lcall","__decdptr");
2335 /* if not in accumulater */
2338 pic16_emitcode ("movx","@dptr,a");
2340 if (aop->type == AOP_DPTR2)
2348 while (offset > aop->coff) {
2350 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2352 while (offset < aop->coff) {
2354 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2360 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2365 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2367 if (strcmp(s,"r0") == 0 ||
2368 strcmp(s,"r1") == 0 ||
2369 strcmp(s,"r2") == 0 ||
2370 strcmp(s,"r3") == 0 ||
2371 strcmp(s,"r4") == 0 ||
2372 strcmp(s,"r5") == 0 ||
2373 strcmp(s,"r6") == 0 ||
2374 strcmp(s,"r7") == 0 ) {
2376 sprintf(buffer,"a%s",s);
2377 pic16_emitcode("mov","@%s,%s",
2378 aop->aopu.aop_ptr->name,buffer);
2380 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2385 if (strcmp(s,"a") == 0)
2386 pic16_emitcode("push","acc");
2388 pic16_emitcode("push","%s",s);
2393 /* if bit variable */
2394 if (!aop->aopu.aop_dir) {
2395 pic16_emitcode("clr","a");
2396 pic16_emitcode("rlc","a");
2399 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2402 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2405 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2407 lbl = newiTempLabel(NULL);
2409 if (strcmp(s,"a")) {
2412 pic16_emitcode("clr","c");
2413 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2414 pic16_emitcode("cpl","c");
2415 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2416 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2423 if (strcmp(aop->aopu.aop_str[offset],s))
2424 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2429 if (!offset && (strcmp(s,"acc") == 0))
2432 if (strcmp(aop->aopu.aop_str[offset],s))
2433 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2437 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2438 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2439 // "pic16_aopPut got unsupported aop->type");
2445 /*-----------------------------------------------------------------*/
2446 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2447 /*-----------------------------------------------------------------*/
2448 void pic16_mov2w (asmop *aop, int offset)
2450 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2453 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2455 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2458 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2460 if(is_LitAOp(src)) {
2461 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2462 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2464 if(pic16_sameRegsOfs(src, dst, offset))return;
2465 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2466 pic16_popGet(dst, offset)));
2470 static void pic16_movLit2f(pCodeOp *pc, int lit)
2472 if (0 == (lit & 0x00ff))
2474 pic16_emitpcode (POC_CLRF, pc);
2475 } else if (0xff == (lit & 0x00ff))
2477 pic16_emitpcode (POC_SETF, pc);
2479 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2480 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2484 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2486 if(is_LitAOp(src)) {
2487 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2488 pic16_emitpcode(POC_MOVWF, dst);
2490 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2494 void pic16_testStackOverflow(void)
2496 #define GSTACK_TEST_NAME "_gstack_test"
2498 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2503 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2504 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2505 // strcpy(sym->rname, GSTACK_TEST_NAME);
2506 checkAddSym(&externs, sym);
2511 /* push pcop into stack */
2512 void pic16_pushpCodeOp(pCodeOp *pcop)
2514 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2515 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2516 if(pic16_options.gstack)
2517 pic16_testStackOverflow();
2521 /* pop pcop from stack */
2522 void pic16_poppCodeOp(pCodeOp *pcop)
2524 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2525 if(pic16_options.gstack)
2526 pic16_testStackOverflow();
2530 /*-----------------------------------------------------------------*/
2531 /* pushw - pushes wreg to stack */
2532 /*-----------------------------------------------------------------*/
2535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2536 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2537 if(pic16_options.gstack)
2538 pic16_testStackOverflow();
2542 /*-----------------------------------------------------------------*/
2543 /* pushaop - pushes aop to stack */
2544 /*-----------------------------------------------------------------*/
2545 void pushaop(asmop *aop, int offset)
2547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2549 if(_G.resDirect)return;
2551 if(is_LitAOp(aop)) {
2552 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2553 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2555 pic16_emitpcode(POC_MOVFF,
2556 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2559 if(pic16_options.gstack)
2560 pic16_testStackOverflow();
2563 /*-----------------------------------------------------------------*/
2564 /* popaop - pops aop from stack */
2565 /*-----------------------------------------------------------------*/
2566 void popaop(asmop *aop, int offset)
2568 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2569 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2570 if(pic16_options.gstack)
2571 pic16_testStackOverflow();
2574 void popaopidx(asmop *aop, int offset, int index)
2578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2580 if(STACK_MODEL_LARGE)ofs++;
2582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2583 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2584 if(pic16_options.gstack)
2585 pic16_testStackOverflow();
2588 #if !(USE_GENERIC_SIGNED_SHIFT)
2589 /*-----------------------------------------------------------------*/
2590 /* reAdjustPreg - points a register back to where it should */
2591 /*-----------------------------------------------------------------*/
2592 static void reAdjustPreg (asmop *aop)
2596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2598 if ((size = aop->size) <= 1)
2601 switch (aop->type) {
2605 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2609 if (aop->type == AOP_DPTR2)
2615 pic16_emitcode("lcall","__decdptr");
2618 if (aop->type == AOP_DPTR2)
2630 /*-----------------------------------------------------------------*/
2631 /* opIsGptr: returns non-zero if the passed operand is */
2632 /* a generic pointer type. */
2633 /*-----------------------------------------------------------------*/
2634 static int opIsGptr(operand *op)
2636 sym_link *type = operandType(op);
2638 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2639 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2647 /*-----------------------------------------------------------------*/
2648 /* pic16_getDataSize - get the operand data size */
2649 /*-----------------------------------------------------------------*/
2650 int pic16_getDataSize(operand *op)
2652 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2655 return AOP_SIZE(op);
2657 // tsd- in the pic port, the genptr size is 1, so this code here
2658 // fails. ( in the 8051 port, the size was 4).
2661 size = AOP_SIZE(op);
2662 if (size == GPTRSIZE)
2664 sym_link *type = operandType(op);
2665 if (IS_GENPTR(type))
2667 /* generic pointer; arithmetic operations
2668 * should ignore the high byte (pointer type).
2671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outAcc - output Acc */
2680 /*-----------------------------------------------------------------*/
2681 void pic16_outAcc(operand *result)
2684 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2685 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2688 size = pic16_getDataSize(result);
2690 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2693 /* unsigned or positive */
2695 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2700 /*-----------------------------------------------------------------*/
2701 /* pic16_outBitC - output a bit C */
2702 /* Move to result the value of Carry flag -- VR */
2703 /*-----------------------------------------------------------------*/
2704 void pic16_outBitC(operand *result)
2708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2710 /* if the result is bit */
2711 if (AOP_TYPE(result) == AOP_CRY) {
2712 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2713 pic16_aopPut(AOP(result),"c",0);
2716 i = AOP_SIZE(result);
2718 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2720 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2724 /*-----------------------------------------------------------------*/
2725 /* pic16_outBitOp - output a bit from Op */
2726 /* Move to result the value of set/clr op -- VR */
2727 /*-----------------------------------------------------------------*/
2728 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2734 /* if the result is bit */
2735 if (AOP_TYPE(result) == AOP_CRY) {
2736 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2737 pic16_aopPut(AOP(result),"c",0);
2740 i = AOP_SIZE(result);
2742 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2744 pic16_emitpcode(POC_RRCF, pcop);
2745 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2749 /*-----------------------------------------------------------------*/
2750 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2751 /*-----------------------------------------------------------------*/
2752 void pic16_toBoolean(operand *oper)
2754 int size = AOP_SIZE(oper) - 1;
2757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2759 if ( AOP_TYPE(oper) != AOP_ACC) {
2760 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2763 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2767 /*-----------------------------------------------------------------*/
2768 /* genUminusFloat - unary minus for floating points */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminusFloat(operand *op,operand *result)
2772 int size ,offset =0 ;
2775 /* for this we just need to flip the
2776 first it then copy the rest in place */
2777 size = AOP_SIZE(op);
2778 assert( size == AOP_SIZE(result) );
2781 pic16_mov2f(AOP(result), AOP(op), offset);
2785 /* toggle the MSB's highest bit */
2786 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2789 /*-----------------------------------------------------------------*/
2790 /* genUminus - unary minus code generation */
2791 /*-----------------------------------------------------------------*/
2792 static void genUminus (iCode *ic)
2795 sym_link *optype, *rtype;
2802 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2803 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2805 /* if both in bit space then special case */
2806 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2807 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2809 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2810 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2811 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2815 optype = operandType(IC_LEFT(ic));
2816 rtype = operandType(IC_RESULT(ic));
2819 /* if float then do float stuff */
2820 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2821 if(IS_FIXED(optype))
2822 debugf("implement fixed16x16 type\n", 0);
2824 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2828 /* otherwise subtract from zero by taking the 2's complement */
2829 size = AOP_SIZE(IC_LEFT(ic));
2830 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2831 label = newiTempLabel ( NULL );
2833 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2834 for (i=size-1; i > 0; i--) {
2835 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2837 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2838 for (i=1; i < size; i++) {
2839 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2840 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2843 for (i=size-1; i >= 0; i--) {
2844 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2848 for (i=0; i < size-2; i++) {
2849 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2850 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2852 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2854 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2857 pic16_emitpLabel (label->key);
2860 /* release the aops */
2861 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2862 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2866 /*-----------------------------------------------------------------*/
2867 /* saveRegisters - will look for a call and save the registers */
2868 /*-----------------------------------------------------------------*/
2869 static void saveRegisters(iCode *lic)
2876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2878 for (ic = lic ; ic ; ic = ic->next)
2879 if (ic->op == CALL || ic->op == PCALL)
2883 fprintf(stderr,"found parameter push with no function call\n");
2887 /* if the registers have been saved already then
2889 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2892 /* find the registers in use at this time
2893 and push them away to safety */
2894 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2898 if (options.useXstack) {
2899 if (bitVectBitValue(rsave,R0_IDX))
2900 pic16_emitcode("mov","b,r0");
2901 pic16_emitcode("mov","r0,%s",spname);
2902 for (i = 0 ; i < pic16_nRegs ; i++) {
2903 if (bitVectBitValue(rsave,i)) {
2905 pic16_emitcode("mov","a,b");
2907 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2908 pic16_emitcode("movx","@r0,a");
2909 pic16_emitcode("inc","r0");
2912 pic16_emitcode("mov","%s,r0",spname);
2913 if (bitVectBitValue(rsave,R0_IDX))
2914 pic16_emitcode("mov","r0,b");
2916 //for (i = 0 ; i < pic16_nRegs ; i++) {
2917 // if (bitVectBitValue(rsave,i))
2918 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2921 dtype = operandType(IC_LEFT(ic));
2922 if (currFunc && dtype &&
2923 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2924 IFFUNC_ISISR(currFunc->type) &&
2927 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2930 /*-----------------------------------------------------------------*/
2931 /* unsaveRegisters - pop the pushed registers */
2932 /*-----------------------------------------------------------------*/
2933 static void unsaveRegisters (iCode *ic)
2938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2939 /* find the registers in use at this time
2940 and push them away to safety */
2941 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2944 if (options.useXstack) {
2945 pic16_emitcode("mov","r0,%s",spname);
2946 for (i = pic16_nRegs ; i >= 0 ; i--) {
2947 if (bitVectBitValue(rsave,i)) {
2948 pic16_emitcode("dec","r0");
2949 pic16_emitcode("movx","a,@r0");
2951 pic16_emitcode("mov","b,a");
2953 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2957 pic16_emitcode("mov","%s,r0",spname);
2958 if (bitVectBitValue(rsave,R0_IDX))
2959 pic16_emitcode("mov","r0,b");
2961 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2962 // if (bitVectBitValue(rsave,i))
2963 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2970 /*-----------------------------------------------------------------*/
2972 /*-----------------------------------------------------------------*/
2973 static void pushSide(operand * oper, int size)
2976 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2978 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2979 if (AOP_TYPE(oper) != AOP_REG &&
2980 AOP_TYPE(oper) != AOP_DIR &&
2982 pic16_emitcode("mov","a,%s",l);
2983 pic16_emitcode("push","acc");
2985 pic16_emitcode("push","%s",l);
2990 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2992 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2993 pic16_emitpcode(POC_MOVFW, src);
2994 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2996 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2997 src, pic16_popGet(AOP(op), offset)));
3002 /*-----------------------------------------------------------------*/
3003 /* assignResultValue - assign results to oper, rescall==1 is */
3004 /* called from genCall() or genPcall() */
3005 /*-----------------------------------------------------------------*/
3006 static void assignResultValue(operand * oper, int rescall)
3008 int size = AOP_SIZE(oper);
3012 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3013 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3016 /* assign result from a call/pcall function() */
3018 /* function results are stored in a special order,
3019 * see top of file with Function return policy, or manual */
3022 /* 8-bits, result in WREG */
3023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3026 /* 16-bits, result in PRODL:WREG */
3027 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3031 /* 24-bits, result in PRODH:PRODL:WREG */
3032 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3036 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3037 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3041 /* >32-bits, result on stack, and FSR0 points to beginning.
3042 * Fix stack when done */
3044 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3046 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3047 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3049 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3054 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3055 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3056 if(STACK_MODEL_LARGE) {
3058 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3062 int areg = 0; /* matching argument register */
3064 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3065 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3068 /* its called from genReceive (probably) -- VR */
3069 /* I hope this code will not be called from somewhere else in the future!
3070 * We manually set the pseudo stack pointer in genReceive. - dw
3072 if(!GpsuedoStkPtr && _G.useWreg) {
3073 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3075 /* The last byte in the assignment is in W */
3076 if(areg <= GpsuedoStkPtr) {
3078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3080 // debugf("receive from WREG\n", 0);
3082 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3085 _G.stack_lat = AOP_SIZE(oper)-1;
3090 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3091 // debugf("receive from STACK\n", 0);
3098 /*-----------------------------------------------------------------*/
3099 /* genIpush - generate code for pushing this gets a little complex */
3100 /*-----------------------------------------------------------------*/
3101 static void genIpush (iCode *ic)
3103 // int size, offset=0;
3106 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3109 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3111 /* send to stack as normal */
3112 addSet(&_G.sendSet,ic);
3113 // addSetHead(&_G.sendSet,ic);
3114 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3119 int size, offset = 0 ;
3123 /* if this is not a parm push : ie. it is spill push
3124 and spill push is always done on the local stack */
3125 if (!ic->parmPush) {
3127 /* and the item is spilt then do nothing */
3128 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3131 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3132 size = AOP_SIZE(IC_LEFT(ic));
3133 /* push it on the stack */
3135 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3140 pic16_emitcode("push","%s",l);
3145 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3149 /*-----------------------------------------------------------------*/
3150 /* genIpop - recover the registers: can happen only for spilling */
3151 /*-----------------------------------------------------------------*/
3152 static void genIpop (iCode *ic)
3155 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3160 /* if the temp was not pushed then */
3161 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3164 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3165 size = AOP_SIZE(IC_LEFT(ic));
3168 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3171 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3176 /*-----------------------------------------------------------------*/
3177 /* unsaverbank - restores the resgister bank from stack */
3178 /*-----------------------------------------------------------------*/
3179 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3181 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3189 if (options.useXstack) {
3191 r = getFreePtr(ic,&aop,FALSE);
3194 pic16_emitcode("mov","%s,_spx",r->name);
3195 pic16_emitcode("movx","a,@%s",r->name);
3196 pic16_emitcode("mov","psw,a");
3197 pic16_emitcode("dec","%s",r->name);
3200 pic16_emitcode ("pop","psw");
3203 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3204 if (options.useXstack) {
3205 pic16_emitcode("movx","a,@%s",r->name);
3206 //pic16_emitcode("mov","(%s+%d),a",
3207 // regspic16[i].base,8*bank+regspic16[i].offset);
3208 pic16_emitcode("dec","%s",r->name);
3211 pic16_emitcode("pop",""); //"(%s+%d)",
3212 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3215 if (options.useXstack) {
3217 pic16_emitcode("mov","_spx,%s",r->name);
3218 pic16_freeAsmop(NULL,aop,ic,TRUE);
3224 /*-----------------------------------------------------------------*/
3225 /* saverbank - saves an entire register bank on the stack */
3226 /*-----------------------------------------------------------------*/
3227 static void saverbank (int bank, iCode *ic, bool pushPsw)
3229 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3236 if (options.useXstack) {
3239 r = getFreePtr(ic,&aop,FALSE);
3240 pic16_emitcode("mov","%s,_spx",r->name);
3244 for (i = 0 ; i < pic16_nRegs ;i++) {
3245 if (options.useXstack) {
3246 pic16_emitcode("inc","%s",r->name);
3247 //pic16_emitcode("mov","a,(%s+%d)",
3248 // regspic16[i].base,8*bank+regspic16[i].offset);
3249 pic16_emitcode("movx","@%s,a",r->name);
3251 pic16_emitcode("push","");// "(%s+%d)",
3252 //regspic16[i].base,8*bank+regspic16[i].offset);
3256 if (options.useXstack) {
3257 pic16_emitcode("mov","a,psw");
3258 pic16_emitcode("movx","@%s,a",r->name);
3259 pic16_emitcode("inc","%s",r->name);
3260 pic16_emitcode("mov","_spx,%s",r->name);
3261 pic16_freeAsmop (NULL,aop,ic,TRUE);
3264 pic16_emitcode("push","psw");
3266 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3274 static int wparamCmp(void *p1, void *p2)
3276 return (!strcmp((char *)p1, (char *)p2));
3279 int inWparamList(char *s)
3281 return isinSetWith(wparamList, s, wparamCmp);
3285 /*-----------------------------------------------------------------*/
3286 /* genCall - generates a call statement */
3287 /*-----------------------------------------------------------------*/
3288 static void genCall (iCode *ic)
3298 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3299 /* if caller saves & we have not saved then */
3300 // if (!ic->regsSaved)
3301 // saveRegisters(ic);
3303 /* initialise stackParms for IPUSH pushes */
3304 // stackParms = psuedoStkPtr;
3305 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3306 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3307 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3310 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3313 /* if send set is not empty the assign */
3316 int psuedoStkPtr=-1;
3317 int firstTimeThruLoop = 1;
3320 /* reverse sendSet if function is not reentrant */
3321 if(!IFFUNC_ISREENT(ftype))
3322 _G.sendSet = reverseSet(_G.sendSet);
3324 /* First figure how many parameters are getting passed */
3328 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3332 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3333 size = AOP_SIZE(IC_LEFT(sic));
3337 /* pass the last byte through WREG */
3341 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3342 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3343 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3345 if(!firstTimeThruLoop) {
3346 /* If this is not the first time we've been through the loop
3347 * then we need to save the parameter in a temporary
3348 * register. The last byte of the last parameter is
3352 // --psuedoStkPtr; // sanity check
3356 firstTimeThruLoop=0;
3358 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3363 /* all arguments are passed via stack */
3367 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3368 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3369 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3371 // pushaop(AOP(IC_LEFT(sic)), size);
3372 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3379 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3383 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3384 pushw(); /* save last parameter to stack if functions has varargs */
3388 } else use_wreg = 0;
3390 _G.stackRegSet = _G.sendSet;
3395 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3399 /* if we need to assign a result value */
3400 if ((IS_ITEMP(IC_RESULT(ic))
3401 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3402 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3403 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3406 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3409 assignResultValue(IC_RESULT(ic), 1);
3411 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3414 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3417 if(!stackParms && ic->parmBytes) {
3418 stackParms = ic->parmBytes;
3421 stackParms -= use_wreg;
3424 if(stackParms == 1) {
3425 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3427 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3428 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3430 if(STACK_MODEL_LARGE) {
3432 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3437 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3440 /* adjust the stack for parameters if required */
3441 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3444 /* if register bank was saved then pop them */
3446 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3448 /* if we hade saved some registers then unsave them */
3449 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3450 unsaveRegisters (ic);
3456 /*-----------------------------------------------------------------*/
3457 /* genPcall - generates a call by pointer statement */
3458 /* new version, created from genCall - HJD */
3459 /*-----------------------------------------------------------------*/
3460 static void genPcall (iCode *ic)
3464 symbol *retlbl = newiTempLabel(NULL);
3465 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3469 fntype = operandType( IC_LEFT(ic) )->next;
3471 /* if send set is not empty the assign */
3474 int psuedoStkPtr=-1;
3476 /* reverse sendSet if function is not reentrant */
3477 if(!IFFUNC_ISREENT(fntype))
3478 _G.sendSet = reverseSet(_G.sendSet);
3482 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3485 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3486 size = AOP_SIZE(IC_LEFT(sic));
3489 /* all parameters are passed via stack, since WREG is clobbered
3490 * by the calling sequence */
3492 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3493 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3494 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3496 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3500 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3503 _G.stackRegSet = _G.sendSet;
3507 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3509 // push return address
3510 // push $ on return stack, then replace with retlbl
3512 /* Thanks to Thorsten Klose for pointing out that the following
3513 * snippet should be interrupt safe */
3514 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3515 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3517 pic16_emitpcodeNULLop(POC_PUSH);
3519 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3520 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3521 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3522 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3523 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3524 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3527 /* restore interrupt control register */
3528 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3529 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3531 /* make the call by writing the pointer into pc */
3532 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3533 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3535 // note: MOVFF to PCL not allowed
3536 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3540 /* return address is here: (X) */
3541 pic16_emitpLabelFORCE(retlbl->key);
3543 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3546 /* if we need assign a result value */
3547 if ((IS_ITEMP(IC_RESULT(ic))
3548 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3549 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3550 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3553 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3556 assignResultValue(IC_RESULT(ic), 1);
3558 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3559 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3561 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3564 // stackParms -= use_wreg;
3567 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3568 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3569 if(STACK_MODEL_LARGE) {
3571 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3576 /*-----------------------------------------------------------------*/
3577 /* resultRemat - result is rematerializable */
3578 /*-----------------------------------------------------------------*/
3579 static int resultRemat (iCode *ic)
3581 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3582 if (SKIP_IC(ic) || ic->op == IFX)
3585 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3586 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3587 if (sym->remat && !POINTER_SET(ic))
3594 #if defined(__BORLANDC__) || defined(_MSC_VER)
3595 #define STRCASECMP stricmp
3597 #define STRCASECMP strcasecmp
3601 /*-----------------------------------------------------------------*/
3602 /* inExcludeList - return 1 if the string is in exclude Reg list */
3603 /*-----------------------------------------------------------------*/
3604 static bool inExcludeList(char *s)
3606 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3609 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3610 if (options.excludeRegs[i] &&
3611 STRCASECMP(options.excludeRegs[i],"none") == 0)
3614 for ( i = 0 ; options.excludeRegs[i]; i++) {
3615 if (options.excludeRegs[i] &&
3616 STRCASECMP(s,options.excludeRegs[i]) == 0)
3623 /*-----------------------------------------------------------------*/
3624 /* genFunction - generated code for function entry */
3625 /*-----------------------------------------------------------------*/
3626 static void genFunction (iCode *ic)
3632 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3634 pic16_labelOffset += (max_key+4);
3639 ftype = operandType(IC_LEFT(ic));
3640 sym = OP_SYMBOL(IC_LEFT(ic));
3642 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3643 /* create an absolute section at the interrupt vector:
3644 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3649 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3651 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3652 sprintf(asymname, "ivec_%s", sym->name);
3654 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3656 /* when an interrupt is declared as naked, do not emit the special
3657 * wrapper segment at vector address. The user should take care for
3658 * this instead. -- VR */
3660 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3661 asym = newSymbol(asymname, 0);
3662 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3663 pic16_addpBlock( apb );
3665 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3666 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3667 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3668 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3669 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3671 /* mark the end of this tiny function */
3672 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3674 sprintf(asymname, "%s", sym->rname);
3680 abSym = Safe_calloc(1, sizeof(absSym));
3681 strcpy(abSym->name, asymname);
3683 switch( FUNC_INTNO(sym->type) ) {
3684 case 0: abSym->address = 0x000000; break;
3685 case 1: abSym->address = 0x000008; break;
3686 case 2: abSym->address = 0x000018; break;
3689 // fprintf(stderr, "no interrupt number is given\n");
3690 abSym->address = -1; break;
3693 /* relocate interrupt vectors if needed */
3694 if(abSym->address != -1)
3695 abSym->address += pic16_options.ivt_loc;
3697 addSet(&absSymSet, abSym);
3701 /* create the function header */
3702 pic16_emitcode(";","-----------------------------------------");
3703 pic16_emitcode(";"," function %s",sym->name);
3704 pic16_emitcode(";","-----------------------------------------");
3706 pic16_emitcode("","%s:",sym->rname);
3707 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3712 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3713 if(!strcmp(ab->name, sym->rname)) {
3714 pic16_pBlockConvert2Absolute(pb);
3720 if(IFFUNC_ISNAKED(ftype)) {
3721 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3725 /* if critical function then turn interrupts off */
3726 if (IFFUNC_ISCRITICAL(ftype)) {
3727 //pic16_emitcode("clr","ea");
3730 currFunc = sym; /* update the currFunc symbol */
3731 _G.fregsUsed = sym->regsUsed;
3732 _G.sregsAlloc = newBitVect(128);
3735 /* if this is an interrupt service routine then
3736 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3737 if (IFFUNC_ISISR(sym->type)) {
3738 _G.usefastretfie = 1; /* use shadow registers by default */
3740 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3741 if(!FUNC_ISSHADOWREGS(sym->type)) {
3742 /* do not save WREG,STATUS,BSR for high priority interrupts
3743 * because they are stored in the hardware shadow registers already */
3744 _G.usefastretfie = 0;
3745 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3746 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3747 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3750 /* these should really be optimized somehow, because not all
3751 * interrupt handlers modify them */
3752 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3753 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3757 // pic16_pBlockConvert2ISR(pb);
3760 /* emit code to setup stack frame if user enabled,
3761 * and function is not main() */
3763 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3764 if(strcmp(sym->name, "main")) {
3766 || !options.ommitFramePtr
3768 || IFFUNC_ARGS(sym->type)
3769 || FUNC_HASSTACKPARM(sym->etype)
3771 /* setup the stack frame */
3772 if(STACK_MODEL_LARGE)
3773 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3774 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3776 if(STACK_MODEL_LARGE)
3777 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3778 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3782 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3785 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3787 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3788 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3790 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3793 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3794 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3801 /* if callee-save to be used for this function
3802 * then save the registers being used in this function */
3803 // if (IFFUNC_CALLEESAVES(sym->type))
3804 if(strcmp(sym->name, "main")) {
3807 /* if any registers used */
3808 if (sym->regsUsed) {
3809 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3812 /* save the registers used */
3813 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3814 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3815 if (bitVectBitValue(sym->regsUsed,i)) {
3817 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3819 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3822 if(!pic16_regWithIdx(i)->wasUsed) {
3823 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3824 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3825 pic16_regWithIdx(i)->wasUsed = 1;
3832 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3833 for(i=0;i<sym->regsUsed->size;i++) {
3834 if(bitVectBitValue(sym->regsUsed, i)) {
3839 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3842 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3847 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3848 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3851 /*-----------------------------------------------------------------*/
3852 /* genEndFunction - generates epilogue for functions */
3853 /*-----------------------------------------------------------------*/
3854 static void genEndFunction (iCode *ic)
3856 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3860 if(IFFUNC_ISNAKED(sym->type)) {
3861 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3867 /* add code for ISCRITICAL */
3868 if(IFFUNC_ISCRITICAL(sym->type)) {
3869 /* if critical function, turn on interrupts */
3871 /* TODO: add code here -- VR */
3874 // sym->regsUsed = _G.fregsUsed;
3876 /* now we need to restore the registers */
3877 /* if any registers used */
3879 /* first restore registers that might be used for stack access */
3880 if(_G.sregsAllocSet) {
3883 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3884 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3885 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3889 if (strcmp(sym->name, "main") && sym->regsUsed) {
3892 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3893 /* restore registers used */
3894 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3895 for ( i = sym->regsUsed->size; i >= 0; i--) {
3896 if (bitVectBitValue(sym->regsUsed,i)) {
3897 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3901 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3906 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3908 if (sym->stack == 1) {
3909 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3910 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3912 // we have to add more than one...
3913 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3914 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3915 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3917 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3918 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3919 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3923 if(strcmp(sym->name, "main")) {
3925 || !options.ommitFramePtr
3927 || IFFUNC_ARGS(sym->type)
3928 || FUNC_HASSTACKPARM(sym->etype)
3930 /* restore stack frame */
3931 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3932 if(STACK_MODEL_LARGE)
3933 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3939 if (IFFUNC_ISISR(sym->type)) {
3940 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3941 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3942 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3943 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3945 if(!FUNC_ISSHADOWREGS(sym->type)) {
3946 /* do not restore interrupt vector for WREG,STATUS,BSR
3947 * for high priority interrupt, see genFunction */
3948 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3949 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3950 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3952 // _G.interruptvector = 0; /* sanity check */
3955 /* if debug then send end of function */
3956 /* if (options.debug && currFunc) */
3958 debugFile->writeEndFunction (currFunc, ic, 1);
3961 if(_G.usefastretfie)
3962 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3964 pic16_emitpcodeNULLop(POC_RETFIE);
3966 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3968 _G.usefastretfie = 0;
3972 if (IFFUNC_ISCRITICAL(sym->type)) {
3973 pic16_emitcode("setb","ea");
3976 /* if debug then send end of function */
3978 debugFile->writeEndFunction (currFunc, ic, 1);
3981 /* insert code to restore stack frame, if user enabled it
3982 * and function is not main() */
3985 pic16_emitpcodeNULLop(POC_RETURN);
3987 /* Mark the end of a function */
3988 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3992 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3994 unsigned long lit=1;
3999 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4000 if(AOP_TYPE(op) == AOP_LIT) {
4001 if(!IS_FLOAT(operandType( op ))) {
4002 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4005 unsigned long lit_int;
4009 /* take care if literal is a float */
4010 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4015 if (AOP_TYPE(op) == AOP_LIT) {
4016 /* FIXME: broken for
4017 * char __at(0x456) foo;
4019 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4020 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4021 } else if (AOP_TYPE(op) == AOP_PCODE
4022 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4023 /* char *s= "aaa"; return s; */
4024 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4025 * that the generic pointer is interpreted correctly
4026 * as referring to __code space, but this is fragile! */
4027 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4028 /* XXX: should check that dest != WREG */
4029 pic16_emitpcode(POC_MOVWF, dest);
4031 if(dest->type == PO_WREG && (offset == 0)) {
4032 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4035 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4039 /*-----------------------------------------------------------------*/
4040 /* genRet - generate code for return statement */
4041 /*-----------------------------------------------------------------*/
4042 static void genRet (iCode *ic)
4048 /* if we have no return value then
4049 * just generate the "ret" */
4054 /* we have something to return then
4055 * move the return value into place */
4056 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4057 size = AOP_SIZE(IC_LEFT(ic));
4061 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4064 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4067 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4069 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4072 /* >32-bits, setup stack and FSR0 */
4074 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4075 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4077 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4079 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4084 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4085 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4087 if(STACK_MODEL_LARGE) {
4088 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4089 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4091 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4096 /* old code, left here for reference -- VR */
4100 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4102 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4103 pic16_emitpcomment("push %s",l);
4106 DEBUGpic16_emitcode(";", "%d", __LINE__);
4107 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4108 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4110 if (strcmp(fReturn[offset],l)) {
4111 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4112 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4113 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4115 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4119 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4129 if (strcmp(fReturn[pushed],"a"))
4130 pic16_emitcode("pop",fReturn[pushed]);
4132 pic16_emitcode("pop","acc");
4138 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4141 /* generate a jump to the return label
4142 * if the next is not the return statement */
4143 if (!(ic->next && ic->next->op == LABEL
4144 && IC_LABEL(ic->next) == returnLabel)) {
4146 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4147 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4151 /*-----------------------------------------------------------------*/
4152 /* genLabel - generates a label */
4153 /*-----------------------------------------------------------------*/
4154 static void genLabel (iCode *ic)
4158 /* special case never generate */
4159 if (IC_LABEL(ic) == entryLabel)
4162 pic16_emitpLabel(IC_LABEL(ic)->key);
4163 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4166 /*-----------------------------------------------------------------*/
4167 /* genGoto - generates a goto */
4168 /*-----------------------------------------------------------------*/
4170 static void genGoto (iCode *ic)
4173 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4174 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4178 /*-----------------------------------------------------------------*/
4179 /* genMultbits :- multiplication of bits */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultbits (operand *left,
4187 if(!pic16_sameRegs(AOP(result),AOP(right)))
4188 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4190 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4191 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4192 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4197 /*-----------------------------------------------------------------*/
4198 /* genMultOneByte : 8 bit multiplication & division */
4199 /*-----------------------------------------------------------------*/
4200 static void genMultOneByte (operand *left,
4206 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4207 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4209 /* (if two literals, the value is computed before) */
4210 /* if one literal, literal on the right */
4211 if (AOP_TYPE(left) == AOP_LIT){
4217 /* size is already checked in genMult == 1 */
4218 // size = AOP_SIZE(result);
4220 if (AOP_TYPE(right) == AOP_LIT){
4221 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4222 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4223 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4224 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4226 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4227 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4228 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4229 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4232 pic16_genMult8X8_8 (left, right,result);
4235 /*-----------------------------------------------------------------*/
4236 /* genMultOneWord : 16 bit multiplication */
4237 /*-----------------------------------------------------------------*/
4238 static void genMultOneWord (operand *left,
4243 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4244 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4246 /* (if two literals, the value is computed before)
4247 * if one literal, literal on the right */
4248 if (AOP_TYPE(left) == AOP_LIT){
4254 /* size is checked already == 2 */
4255 // size = AOP_SIZE(result);
4257 if (AOP_TYPE(right) == AOP_LIT) {
4258 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4259 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4260 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4261 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4263 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4264 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4265 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4266 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4269 pic16_genMult16X16_16(left, right,result);
4272 /*-----------------------------------------------------------------*/
4273 /* genMultOneLong : 32 bit multiplication */
4274 /*-----------------------------------------------------------------*/
4275 static void genMultOneLong (operand *left,
4280 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4281 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4283 /* (if two literals, the value is computed before)
4284 * if one literal, literal on the right */
4285 if (AOP_TYPE(left) == AOP_LIT){
4291 /* size is checked already == 4 */
4292 // size = AOP_SIZE(result);
4294 if (AOP_TYPE(right) == AOP_LIT) {
4295 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4296 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4297 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4298 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4300 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4301 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4302 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4303 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4306 pic16_genMult32X32_32(left, right,result);
4311 /*-----------------------------------------------------------------*/
4312 /* genMult - generates code for multiplication */
4313 /*-----------------------------------------------------------------*/
4314 static void genMult (iCode *ic)
4316 operand *left = IC_LEFT(ic);
4317 operand *right = IC_RIGHT(ic);
4318 operand *result= IC_RESULT(ic);
4321 /* assign the amsops */
4322 pic16_aopOp (left,ic,FALSE);
4323 pic16_aopOp (right,ic,FALSE);
4324 pic16_aopOp (result,ic,TRUE);
4326 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4328 /* special cases first *
4330 if (AOP_TYPE(left) == AOP_CRY
4331 && AOP_TYPE(right)== AOP_CRY) {
4332 genMultbits(left,right,result);
4336 /* if both are of size == 1 */
4337 if(AOP_SIZE(left) == 1
4338 && AOP_SIZE(right) == 1) {
4339 genMultOneByte(left,right,result);
4343 /* if both are of size == 2 */
4344 if(AOP_SIZE(left) == 2
4345 && AOP_SIZE(right) == 2) {
4346 genMultOneWord(left, right, result);
4350 /* if both are of size == 4 */
4351 if(AOP_SIZE(left) == 4
4352 && AOP_SIZE(right) == 4) {
4353 genMultOneLong(left, right, result);
4357 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4360 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4361 /* should have been converted to function call */
4365 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4366 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4367 pic16_freeAsmop(result,NULL,ic,TRUE);
4370 /*-----------------------------------------------------------------*/
4371 /* genDivbits :- division of bits */
4372 /*-----------------------------------------------------------------*/
4373 static void genDivbits (operand *left,
4380 /* the result must be bit */
4381 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4382 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4386 pic16_emitcode("div","ab");
4387 pic16_emitcode("rrc","a");
4388 pic16_aopPut(AOP(result),"c",0);
4391 /*-----------------------------------------------------------------*/
4392 /* genDivOneByte : 8 bit division */
4393 /*-----------------------------------------------------------------*/
4394 static void genDivOneByte (operand *left,
4398 sym_link *opetype = operandType(result);
4403 /* result = divident / divisor
4404 * - divident may be a register or a literal,
4405 * - divisor may be a register or a literal,
4406 * so there are 3 cases (literal / literal is optimized
4407 * by the front-end) to handle.
4408 * In addition we must handle signed and unsigned, which
4409 * result in 6 final different cases -- VR */
4413 size = AOP_SIZE(result) - 1;
4415 /* signed or unsigned */
4416 if (SPEC_USIGN(opetype)) {
4417 pCodeOp *pct1, /* count */
4420 symbol *label1, *label2, *label3;;
4423 /* unsigned is easy */
4425 pct1 = pic16_popGetTempReg(1);
4426 pct2 = pic16_popGetTempReg(1);
4427 pct3 = pic16_popGetTempReg(1);
4429 label1 = newiTempLabel(NULL);
4430 label2 = newiTempLabel(NULL);
4431 label3 = newiTempLabel(NULL);
4433 /* the following algorithm is extracted from divuint.c */
4435 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4436 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4438 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4440 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4442 pic16_emitpLabel(label1->key);
4445 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4449 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4453 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4455 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4456 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4458 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4459 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4460 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4462 pic16_emitpLabel( label3->key );
4463 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4464 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4468 pic16_emitpLabel(label2->key);
4469 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4470 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4471 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4473 /* result is in wreg */
4474 if(AOP_TYPE(result) != AOP_ACC)
4475 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4477 pic16_popReleaseTempReg( pct3, 1);
4478 pic16_popReleaseTempReg( pct2, 1);
4479 pic16_popReleaseTempReg( pct1, 1);
4484 /* signed is a little bit more difficult */
4486 /* save the signs of the operands */
4487 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4489 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4490 pic16_emitcode("push","acc"); /* save it on the stack */
4492 /* now sign adjust for both left & right */
4493 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4495 lbl = newiTempLabel(NULL);
4496 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4497 pic16_emitcode("cpl","a");
4498 pic16_emitcode("inc","a");
4499 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4500 pic16_emitcode("mov","b,a");
4502 /* sign adjust left side */
4503 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4506 lbl = newiTempLabel(NULL);
4507 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4508 pic16_emitcode("cpl","a");
4509 pic16_emitcode("inc","a");
4510 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4512 /* now the division */
4513 pic16_emitcode("div","ab");
4514 /* we are interested in the lower order
4516 pic16_emitcode("mov","b,a");
4517 lbl = newiTempLabel(NULL);
4518 pic16_emitcode("pop","acc");
4519 /* if there was an over flow we don't
4520 adjust the sign of the result */
4521 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4522 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4524 pic16_emitcode("clr","a");
4525 pic16_emitcode("subb","a,b");
4526 pic16_emitcode("mov","b,a");
4527 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4529 /* now we are done */
4530 pic16_aopPut(AOP(result),"b",0);
4532 pic16_emitcode("mov","c,b.7");
4533 pic16_emitcode("subb","a,acc");
4536 pic16_aopPut(AOP(result),"a",offset++);
4540 /*-----------------------------------------------------------------*/
4541 /* genDiv - generates code for division */
4542 /*-----------------------------------------------------------------*/
4543 static void genDiv (iCode *ic)
4545 operand *left = IC_LEFT(ic);
4546 operand *right = IC_RIGHT(ic);
4547 operand *result= IC_RESULT(ic);
4550 /* Division is a very lengthy algorithm, so it is better
4551 * to call support routines than inlining algorithm.
4552 * Division functions written here just in case someone
4553 * wants to inline and not use the support libraries -- VR */
4557 /* assign the amsops */
4558 pic16_aopOp (left,ic,FALSE);
4559 pic16_aopOp (right,ic,FALSE);
4560 pic16_aopOp (result,ic,TRUE);
4562 /* special cases first */
4564 if (AOP_TYPE(left) == AOP_CRY &&
4565 AOP_TYPE(right)== AOP_CRY) {
4566 genDivbits(left,right,result);
4570 /* if both are of size == 1 */
4571 if (AOP_SIZE(left) == 1 &&
4572 AOP_SIZE(right) == 1 ) {
4573 genDivOneByte(left,right,result);
4577 /* should have been converted to function call */
4580 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4581 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4582 pic16_freeAsmop(result,NULL,ic,TRUE);
4585 /*-----------------------------------------------------------------*/
4586 /* genModbits :- modulus of bits */
4587 /*-----------------------------------------------------------------*/
4588 static void genModbits (operand *left,
4596 werror(W_POSSBUG2, __FILE__, __LINE__);
4597 /* the result must be bit */
4598 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4599 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4603 pic16_emitcode("div","ab");
4604 pic16_emitcode("mov","a,b");
4605 pic16_emitcode("rrc","a");
4606 pic16_aopPut(AOP(result),"c",0);
4609 /*-----------------------------------------------------------------*/
4610 /* genModOneByte : 8 bit modulus */
4611 /*-----------------------------------------------------------------*/
4612 static void genModOneByte (operand *left,
4616 sym_link *opetype = operandType(result);
4621 werror(W_POSSBUG2, __FILE__, __LINE__);
4623 /* signed or unsigned */
4624 if (SPEC_USIGN(opetype)) {
4625 /* unsigned is easy */
4626 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4627 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4629 pic16_emitcode("div","ab");
4630 pic16_aopPut(AOP(result),"b",0);
4634 /* signed is a little bit more difficult */
4636 /* save the signs of the operands */
4637 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4640 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4641 pic16_emitcode("push","acc"); /* save it on the stack */
4643 /* now sign adjust for both left & right */
4644 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4647 lbl = newiTempLabel(NULL);
4648 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4649 pic16_emitcode("cpl","a");
4650 pic16_emitcode("inc","a");
4651 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4652 pic16_emitcode("mov","b,a");
4654 /* sign adjust left side */
4655 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4658 lbl = newiTempLabel(NULL);
4659 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4660 pic16_emitcode("cpl","a");
4661 pic16_emitcode("inc","a");
4662 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4664 /* now the multiplication */
4665 pic16_emitcode("div","ab");
4666 /* we are interested in the lower order
4668 lbl = newiTempLabel(NULL);
4669 pic16_emitcode("pop","acc");
4670 /* if there was an over flow we don't
4671 adjust the sign of the result */
4672 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4673 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4675 pic16_emitcode("clr","a");
4676 pic16_emitcode("subb","a,b");
4677 pic16_emitcode("mov","b,a");
4678 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4680 /* now we are done */
4681 pic16_aopPut(AOP(result),"b",0);
4685 /*-----------------------------------------------------------------*/
4686 /* genMod - generates code for division */
4687 /*-----------------------------------------------------------------*/
4688 static void genMod (iCode *ic)
4690 operand *left = IC_LEFT(ic);
4691 operand *right = IC_RIGHT(ic);
4692 operand *result= IC_RESULT(ic);
4696 /* assign the amsops */
4697 pic16_aopOp (left,ic,FALSE);
4698 pic16_aopOp (right,ic,FALSE);
4699 pic16_aopOp (result,ic,TRUE);
4701 /* special cases first */
4703 if (AOP_TYPE(left) == AOP_CRY &&
4704 AOP_TYPE(right)== AOP_CRY) {
4705 genModbits(left,right,result);
4709 /* if both are of size == 1 */
4710 if (AOP_SIZE(left) == 1 &&
4711 AOP_SIZE(right) == 1 ) {
4712 genModOneByte(left,right,result);
4716 /* should have been converted to function call */
4720 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4721 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4722 pic16_freeAsmop(result,NULL,ic,TRUE);
4725 /*-----------------------------------------------------------------*/
4726 /* genIfxJump :- will create a jump depending on the ifx */
4727 /*-----------------------------------------------------------------*/
4729 note: May need to add parameter to indicate when a variable is in bit space.
4731 static void genIfxJump (iCode *ic, char *jval)
4735 /* if true label then we jump if condition
4737 if ( IC_TRUE(ic) ) {
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_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4748 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4749 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4753 /* false label is present */
4754 if(strcmp(jval,"a") == 0)
4756 else if (strcmp(jval,"c") == 0)
4759 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4760 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4763 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4764 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4769 /* mark the icode as generated */
4773 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4777 /* if true label then we jump if condition
4779 if ( IC_TRUE(ic) ) {
4780 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4781 pic16_emitpcode(POC_BTFSC, jop);
4783 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4784 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4787 /* false label is present */
4788 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4789 pic16_emitpcode(POC_BTFSS, jop);
4791 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4792 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4796 /* mark the icode as generated */
4803 /*-----------------------------------------------------------------*/
4805 /*-----------------------------------------------------------------*/
4806 static void genSkip(iCode *ifx,int status_bit)
4808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4812 if ( IC_TRUE(ifx) ) {
4813 switch(status_bit) {
4828 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4829 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4833 switch(status_bit) {
4847 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4848 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4855 /*-----------------------------------------------------------------*/
4857 /*-----------------------------------------------------------------*/
4858 static void genSkipc(resolvedIfx *rifx)
4860 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4870 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4871 rifx->generated = 1;
4874 #if !(USE_SIMPLE_GENCMP)
4875 /*-----------------------------------------------------------------*/
4877 /*-----------------------------------------------------------------*/
4878 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4880 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4885 if( (rifx->condition ^ invert_condition) & 1)
4890 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4891 rifx->generated = 1;
4896 /*-----------------------------------------------------------------*/
4898 /*-----------------------------------------------------------------*/
4899 static void genSkipz(iCode *ifx, int condition)
4910 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4912 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4915 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4917 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4922 #if !(USE_SIMPLE_GENCMP)
4923 /*-----------------------------------------------------------------*/
4925 /*-----------------------------------------------------------------*/
4926 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4932 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4934 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4937 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4938 rifx->generated = 1;
4943 /*-----------------------------------------------------------------*/
4944 /* genChkZeroes :- greater or less than comparison */
4945 /* For each byte in a literal that is zero, inclusive or the */
4946 /* the corresponding byte in the operand with W */
4947 /* returns true if any of the bytes are zero */
4948 /*-----------------------------------------------------------------*/
4949 static int genChkZeroes(operand *op, int lit, int size)
4956 i = (lit >> (size*8)) & 0xff;
4960 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4962 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4972 /*-----------------------------------------------------------------*/
4973 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4974 /* aop (if it's NOT a literal) or from lit (if */
4975 /* aop is a literal) */
4976 /*-----------------------------------------------------------------*/
4977 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4978 if (aop->type == AOP_LIT) {
4979 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4981 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4985 /*-----------------------------------------------------------------*/
4986 /* genCmp :- greater or less than comparison */
4987 /*-----------------------------------------------------------------*/
4989 #if USE_SIMPLE_GENCMP /* { */
4991 /* genCmp performs a left < right comparison, stores
4992 * the outcome in result (if != NULL) and generates
4993 * control flow code for the ifx (if != NULL).
4995 * This version leaves in sequences like
4996 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4997 * which should be optmized by the peephole
4998 * optimizer - RN 2005-01-01 */
4999 static void genCmp (operand *left,operand *right,
5000 operand *result, iCode *ifx, int sign)
5013 assert (left && right);
5014 assert (AOP_SIZE(left) == AOP_SIZE(right));
5016 size = AOP_SIZE(right) - 1;
5017 mask = (0x100UL << (size*8)) - 1;
5018 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5023 resolveIfx (&rIfx, ifx);
5025 /* handle for special cases */
5026 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5029 /**********************************************************************
5030 * handle bits - bit compares are promoted to int compares seemingly! *
5031 **********************************************************************/
5033 // THIS IS COMPLETELY UNTESTED!
5034 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5035 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5036 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5037 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5040 // 1 < {0,1} is false --> clear C by skipping the next instruction
5041 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5042 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5043 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5044 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5045 emitCLRC; // only skipped for left=0 && right=1
5047 goto correct_result_in_carry;
5051 /*************************************************
5052 * make sure that left is register (or the like) *
5053 *************************************************/
5054 if (!isAOP_REGlike(left)) {
5055 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5056 assert (isAOP_LIT(left));
5057 assert (isAOP_REGlike(right));
5058 // swap left and right
5059 // left < right <==> right > left <==> (right >= left + 1)
5060 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5062 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5063 // MAXVALUE < right? always false
5064 if (performedLt) emitCLRC; else emitSETC;
5065 goto correct_result_in_carry;
5068 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5069 // that's why we handled it above.
5076 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5077 } else if (isAOP_LIT(right)) {
5078 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5081 assert (isAOP_REGlike(left)); // left must be register or the like
5082 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5084 /*************************************************
5085 * special cases go here *
5086 *************************************************/
5088 if (isAOP_LIT(right)) {
5090 // unsigned comparison to a literal
5091 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5093 // unsigned left < 0? always false
5094 if (performedLt) emitCLRC; else emitSETC;
5095 goto correct_result_in_carry;
5098 // signed comparison to a literal
5099 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5100 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5101 // signed left < 0x80000000? always false
5102 if (performedLt) emitCLRC; else emitSETC;
5103 goto correct_result_in_carry;
5104 } else if (lit == 0) {
5105 // compare left < 0; set CARRY if SIGNBIT(left) is set
5106 if (performedLt) emitSETC; else emitCLRC;
5107 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5108 if (performedLt) emitCLRC; else emitSETC;
5109 goto correct_result_in_carry;
5112 } // right is literal
5114 /*************************************************
5115 * perform a general case comparison *
5116 * make sure we get CARRY==1 <==> left >= right *
5117 *************************************************/
5118 // compare most significant bytes
5119 //DEBUGpc ("comparing bytes at offset %d", size);
5121 // unsigned comparison
5122 mov2w_regOrLit (AOP(right), lit, size);
5123 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5125 // signed comparison
5126 // (add 2^n to both operands then perform an unsigned comparison)
5127 if (isAOP_LIT(right)) {
5128 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5129 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5131 if (litbyte == 0x80) {
5132 // left >= 0x80 -- always true, but more bytes to come
5133 pic16_mov2w (AOP(left), size);
5134 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5137 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5138 pic16_mov2w (AOP(left), size);
5139 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5140 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5143 /* using PRODL as a temporary register here */
5144 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5145 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5146 pic16_mov2w (AOP(left), size);
5147 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5148 pic16_emitpcode (POC_MOVWF, pctemp);
5149 pic16_mov2w (AOP(right), size);
5150 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5151 pic16_emitpcode (POC_SUBFW, pctemp);
5152 //pic16_popReleaseTempReg(pctemp, 1);
5156 // compare remaining bytes (treat as unsigned case from above)
5157 templbl = newiTempLabel ( NULL );
5160 //DEBUGpc ("comparing bytes at offset %d", offs);
5161 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5162 mov2w_regOrLit (AOP(right), lit, offs);
5163 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5165 pic16_emitpLabel (templbl->key);
5166 goto result_in_carry;
5170 /****************************************************
5171 * now CARRY contains the result of the comparison: *
5172 * SUBWF sets CARRY iff *
5173 * F-W >= 0 <==> F >= W <==> !(F < W) *
5174 * (F=left, W=right) *
5175 ****************************************************/
5178 if (result && AOP_TYPE(result) != AOP_CRY) {
5179 // value will be stored
5182 // value wil only be used in the following genSkipc()
5183 rIfx.condition ^= 1;
5187 correct_result_in_carry:
5189 // assign result to variable (if neccessary)
5190 if (result && AOP_TYPE(result) != AOP_CRY) {
5191 //DEBUGpc ("assign result");
5192 size = AOP_SIZE(result);
5194 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5196 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5199 // perform conditional jump
5201 //DEBUGpc ("generate control flow");
5210 static void genCmp (operand *left,operand *right,
5211 operand *result, iCode *ifx, int sign)
5213 int size; //, offset = 0 ;
5214 unsigned long lit = 0L,i = 0;
5215 resolvedIfx rFalseIfx;
5216 // resolvedIfx rTrueIfx;
5218 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5221 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5222 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5228 resolveIfx(&rFalseIfx,ifx);
5229 truelbl = newiTempLabel(NULL);
5230 size = max(AOP_SIZE(left),AOP_SIZE(right));
5232 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5236 /* if literal is on the right then swap with left */
5237 if ((AOP_TYPE(right) == AOP_LIT)) {
5238 operand *tmp = right ;
5239 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5240 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5243 lit = (lit - 1) & mask;
5246 rFalseIfx.condition ^= 1;
5249 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5250 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5254 //if(IC_TRUE(ifx) == NULL)
5255 /* if left & right are bit variables */
5256 if (AOP_TYPE(left) == AOP_CRY &&
5257 AOP_TYPE(right) == AOP_CRY ) {
5258 assert (0 && "bit variables used in genCmp");
5259 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5260 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5262 /* subtract right from left if at the
5263 end the carry flag is set then we know that
5264 left is greater than right */
5266 symbol *lbl = newiTempLabel(NULL);
5269 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5270 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5274 if(AOP_TYPE(right) == AOP_LIT) {
5276 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5278 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5285 genSkipCond(&rFalseIfx,left,size-1,7);
5287 /* no need to compare to 0...*/
5288 /* NOTE: this is a de-generate compare that most certainly
5289 * creates some dead code. */
5290 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5292 if(ifx) ifx->generated = 1;
5299 //i = (lit >> (size*8)) & 0xff;
5300 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5302 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5304 i = ((0-lit) & 0xff);
5307 /* lit is 0x7f, all signed chars are less than
5308 * this except for 0x7f itself */
5309 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5310 genSkipz2(&rFalseIfx,0);
5312 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5313 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5314 genSkipc(&rFalseIfx);
5319 genSkipz2(&rFalseIfx,1);
5321 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5322 genSkipc(&rFalseIfx);
5326 if(ifx) ifx->generated = 1;
5330 /* chars are out of the way. now do ints and longs */
5333 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5340 genSkipCond(&rFalseIfx,left,size,7);
5341 if(ifx) ifx->generated = 1;
5346 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5348 //rFalseIfx.condition ^= 1;
5349 //genSkipCond(&rFalseIfx,left,size,7);
5350 //rFalseIfx.condition ^= 1;
5352 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5353 if(rFalseIfx.condition)
5354 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5356 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5358 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5359 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5360 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5363 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5365 if(rFalseIfx.condition) {
5367 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5373 genSkipc(&rFalseIfx);
5374 pic16_emitpLabel(truelbl->key);
5375 if(ifx) ifx->generated = 1;
5382 if( (lit & 0xff) == 0) {
5383 /* lower byte is zero */
5384 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5385 i = ((lit >> 8) & 0xff) ^0x80;
5386 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5387 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5388 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5389 genSkipc(&rFalseIfx);
5392 if(ifx) ifx->generated = 1;
5397 /* Special cases for signed longs */
5398 if( (lit & 0xffffff) == 0) {
5399 /* lower byte is zero */
5400 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5401 i = ((lit >> 8*3) & 0xff) ^0x80;
5402 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5403 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5404 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5405 genSkipc(&rFalseIfx);
5408 if(ifx) ifx->generated = 1;
5416 if(lit & (0x80 << (size*8))) {
5417 /* lit is negative */
5418 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420 //genSkipCond(&rFalseIfx,left,size,7);
5422 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5424 if(rFalseIfx.condition)
5425 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5427 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5431 /* lit is positive */
5432 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5433 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5434 if(rFalseIfx.condition)
5435 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5437 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5442 This works, but is only good for ints.
5443 It also requires a "known zero" register.
5444 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5445 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5446 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5447 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5448 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5449 genSkipc(&rFalseIfx);
5451 pic16_emitpLabel(truelbl->key);
5452 if(ifx) ifx->generated = 1;
5456 /* There are no more special cases, so perform a general compare */
5458 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5459 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5463 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5465 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5467 //rFalseIfx.condition ^= 1;
5468 genSkipc(&rFalseIfx);
5470 pic16_emitpLabel(truelbl->key);
5472 if(ifx) ifx->generated = 1;
5479 /* sign is out of the way. So now do an unsigned compare */
5480 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5483 /* General case - compare to an unsigned literal on the right.*/
5485 i = (lit >> (size*8)) & 0xff;
5486 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5487 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5489 i = (lit >> (size*8)) & 0xff;
5492 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5494 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5496 /* this byte of the lit is zero,
5497 *if it's not the last then OR in the variable */
5499 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5504 pic16_emitpLabel(lbl->key);
5505 // pic16_emitpLabel(truelbl->key);
5506 //if(emitFinalCheck)
5507 genSkipc(&rFalseIfx);
5509 pic16_emitpLabel(truelbl->key);
5511 if(ifx) ifx->generated = 1;
5518 if(AOP_TYPE(left) == AOP_LIT) {
5519 //symbol *lbl = newiTempLabel(NULL);
5521 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5524 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5527 if((lit == 0) && (sign == 0)){
5530 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5532 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5534 genSkipz2(&rFalseIfx,0);
5535 if(ifx) ifx->generated = 1;
5542 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5543 /* degenerate compare can never be true */
5544 if(rFalseIfx.condition == 0)
5545 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5547 if(ifx) ifx->generated = 1;
5552 /* signed comparisons to a literal byte */
5554 int lp1 = (lit+1) & 0xff;
5556 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5559 rFalseIfx.condition ^= 1;
5560 genSkipCond(&rFalseIfx,right,0,7);
5563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5565 genSkipz2(&rFalseIfx,1);
5568 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5569 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5570 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5571 rFalseIfx.condition ^= 1;
5572 genSkipc(&rFalseIfx);
5576 /* unsigned comparisons to a literal byte */
5578 switch(lit & 0xff ) {
5580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5581 genSkipz2(&rFalseIfx,0);
5584 rFalseIfx.condition ^= 1;
5585 genSkipCond(&rFalseIfx,right,0,7);
5589 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5590 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5591 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5592 rFalseIfx.condition ^= 1;
5593 if (AOP_TYPE(result) == AOP_CRY)
5594 genSkipc(&rFalseIfx);
5596 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5597 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5603 if(ifx) ifx->generated = 1;
5604 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5610 /* Size is greater than 1 */
5618 /* this means lit = 0xffffffff, or -1 */
5621 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5622 rFalseIfx.condition ^= 1;
5623 genSkipCond(&rFalseIfx,right,size,7);
5624 if(ifx) ifx->generated = 1;
5626 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5635 if(rFalseIfx.condition) {
5636 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5637 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5640 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5642 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5646 if(rFalseIfx.condition) {
5647 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5648 pic16_emitpLabel(truelbl->key);
5650 rFalseIfx.condition ^= 1;
5651 genSkipCond(&rFalseIfx,right,s,7);
5654 if(ifx) ifx->generated = 1;
5656 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5662 if((size == 1) && (0 == (lp1&0xff))) {
5663 /* lower byte of signed word is zero */
5664 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5665 i = ((lp1 >> 8) & 0xff) ^0x80;
5666 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5667 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5668 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5670 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5672 if(ifx) ifx->generated = 1;
5675 rFalseIfx.condition ^= 1;
5676 genSkipc(&rFalseIfx);
5677 if(ifx) ifx->generated = 1;
5683 if(lit & (0x80 << (size*8))) {
5684 /* Lit is less than zero */
5685 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5686 //rFalseIfx.condition ^= 1;
5687 //genSkipCond(&rFalseIfx,left,size,7);
5688 //rFalseIfx.condition ^= 1;
5689 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5690 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5692 if(rFalseIfx.condition)
5693 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5699 /* Lit is greater than or equal to zero */
5700 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5701 //rFalseIfx.condition ^= 1;
5702 //genSkipCond(&rFalseIfx,right,size,7);
5703 //rFalseIfx.condition ^= 1;
5705 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5706 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5708 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5709 if(rFalseIfx.condition)
5710 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5712 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5716 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5717 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5723 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5725 rFalseIfx.condition ^= 1;
5726 //rFalseIfx.condition = 1;
5727 genSkipc(&rFalseIfx);
5729 pic16_emitpLabel(truelbl->key);
5731 if(ifx) ifx->generated = 1;
5734 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5741 /* compare word or long to an unsigned literal on the right.*/
5746 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5749 break; /* handled above */
5752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5754 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5755 genSkipz2(&rFalseIfx,0);
5759 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5761 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5764 if(rFalseIfx.condition)
5765 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5767 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5771 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5773 rFalseIfx.condition ^= 1;
5774 genSkipc(&rFalseIfx);
5777 pic16_emitpLabel(truelbl->key);
5779 if(ifx) ifx->generated = 1;
5781 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5789 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5790 i = (lit >> (size*8)) & 0xff;
5792 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5793 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5796 i = (lit >> (size*8)) & 0xff;
5799 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5801 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5803 /* this byte of the lit is zero,
5804 * if it's not the last then OR in the variable */
5806 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5811 pic16_emitpLabel(lbl->key);
5813 rFalseIfx.condition ^= 1;
5815 genSkipc(&rFalseIfx);
5819 pic16_emitpLabel(truelbl->key);
5820 if(ifx) ifx->generated = 1;
5822 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5828 /* Compare two variables */
5830 DEBUGpic16_emitcode(";sign","%d",sign);
5834 /* Sigh. thus sucks... */
5838 pctemp = pic16_popGetTempReg(1);
5839 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5840 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5841 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5842 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5843 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5844 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5845 pic16_popReleaseTempReg(pctemp, 1);
5847 /* Signed char comparison */
5848 /* Special thanks to Nikolai Golovchenko for this snippet */
5849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5850 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5851 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5852 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5853 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5854 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5856 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5857 genSkipc(&rFalseIfx);
5859 if(ifx) ifx->generated = 1;
5861 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5869 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5870 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5874 /* The rest of the bytes of a multi-byte compare */
5878 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5881 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5882 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5887 pic16_emitpLabel(lbl->key);
5889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5890 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5891 (AOP_TYPE(result) == AOP_REG)) {
5892 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5893 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5895 genSkipc(&rFalseIfx);
5897 //genSkipc(&rFalseIfx);
5898 if(ifx) ifx->generated = 1;
5901 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5909 if ((AOP_TYPE(result) != AOP_CRY)
5910 && AOP_SIZE(result)) {
5911 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5913 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5915 pic16_outBitC(result);
5917 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5918 /* if the result is used in the next
5919 ifx conditional branch then generate
5920 code a little differently */
5922 genIfxJump (ifx,"c");
5924 pic16_outBitC(result);
5925 /* leave the result in acc */
5930 #elif 0 /* VR version of genCmp() */ /* } else { */
5932 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5933 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5934 operand *result, int offset, int invert_op)
5938 /* check condition, > or < ?? */
5939 if(rIfx->condition != 0)invert_op ^= 1;
5941 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5943 if(!ifx)invert_op ^= 1;
5945 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5946 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5949 if(!invert_op)return POC_CPFSGT;
5950 else return POC_CPFSLT;
5953 static int compareAopfirstpass=1;
5955 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5956 operand *oper, int offset, operand *result,
5957 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5963 /* invert if there is a result to be loaded, in order to fit,
5964 * SETC/CLRC sequence */
5965 if(AOP_SIZE(result))invert_op ^= 1;
5967 // if(sign && !offset)invert_op ^= 1;
5969 // if(sign)invert_op ^= 1;
5971 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5973 if(AOP_SIZE(result) && compareAopfirstpass) {
5976 pic16_emitpcode(POC_SETF, pcop2);
5981 pic16_emitpcode(POC_CLRF, pcop2);
5987 compareAopfirstpass = 0;
5989 /* there is a bug when comparing operands with size > 1,
5990 * because higher bytes can be equal and test should be performed
5991 * to the next lower byte, current algorithm, considers operands
5992 * inequal in these cases! -- VR 20041107 */
5996 pic16_emitpcode(op, pcop);
5998 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6001 if((!sign || !offset) && AOP_SIZE(result)) {
6004 pic16_emitpcode(POC_CLRF, pcop2);
6009 pic16_emitpcode(POC_SETF, pcop2);
6014 /* don't emit final branch (offset == 0) */
6018 pic16_emitpcode(POC_RRCF, pcop2);
6020 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6023 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6024 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6025 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6027 truelbl = newiTempLabel( NULL );
6028 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6029 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6030 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6032 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6033 pic16_emitpLabel(truelbl->key);
6035 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6040 static void genCmp (operand *left, operand *right,
6041 operand *result, iCode *ifx, int sign)
6045 resolvedIfx rFalseIfx;
6046 symbol *falselbl, *tlbl;
6050 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6052 resolveIfx(&rFalseIfx, ifx);
6053 size = max(AOP_SIZE(left), AOP_SIZE(right));
6055 /* if left & right are bit variables */
6056 if(AOP_TYPE(left) == AOP_CRY
6057 && AOP_TYPE(right) == AOP_CRY ) {
6059 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6060 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6062 werror(W_POSSBUG2, __FILE__, __LINE__);
6066 /* if literal is on the right then swap with left */
6067 if((AOP_TYPE(right) == AOP_LIT)) {
6068 operand *tmp = right ;
6069 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6071 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6073 // lit = (lit - 1) & mask;
6076 rFalseIfx.condition ^= 1; /* reverse compare */
6078 if ((AOP_TYPE(left) == AOP_LIT)) {
6079 /* float compares are handled by support functions */
6080 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6083 /* actual comparing algorithm */
6084 // size = AOP_SIZE( right );
6086 falselbl = newiTempLabel( NULL );
6087 if(AOP_TYPE(left) == AOP_LIT) {
6088 /* compare to literal */
6089 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6092 pCodeOp *pct, *pct2;
6095 /* signed compare */
6096 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6098 /* using PRODL:PRODH as a temporary register here */
6099 pct = pic16_popCopyReg(&pic16_pc_prodl);
6100 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6101 tlbl = newiTempLabel( NULL );
6103 /* first compare signs:
6104 * a. if both are positive, compare just like unsigned
6105 * b. if both are negative, invert cmpop, compare just like unsigned
6106 * c. if different signs, determine the result directly */
6112 tlbl1 = newiTempLabel( NULL );
6113 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6117 /* literal is zero or positive:
6118 * a. if carry is zero, too, continue compare,
6119 * b. if carry is set, then continue depending on cmpop ^ condition:
6120 * 1. '<' return false (literal < variable),
6121 * 2. '>' return true (literal > variable) */
6122 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6123 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6126 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6131 /* literal is negative:
6132 * a. if carry is set, too, continue compare,
6133 * b. if carry is zero, then continue depending on cmpop ^ condition:
6134 * 1. '<' return true (literal < variable),
6135 * 2. '>' return false (literal > variable) */
6136 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6137 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6139 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6140 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6145 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6147 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6148 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6153 pic16_emitpLabel( tlbl1->key );
6156 compareAopfirstpass=1;
6157 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6158 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6159 // pic16_emitpcode(POC_MOVWF, pct);
6161 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6162 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6163 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6168 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6169 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6170 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6171 // pic16_emitpcode(POC_MOVWF, pct);
6173 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6174 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6175 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6176 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6177 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6180 if(ifx)ifx->generated = 1;
6182 if(AOP_SIZE(result)) {
6183 pic16_emitpLabel(tlbl->key);
6184 pic16_emitpLabel(falselbl->key);
6185 pic16_outBitOp( result, pct2 );
6187 pic16_emitpLabel(tlbl->key);
6191 /* unsigned compare */
6192 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6194 compareAopfirstpass=1;
6197 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6198 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6201 if(ifx)ifx->generated = 1;
6203 if(AOP_SIZE(result)) {
6204 pic16_emitpLabel(falselbl->key);
6205 pic16_outBitC( result );
6210 /* compare registers */
6211 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6215 pCodeOp *pct, *pct2;
6217 /* signed compare */
6218 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6220 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6221 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6222 tlbl = newiTempLabel( NULL );
6224 compareAopfirstpass=1;
6227 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6228 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230 pic16_emitpcode(POC_MOVWF, pct);
6232 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6233 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6234 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6236 /* WREG already holds left + 0x80 */
6237 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6240 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6241 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6242 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6243 pic16_emitpcode(POC_MOVWF, pct);
6245 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6246 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6247 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6249 /* WREG already holds left + 0x80 */
6250 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6251 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6254 if(ifx)ifx->generated = 1;
6256 if(AOP_SIZE(result)) {
6257 pic16_emitpLabel(tlbl->key);
6258 pic16_emitpLabel(falselbl->key);
6259 pic16_outBitOp( result, pct2 );
6261 pic16_emitpLabel(tlbl->key);
6265 /* unsigned compare */
6266 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6268 compareAopfirstpass=1;
6271 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6272 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6276 if(ifx)ifx->generated = 1;
6277 if(AOP_SIZE(result)) {
6279 pic16_emitpLabel(falselbl->key);
6280 pic16_outBitC( result );
6291 /*-----------------------------------------------------------------*/
6292 /* genCmpGt :- greater than comparison */
6293 /*-----------------------------------------------------------------*/
6294 static void genCmpGt (iCode *ic, iCode *ifx)
6296 operand *left, *right, *result;
6297 sym_link *letype , *retype;
6303 right= IC_RIGHT(ic);
6304 result = IC_RESULT(ic);
6306 letype = getSpec(operandType(left));
6307 retype =getSpec(operandType(right));
6308 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6309 /* assign the amsops */
6310 pic16_aopOp (left,ic,FALSE);
6311 pic16_aopOp (right,ic,FALSE);
6312 pic16_aopOp (result,ic,TRUE);
6314 genCmp(right, left, result, ifx, sign);
6316 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6317 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6318 pic16_freeAsmop(result,NULL,ic,TRUE);
6321 /*-----------------------------------------------------------------*/
6322 /* genCmpLt - less than comparisons */
6323 /*-----------------------------------------------------------------*/
6324 static void genCmpLt (iCode *ic, iCode *ifx)
6326 operand *left, *right, *result;
6327 sym_link *letype , *retype;
6333 right= IC_RIGHT(ic);
6334 result = IC_RESULT(ic);
6336 letype = getSpec(operandType(left));
6337 retype =getSpec(operandType(right));
6338 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6340 /* assign the amsops */
6341 pic16_aopOp (left,ic,FALSE);
6342 pic16_aopOp (right,ic,FALSE);
6343 pic16_aopOp (result,ic,TRUE);
6345 genCmp(left, right, result, ifx, sign);
6347 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6348 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6349 pic16_freeAsmop(result,NULL,ic,TRUE);
6354 // FIXME reenable literal optimisation when the pic16 port is stable
6356 /*-----------------------------------------------------------------*/
6357 /* genc16bit2lit - compare a 16 bit value to a literal */
6358 /*-----------------------------------------------------------------*/
6359 static void genc16bit2lit(operand *op, int lit, int offset)
6363 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6364 if( (lit&0xff) == 0)
6369 switch( BYTEofLONG(lit,i)) {
6371 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6374 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6377 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6380 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6381 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6386 switch( BYTEofLONG(lit,i)) {
6388 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6392 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6396 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6399 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6401 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6410 /*-----------------------------------------------------------------*/
6411 /* gencjneshort - compare and jump if not equal */
6412 /*-----------------------------------------------------------------*/
6413 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6415 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6417 int res_offset = 0; /* the result may be a different size then left or right */
6418 int res_size = AOP_SIZE(result);
6420 symbol *lbl, *lbl_done;
6422 unsigned long lit = 0L;
6423 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6425 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6426 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6428 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6429 resolveIfx(&rIfx,ifx);
6430 lbl = newiTempLabel(NULL);
6431 lbl_done = newiTempLabel(NULL);
6434 /* if the left side is a literal or
6435 if the right is in a pointer register and left
6437 if ((AOP_TYPE(left) == AOP_LIT) ||
6438 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6443 if(AOP_TYPE(right) == AOP_LIT)
6444 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6446 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6447 preserve_result = 1;
6449 if(result && !preserve_result)
6452 for(i = 0; i < AOP_SIZE(result); i++)
6453 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6457 /* if the right side is a literal then anything goes */
6458 if (AOP_TYPE(right) == AOP_LIT &&
6459 AOP_TYPE(left) != AOP_DIR ) {
6462 genc16bit2lit(left, lit, 0);
6464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6467 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6470 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6471 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6473 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6477 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6479 if(res_offset < res_size-1)
6487 /* if the right side is in a register or in direct space or
6488 if the left is a pointer register & right is not */
6489 else if (AOP_TYPE(right) == AOP_REG ||
6490 AOP_TYPE(right) == AOP_DIR ||
6491 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6492 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6493 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6494 int lbl_key = lbl->key;
6497 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6498 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6500 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6501 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6502 __FUNCTION__,__LINE__);
6506 /* switch(size) { */
6508 /* genc16bit2lit(left, lit, 0); */
6510 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6515 if((AOP_TYPE(left) == AOP_DIR) &&
6516 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6518 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6519 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6521 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6523 switch (lit & 0xff) {
6525 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6528 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6529 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6530 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6534 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6535 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6536 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6537 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6541 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6542 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6547 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6550 if(AOP_TYPE(result) == AOP_CRY) {
6551 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6556 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6558 /* fix me. probably need to check result size too */
6559 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6564 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6565 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6572 if(res_offset < res_size-1)
6577 } else if(AOP_TYPE(right) == AOP_REG &&
6578 AOP_TYPE(left) != AOP_DIR){
6581 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6582 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6583 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6588 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6590 if(res_offset < res_size-1)
6595 /* right is a pointer reg need both a & b */
6597 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6599 pic16_emitcode("mov","b,%s",l);
6600 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6601 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6606 if(result && preserve_result)
6609 for(i = 0; i < AOP_SIZE(result); i++)
6610 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6613 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6615 if(result && preserve_result)
6616 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6619 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6621 pic16_emitpLabel(lbl->key);
6623 if(result && preserve_result)
6626 for(i = 0; i < AOP_SIZE(result); i++)
6627 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6629 pic16_emitpLabel(lbl_done->key);
6632 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6640 /*-----------------------------------------------------------------*/
6641 /* gencjne - compare and jump if not equal */
6642 /*-----------------------------------------------------------------*/
6643 static void gencjne(operand *left, operand *right, iCode *ifx)
6645 symbol *tlbl = newiTempLabel(NULL);
6647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6648 gencjneshort(left, right, lbl);
6650 pic16_emitcode("mov","a,%s",one);
6651 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6652 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6653 pic16_emitcode("clr","a");
6654 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6656 pic16_emitpLabel(lbl->key);
6657 pic16_emitpLabel(tlbl->key);
6663 /*-----------------------------------------------------------------*/
6664 /* is_LitOp - check if operand has to be treated as literal */
6665 /*-----------------------------------------------------------------*/
6666 static bool is_LitOp(operand *op)
6668 return ((AOP_TYPE(op) == AOP_LIT)
6669 || ( (AOP_TYPE(op) == AOP_PCODE)
6670 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6671 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6674 /*-----------------------------------------------------------------*/
6675 /* is_LitAOp - check if operand has to be treated as literal */
6676 /*-----------------------------------------------------------------*/
6677 static bool is_LitAOp(asmop *aop)
6679 return ((aop->type == AOP_LIT)
6680 || ( (aop->type == AOP_PCODE)
6681 && ( (aop->aopu.pcop->type == PO_LITERAL)
6682 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6687 /*-----------------------------------------------------------------*/
6688 /* genCmpEq - generates code for equal to */
6689 /*-----------------------------------------------------------------*/
6690 static void genCmpEq (iCode *ic, iCode *ifx)
6692 operand *left, *right, *result;
6693 symbol *falselbl = newiTempLabel(NULL);
6694 symbol *donelbl = newiTempLabel(NULL);
6696 int preserve_result = 0;
6697 int generate_result = 0;
6699 unsigned long lit = -1;
6703 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6704 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6705 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6707 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6709 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6711 werror(W_POSSBUG2, __FILE__, __LINE__);
6712 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6713 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6717 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6719 operand *tmp = right ;
6724 if (AOP_TYPE(right) == AOP_LIT) {
6725 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6728 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6729 preserve_result = 1;
6731 if(result && AOP_SIZE(result))
6732 generate_result = 1;
6734 if(generate_result && !preserve_result)
6736 for(i = 0; i < AOP_SIZE(result); i++)
6737 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6740 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6741 for(i=0; i < AOP_SIZE(left); i++)
6743 if(AOP_TYPE(left) != AOP_ACC)
6746 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6750 if(is_LitOp(right)) {
6751 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6752 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6755 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6757 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6762 if(generate_result && preserve_result)
6764 for(i = 0; i < AOP_SIZE(result); i++)
6765 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6769 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6771 if(generate_result && preserve_result)
6772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6774 if(ifx && IC_TRUE(ifx))
6775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6777 if(ifx && IC_FALSE(ifx))
6778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6780 pic16_emitpLabel(falselbl->key);
6784 if(ifx && IC_FALSE(ifx))
6785 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6787 if(generate_result && preserve_result)
6789 for(i = 0; i < AOP_SIZE(result); i++)
6790 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6793 pic16_emitpLabel(donelbl->key);
6799 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6800 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6801 pic16_freeAsmop(result,NULL,ic,TRUE);
6807 // old version kept for reference
6809 /*-----------------------------------------------------------------*/
6810 /* genCmpEq - generates code for equal to */
6811 /*-----------------------------------------------------------------*/
6812 static void genCmpEq (iCode *ic, iCode *ifx)
6814 operand *left, *right, *result;
6815 unsigned long lit = 0L;
6817 symbol *falselbl = newiTempLabel(NULL);
6820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6823 DEBUGpic16_emitcode ("; ifx is non-null","");
6825 DEBUGpic16_emitcode ("; ifx is null","");
6827 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6828 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6829 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6831 size = max(AOP_SIZE(left),AOP_SIZE(right));
6833 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6835 /* if literal, literal on the right or
6836 if the right is in a pointer register and left
6838 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6839 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6840 operand *tmp = right ;
6846 if(ifx && !AOP_SIZE(result)){
6848 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6849 /* if they are both bit variables */
6850 if (AOP_TYPE(left) == AOP_CRY &&
6851 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6852 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6853 if(AOP_TYPE(right) == AOP_LIT){
6854 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6856 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6857 pic16_emitcode("cpl","c");
6858 } else if(lit == 1L) {
6859 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6861 pic16_emitcode("clr","c");
6863 /* AOP_TYPE(right) == AOP_CRY */
6865 symbol *lbl = newiTempLabel(NULL);
6866 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6867 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6868 pic16_emitcode("cpl","c");
6869 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6871 /* if true label then we jump if condition
6873 tlbl = newiTempLabel(NULL);
6874 if ( IC_TRUE(ifx) ) {
6875 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6876 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6878 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6879 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6881 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6884 /* left and right are both bit variables, result is carry */
6887 resolveIfx(&rIfx,ifx);
6889 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6890 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6891 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6892 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6897 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6899 /* They're not both bit variables. Is the right a literal? */
6900 if(AOP_TYPE(right) == AOP_LIT) {
6901 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6906 switch(lit & 0xff) {
6908 if ( IC_TRUE(ifx) ) {
6909 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6911 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6913 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6914 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6918 if ( IC_TRUE(ifx) ) {
6919 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6921 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6923 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6930 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6935 /* end of size == 1 */
6939 genc16bit2lit(left,lit,offset);
6942 /* end of size == 2 */
6947 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6948 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6949 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6950 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6953 /* search for patterns that can be optimized */
6955 genc16bit2lit(left,lit,0);
6959 emitSKPZ; // if hi word unequal
6961 emitSKPNZ; // if hi word equal
6963 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6964 genc16bit2lit(left,lit,2);
6967 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6968 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6972 pic16_emitpLabel(falselbl->key);
6981 } else if(AOP_TYPE(right) == AOP_CRY ) {
6982 /* we know the left is not a bit, but that the right is */
6983 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6984 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6985 pic16_popGet(AOP(right),offset));
6986 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6988 /* if the two are equal, then W will be 0 and the Z bit is set
6989 * we could test Z now, or go ahead and check the high order bytes if
6990 * the variable we're comparing is larger than a byte. */
6993 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6995 if ( IC_TRUE(ifx) ) {
6997 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6998 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7001 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7002 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7006 /* They're both variables that are larger than bits */
7009 tlbl = newiTempLabel(NULL);
7012 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7013 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7015 if ( IC_TRUE(ifx) ) {
7019 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7021 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7022 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7026 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7029 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7030 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7035 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7037 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7038 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7042 if(s>1 && IC_TRUE(ifx)) {
7043 pic16_emitpLabel(tlbl->key);
7044 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7048 /* mark the icode as generated */
7053 /* if they are both bit variables */
7054 if (AOP_TYPE(left) == AOP_CRY &&
7055 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7056 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7057 if(AOP_TYPE(right) == AOP_LIT){
7058 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7060 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7061 pic16_emitcode("cpl","c");
7062 } else if(lit == 1L) {
7063 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7065 pic16_emitcode("clr","c");
7067 /* AOP_TYPE(right) == AOP_CRY */
7069 symbol *lbl = newiTempLabel(NULL);
7070 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7071 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7072 pic16_emitcode("cpl","c");
7073 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7076 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7077 pic16_outBitC(result);
7081 genIfxJump (ifx,"c");
7084 /* if the result is used in an arithmetic operation
7085 then put the result in place */
7086 pic16_outBitC(result);
7089 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7090 gencjne(left,right,result,ifx);
7093 gencjne(left,right,newiTempLabel(NULL));
7095 if(IC_TRUE(ifx)->key)
7096 gencjne(left,right,IC_TRUE(ifx)->key);
7098 gencjne(left,right,IC_FALSE(ifx)->key);
7102 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7103 pic16_aopPut(AOP(result),"a",0);
7108 genIfxJump (ifx,"a");
7112 /* if the result is used in an arithmetic operation
7113 then put the result in place */
7115 if (AOP_TYPE(result) != AOP_CRY)
7116 pic16_outAcc(result);
7118 /* leave the result in acc */
7122 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7123 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7124 pic16_freeAsmop(result,NULL,ic,TRUE);
7128 /*-----------------------------------------------------------------*/
7129 /* ifxForOp - returns the icode containing the ifx for operand */
7130 /*-----------------------------------------------------------------*/
7131 static iCode *ifxForOp ( operand *op, iCode *ic )
7135 /* if true symbol then needs to be assigned */
7136 if (IS_TRUE_SYMOP(op))
7139 /* if this has register type condition and
7140 the next instruction is ifx with the same operand
7141 and live to of the operand is upto the ifx only then */
7143 && ic->next->op == IFX
7144 && IC_COND(ic->next)->key == op->key
7145 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7147 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7153 ic->next->op == IFX &&
7154 IC_COND(ic->next)->key == op->key) {
7155 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7160 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7162 ic->next->op == IFX)
7163 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7166 ic->next->op == IFX &&
7167 IC_COND(ic->next)->key == op->key) {
7168 DEBUGpic16_emitcode ("; "," key is okay");
7169 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7170 OP_SYMBOL(op)->liveTo,
7175 /* the code below is completely untested
7176 * it just allows ulong2fs.c compile -- VR */
7179 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7180 __FILE__, __FUNCTION__, __LINE__);
7182 /* if this has register type condition and
7183 the next instruction is ifx with the same operand
7184 and live to of the operand is upto the ifx only then */
7186 ic->next->op == IFX &&
7187 IC_COND(ic->next)->key == op->key &&
7188 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7192 ic->next->op == IFX &&
7193 IC_COND(ic->next)->key == op->key) {
7194 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7198 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7199 __FILE__, __FUNCTION__, __LINE__);
7201 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7206 /*-----------------------------------------------------------------*/
7207 /* genAndOp - for && operation */
7208 /*-----------------------------------------------------------------*/
7209 static void genAndOp (iCode *ic)
7211 operand *left,*right, *result;
7216 /* note here that && operations that are in an
7217 if statement are taken away by backPatchLabels
7218 only those used in arthmetic operations remain */
7219 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7220 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7221 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7223 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7225 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7226 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7227 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7229 /* if both are bit variables */
7230 /* if (AOP_TYPE(left) == AOP_CRY && */
7231 /* AOP_TYPE(right) == AOP_CRY ) { */
7232 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7233 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7234 /* pic16_outBitC(result); */
7236 /* tlbl = newiTempLabel(NULL); */
7237 /* pic16_toBoolean(left); */
7238 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7239 /* pic16_toBoolean(right); */
7240 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7241 /* pic16_outBitAcc(result); */
7244 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7245 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7246 pic16_freeAsmop(result,NULL,ic,TRUE);
7250 /*-----------------------------------------------------------------*/
7251 /* genOrOp - for || operation */
7252 /*-----------------------------------------------------------------*/
7255 modified this code, but it doesn't appear to ever get called
7258 static void genOrOp (iCode *ic)
7260 operand *left,*right, *result;
7265 /* note here that || operations that are in an
7266 if statement are taken away by backPatchLabels
7267 only those used in arthmetic operations remain */
7268 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7269 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7270 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7272 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7274 /* if both are bit variables */
7275 if (AOP_TYPE(left) == AOP_CRY &&
7276 AOP_TYPE(right) == AOP_CRY ) {
7277 pic16_emitcode("clrc","");
7278 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7279 AOP(left)->aopu.aop_dir,
7280 AOP(left)->aopu.aop_dir);
7281 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7282 AOP(right)->aopu.aop_dir,
7283 AOP(right)->aopu.aop_dir);
7284 pic16_emitcode("setc","");
7287 tlbl = newiTempLabel(NULL);
7288 pic16_toBoolean(left);
7290 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7291 pic16_toBoolean(right);
7292 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7294 pic16_outBitAcc(result);
7297 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7298 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7299 pic16_freeAsmop(result,NULL,ic,TRUE);
7302 /*-----------------------------------------------------------------*/
7303 /* isLiteralBit - test if lit == 2^n */
7304 /*-----------------------------------------------------------------*/
7305 static int isLiteralBit(unsigned long lit)
7307 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7308 0x100L,0x200L,0x400L,0x800L,
7309 0x1000L,0x2000L,0x4000L,0x8000L,
7310 0x10000L,0x20000L,0x40000L,0x80000L,
7311 0x100000L,0x200000L,0x400000L,0x800000L,
7312 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7313 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7316 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7317 for(idx = 0; idx < 32; idx++)
7323 /*-----------------------------------------------------------------*/
7324 /* continueIfTrue - */
7325 /*-----------------------------------------------------------------*/
7326 static void continueIfTrue (iCode *ic)
7330 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7334 /*-----------------------------------------------------------------*/
7336 /*-----------------------------------------------------------------*/
7337 static void jumpIfTrue (iCode *ic)
7341 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7345 /*-----------------------------------------------------------------*/
7346 /* jmpTrueOrFalse - */
7347 /*-----------------------------------------------------------------*/
7348 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7350 // ugly but optimized by peephole
7353 symbol *nlbl = newiTempLabel(NULL);
7354 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7355 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7356 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7357 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7359 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7360 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7365 /*-----------------------------------------------------------------*/
7366 /* genAnd - code for and */
7367 /*-----------------------------------------------------------------*/
7368 static void genAnd (iCode *ic, iCode *ifx)
7370 operand *left, *right, *result;
7372 unsigned long lit = 0L;
7378 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7379 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7380 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7382 resolveIfx(&rIfx,ifx);
7384 /* if left is a literal & right is not then exchange them */
7385 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7386 AOP_NEEDSACC(left)) {
7387 operand *tmp = right ;
7392 /* if result = right then exchange them */
7393 if(pic16_sameRegs(AOP(result),AOP(right))){
7394 operand *tmp = right ;
7399 /* if right is bit then exchange them */
7400 if (AOP_TYPE(right) == AOP_CRY &&
7401 AOP_TYPE(left) != AOP_CRY){
7402 operand *tmp = right ;
7406 if(AOP_TYPE(right) == AOP_LIT)
7407 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7409 size = AOP_SIZE(result);
7411 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7414 // result = bit & yy;
7415 if (AOP_TYPE(left) == AOP_CRY){
7416 // c = bit & literal;
7417 if(AOP_TYPE(right) == AOP_LIT){
7419 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7422 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7425 if(size && (AOP_TYPE(result) == AOP_CRY)){
7426 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7429 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7433 pic16_emitcode("clr","c");
7436 if (AOP_TYPE(right) == AOP_CRY){
7438 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7439 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7442 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7444 pic16_emitcode("rrc","a");
7445 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7451 pic16_outBitC(result);
7453 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7454 genIfxJump(ifx, "c");
7458 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7459 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7460 if((AOP_TYPE(right) == AOP_LIT) &&
7461 (AOP_TYPE(result) == AOP_CRY) &&
7462 (AOP_TYPE(left) != AOP_CRY)){
7463 int posbit = isLiteralBit(lit);
7467 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7470 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7476 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7477 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7479 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7480 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7483 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7484 size = AOP_SIZE(left);
7487 int bp = posbit, ofs=0;
7494 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7495 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7499 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7500 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7502 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7509 symbol *tlbl = newiTempLabel(NULL);
7510 int sizel = AOP_SIZE(left);
7516 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7518 /* patch provided by Aaron Colwell */
7519 if((posbit = isLiteralBit(bytelit)) != 0) {
7520 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7521 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7522 (posbit-1),0, PO_GPR_REGISTER));
7524 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7525 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7527 if (bytelit == 0xff) {
7528 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7529 * a peephole could optimize it out -- VR */
7530 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7532 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7533 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7536 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7537 pic16_popGetLabel(tlbl->key));
7541 /* old code, left here for reference -- VR 09/2004 */
7542 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7544 if((posbit = isLiteralBit(bytelit)) != 0)
7545 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7547 if(bytelit != 0x0FFL)
7548 pic16_emitcode("anl","a,%s",
7549 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7550 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7556 // bit = left & literal
7559 pic16_emitpLabel(tlbl->key);
7561 // if(left & literal)
7564 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7567 pic16_emitpLabel(tlbl->key);
7572 pic16_outBitC(result);
7576 /* if left is same as result */
7577 if(pic16_sameRegs(AOP(result),AOP(left))){
7579 for(;size--; offset++,lit>>=8) {
7580 if(AOP_TYPE(right) == AOP_LIT){
7581 switch(lit & 0xff) {
7583 /* and'ing with 0 has clears the result */
7584 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7585 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7588 /* and'ing with 0xff is a nop when the result and left are the same */
7593 int p = pic16_my_powof2( (~lit) & 0xff );
7595 /* only one bit is set in the literal, so use a bcf instruction */
7596 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7597 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7600 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7601 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7602 if(know_W != (lit&0xff))
7603 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7605 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7610 if (AOP_TYPE(left) == AOP_ACC) {
7611 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7613 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7614 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7621 // left & result in different registers
7622 if(AOP_TYPE(result) == AOP_CRY){
7624 // if(size), result in bit
7625 // if(!size && ifx), conditional oper: if(left & right)
7626 symbol *tlbl = newiTempLabel(NULL);
7627 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7629 pic16_emitcode("setb","c");
7631 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7632 pic16_emitcode("anl","a,%s",
7633 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7634 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7639 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7640 pic16_outBitC(result);
7642 jmpTrueOrFalse(ifx, tlbl);
7644 for(;(size--);offset++) {
7646 // result = left & right
7647 if(AOP_TYPE(right) == AOP_LIT){
7648 int t = (lit >> (offset*8)) & 0x0FFL;
7651 pic16_emitcode("clrf","%s",
7652 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7653 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7656 pic16_emitcode("movf","%s,w",
7657 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7658 pic16_emitcode("movwf","%s",
7659 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7660 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7661 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7664 pic16_emitcode("movlw","0x%x",t);
7665 pic16_emitcode("andwf","%s,w",
7666 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7667 pic16_emitcode("movwf","%s",
7668 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7670 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7671 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7672 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7677 if (AOP_TYPE(left) == AOP_ACC) {
7678 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7679 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7681 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7682 pic16_emitcode("andwf","%s,w",
7683 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7684 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7685 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7687 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7688 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7694 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7695 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7696 pic16_freeAsmop(result,NULL,ic,TRUE);
7699 /*-----------------------------------------------------------------*/
7700 /* genOr - code for or */
7701 /*-----------------------------------------------------------------*/
7702 static void genOr (iCode *ic, iCode *ifx)
7704 operand *left, *right, *result;
7706 unsigned long lit = 0L;
7708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7710 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7711 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7712 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7714 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7716 /* if left is a literal & right is not then exchange them */
7717 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7718 AOP_NEEDSACC(left)) {
7719 operand *tmp = right ;
7724 /* if result = right then exchange them */
7725 if(pic16_sameRegs(AOP(result),AOP(right))){
7726 operand *tmp = right ;
7731 /* if right is bit then exchange them */
7732 if (AOP_TYPE(right) == AOP_CRY &&
7733 AOP_TYPE(left) != AOP_CRY){
7734 operand *tmp = right ;
7739 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7741 if(AOP_TYPE(right) == AOP_LIT)
7742 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7744 size = AOP_SIZE(result);
7748 if (AOP_TYPE(left) == AOP_CRY){
7749 if(AOP_TYPE(right) == AOP_LIT){
7750 // c = bit & literal;
7752 // lit != 0 => result = 1
7753 if(AOP_TYPE(result) == AOP_CRY){
7755 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7756 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7757 // AOP(result)->aopu.aop_dir,
7758 // AOP(result)->aopu.aop_dir);
7760 continueIfTrue(ifx);
7764 // lit == 0 => result = left
7765 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7767 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7770 if (AOP_TYPE(right) == AOP_CRY){
7771 if(pic16_sameRegs(AOP(result),AOP(left))){
7773 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7774 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7775 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7777 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7778 AOP(result)->aopu.aop_dir,
7779 AOP(result)->aopu.aop_dir);
7780 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7781 AOP(right)->aopu.aop_dir,
7782 AOP(right)->aopu.aop_dir);
7783 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7784 AOP(result)->aopu.aop_dir,
7785 AOP(result)->aopu.aop_dir);
7787 if( AOP_TYPE(result) == AOP_ACC) {
7788 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7789 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7790 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7791 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7795 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7796 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7797 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7798 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7800 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7801 AOP(result)->aopu.aop_dir,
7802 AOP(result)->aopu.aop_dir);
7803 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7804 AOP(right)->aopu.aop_dir,
7805 AOP(right)->aopu.aop_dir);
7806 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7807 AOP(left)->aopu.aop_dir,
7808 AOP(left)->aopu.aop_dir);
7809 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7810 AOP(result)->aopu.aop_dir,
7811 AOP(result)->aopu.aop_dir);
7816 symbol *tlbl = newiTempLabel(NULL);
7817 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7820 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7821 if( AOP_TYPE(right) == AOP_ACC) {
7822 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7824 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7825 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7830 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7831 pic16_emitcode(";XXX setb","c");
7832 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7833 AOP(left)->aopu.aop_dir,tlbl->key+100);
7834 pic16_toBoolean(right);
7835 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7836 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7837 jmpTrueOrFalse(ifx, tlbl);
7841 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7848 pic16_outBitC(result);
7850 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7851 genIfxJump(ifx, "c");
7855 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7856 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7857 if((AOP_TYPE(right) == AOP_LIT) &&
7858 (AOP_TYPE(result) == AOP_CRY) &&
7859 (AOP_TYPE(left) != AOP_CRY)){
7861 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7864 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7866 continueIfTrue(ifx);
7869 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7870 // lit = 0, result = boolean(left)
7872 pic16_emitcode(";XXX setb","c");
7873 pic16_toBoolean(right);
7875 symbol *tlbl = newiTempLabel(NULL);
7876 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7878 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7880 genIfxJump (ifx,"a");
7884 pic16_outBitC(result);
7888 /* if left is same as result */
7889 if(pic16_sameRegs(AOP(result),AOP(left))){
7891 for(;size--; offset++,lit>>=8) {
7892 if(AOP_TYPE(right) == AOP_LIT){
7893 if((lit & 0xff) == 0)
7894 /* or'ing with 0 has no effect */
7897 int p = pic16_my_powof2(lit & 0xff);
7899 /* only one bit is set in the literal, so use a bsf instruction */
7900 pic16_emitpcode(POC_BSF,
7901 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7903 if(know_W != (lit & 0xff))
7904 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7905 know_W = lit & 0xff;
7906 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7911 if (AOP_TYPE(left) == AOP_ACC) {
7912 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7913 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7915 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7916 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7918 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7925 // left & result in different registers
7926 if(AOP_TYPE(result) == AOP_CRY){
7928 // if(size), result in bit
7929 // if(!size && ifx), conditional oper: if(left | right)
7930 symbol *tlbl = newiTempLabel(NULL);
7931 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7932 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7936 pic16_emitcode(";XXX setb","c");
7938 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7939 pic16_emitcode(";XXX orl","a,%s",
7940 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7941 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7946 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7947 pic16_outBitC(result);
7949 jmpTrueOrFalse(ifx, tlbl);
7950 } else for(;(size--);offset++){
7952 // result = left & right
7953 if(AOP_TYPE(right) == AOP_LIT){
7954 int t = (lit >> (offset*8)) & 0x0FFL;
7957 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7960 // pic16_emitcode("movf","%s,w",
7961 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7962 // pic16_emitcode("movwf","%s",
7963 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7966 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7967 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7970 // pic16_emitcode("movlw","0x%x",t);
7971 // pic16_emitcode("iorwf","%s,w",
7972 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7973 // pic16_emitcode("movwf","%s",
7974 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7980 // faster than result <- left, anl result,right
7981 // and better if result is SFR
7982 if (AOP_TYPE(left) == AOP_ACC) {
7983 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7984 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7987 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7989 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7990 // pic16_emitcode("iorwf","%s,w",
7991 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7994 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7999 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8000 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8001 pic16_freeAsmop(result,NULL,ic,TRUE);
8004 /*-----------------------------------------------------------------*/
8005 /* genXor - code for xclusive or */
8006 /*-----------------------------------------------------------------*/
8007 static void genXor (iCode *ic, iCode *ifx)
8009 operand *left, *right, *result;
8011 unsigned long lit = 0L;
8013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8015 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8016 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8017 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8019 /* if left is a literal & right is not ||
8020 if left needs acc & right does not */
8021 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8022 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8023 operand *tmp = right ;
8028 /* if result = right then exchange them */
8029 if(pic16_sameRegs(AOP(result),AOP(right))){
8030 operand *tmp = right ;
8035 /* if right is bit then exchange them */
8036 if (AOP_TYPE(right) == AOP_CRY &&
8037 AOP_TYPE(left) != AOP_CRY){
8038 operand *tmp = right ;
8042 if(AOP_TYPE(right) == AOP_LIT)
8043 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8045 size = AOP_SIZE(result);
8049 if (AOP_TYPE(left) == AOP_CRY){
8050 if(AOP_TYPE(right) == AOP_LIT){
8051 // c = bit & literal;
8053 // lit>>1 != 0 => result = 1
8054 if(AOP_TYPE(result) == AOP_CRY){
8056 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8057 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8059 continueIfTrue(ifx);
8062 pic16_emitcode("setb","c");
8066 // lit == 0, result = left
8067 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8069 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8071 // lit == 1, result = not(left)
8072 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8073 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8074 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8075 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8078 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8079 pic16_emitcode("cpl","c");
8086 symbol *tlbl = newiTempLabel(NULL);
8087 if (AOP_TYPE(right) == AOP_CRY){
8089 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8092 int sizer = AOP_SIZE(right);
8094 // if val>>1 != 0, result = 1
8095 pic16_emitcode("setb","c");
8097 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8099 // test the msb of the lsb
8100 pic16_emitcode("anl","a,#0xfe");
8101 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8105 pic16_emitcode("rrc","a");
8107 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8108 pic16_emitcode("cpl","c");
8109 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8114 pic16_outBitC(result);
8116 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8117 genIfxJump(ifx, "c");
8121 if(pic16_sameRegs(AOP(result),AOP(left))){
8122 /* if left is same as result */
8123 for(;size--; offset++) {
8124 if(AOP_TYPE(right) == AOP_LIT){
8125 int t = (lit >> (offset*8)) & 0x0FFL;
8129 if (IS_AOP_PREG(left)) {
8130 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8131 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132 pic16_aopPut(AOP(result),"a",offset);
8134 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8135 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8136 pic16_emitcode("xrl","%s,%s",
8137 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8138 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8141 if (AOP_TYPE(left) == AOP_ACC)
8142 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8144 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8145 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8147 if (IS_AOP_PREG(left)) {
8148 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8149 pic16_aopPut(AOP(result),"a",offset);
8151 pic16_emitcode("xrl","%s,a",
8152 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8158 // left & result in different registers
8159 if(AOP_TYPE(result) == AOP_CRY){
8161 // if(size), result in bit
8162 // if(!size && ifx), conditional oper: if(left ^ right)
8163 symbol *tlbl = newiTempLabel(NULL);
8164 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8166 pic16_emitcode("setb","c");
8168 if((AOP_TYPE(right) == AOP_LIT) &&
8169 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8170 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8172 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8173 pic16_emitcode("xrl","a,%s",
8174 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8176 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8181 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8182 pic16_outBitC(result);
8184 jmpTrueOrFalse(ifx, tlbl);
8185 } else for(;(size--);offset++){
8187 // result = left & right
8188 if(AOP_TYPE(right) == AOP_LIT){
8189 int t = (lit >> (offset*8)) & 0x0FFL;
8192 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8193 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8194 pic16_emitcode("movf","%s,w",
8195 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8196 pic16_emitcode("movwf","%s",
8197 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8200 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8201 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8202 pic16_emitcode("comf","%s,w",
8203 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8204 pic16_emitcode("movwf","%s",
8205 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8208 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8209 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8210 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8211 pic16_emitcode("movlw","0x%x",t);
8212 pic16_emitcode("xorwf","%s,w",
8213 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8214 pic16_emitcode("movwf","%s",
8215 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8221 // faster than result <- left, anl result,right
8222 // and better if result is SFR
8223 if (AOP_TYPE(left) == AOP_ACC) {
8224 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8225 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8227 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8228 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8229 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8230 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8232 if ( AOP_TYPE(result) != AOP_ACC){
8233 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8234 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8240 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8241 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8242 pic16_freeAsmop(result,NULL,ic,TRUE);
8245 /*-----------------------------------------------------------------*/
8246 /* genInline - write the inline code out */
8247 /*-----------------------------------------------------------------*/
8248 static void genInline (iCode *ic)
8250 char *buffer, *bp, *bp1;
8252 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8254 _G.inLine += (!options.asmpeep);
8256 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8257 strcpy(buffer,IC_INLINE(ic));
8259 while((bp1=strstr(bp, "\\n"))) {
8267 /* This is an experimental code for #pragma inline
8268 and is temporarily disabled for 2.5.0 release */
8276 cbuf = Safe_strdup(buffer);
8277 cblen = strlen(buffer)+1;
8278 memset(cbuf, 0, cblen);
8283 if(*bp != '%')*bp1++ = *bp++;
8289 if(i>elementsInSet(asmInlineMap))break;
8292 s = indexSet(asmInlineMap, i);
8293 DEBUGpc("searching symbol s = `%s'", s);
8294 sym = findSym(SymbolTab, NULL, s);
8297 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8299 strcat(bp1, sym->rname);
8305 if(strlen(bp1) > cblen - 16) {
8306 int i = strlen(cbuf);
8308 cbuf = realloc(cbuf, cblen);
8309 memset(cbuf+i, 0, 50);
8315 buffer = Safe_strdup( cbuf );
8322 /* emit each line as a code */
8328 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8336 /* print label, use this special format with NULL directive
8337 * to denote that the argument should not be indented with tab */
8338 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8341 /* advance to end of line (prevent splitting of comments at ':' */
8342 while (*bp && *bp != '\n') {
8350 if ((bp1 != bp) && *bp1)
8351 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8356 _G.inLine -= (!options.asmpeep);
8359 /*-----------------------------------------------------------------*/
8360 /* genRRC - rotate right with carry */
8361 /*-----------------------------------------------------------------*/
8362 static void genRRC (iCode *ic)
8364 operand *left , *result ;
8365 int size, offset = 0, same;
8367 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8369 /* rotate right with carry */
8371 result=IC_RESULT(ic);
8372 pic16_aopOp (left,ic,FALSE);
8373 pic16_aopOp (result,ic,TRUE);
8375 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8377 same = pic16_sameRegs(AOP(result),AOP(left));
8379 size = AOP_SIZE(result);
8381 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8383 /* get the lsb and put it into the carry */
8384 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8391 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8393 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8394 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8400 pic16_freeAsmop(left,NULL,ic,TRUE);
8401 pic16_freeAsmop(result,NULL,ic,TRUE);
8404 /*-----------------------------------------------------------------*/
8405 /* genRLC - generate code for rotate left with carry */
8406 /*-----------------------------------------------------------------*/
8407 static void genRLC (iCode *ic)
8409 operand *left , *result ;
8410 int size, offset = 0;
8413 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8414 /* rotate right with carry */
8416 result=IC_RESULT(ic);
8417 pic16_aopOp (left,ic,FALSE);
8418 pic16_aopOp (result,ic,TRUE);
8420 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8422 same = pic16_sameRegs(AOP(result),AOP(left));
8424 /* move it to the result */
8425 size = AOP_SIZE(result);
8427 /* get the msb and put it into the carry */
8428 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8435 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8437 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8438 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8445 pic16_freeAsmop(left,NULL,ic,TRUE);
8446 pic16_freeAsmop(result,NULL,ic,TRUE);
8450 /* gpasm can get the highest order bit with HIGH/UPPER
8451 * so the following probably is not needed -- VR */
8453 /*-----------------------------------------------------------------*/
8454 /* genGetHbit - generates code get highest order bit */
8455 /*-----------------------------------------------------------------*/
8456 static void genGetHbit (iCode *ic)
8458 operand *left, *result;
8460 result=IC_RESULT(ic);
8461 pic16_aopOp (left,ic,FALSE);
8462 pic16_aopOp (result,ic,FALSE);
8464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8465 /* get the highest order byte into a */
8466 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8467 if(AOP_TYPE(result) == AOP_CRY){
8468 pic16_emitcode("rlc","a");
8469 pic16_outBitC(result);
8472 pic16_emitcode("rl","a");
8473 pic16_emitcode("anl","a,#0x01");
8474 pic16_outAcc(result);
8478 pic16_freeAsmop(left,NULL,ic,TRUE);
8479 pic16_freeAsmop(result,NULL,ic,TRUE);
8483 /*-----------------------------------------------------------------*/
8484 /* AccRol - rotate left accumulator by known count */
8485 /*-----------------------------------------------------------------*/
8486 static void AccRol (int shCount)
8488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8489 shCount &= 0x0007; // shCount : 0..7
8494 pic16_emitcode("rl","a");
8497 pic16_emitcode("rl","a");
8498 pic16_emitcode("rl","a");
8501 pic16_emitcode("swap","a");
8502 pic16_emitcode("rr","a");
8505 pic16_emitcode("swap","a");
8508 pic16_emitcode("swap","a");
8509 pic16_emitcode("rl","a");
8512 pic16_emitcode("rr","a");
8513 pic16_emitcode("rr","a");
8516 pic16_emitcode("rr","a");
8522 /*-----------------------------------------------------------------*/
8523 /* AccLsh - left shift accumulator by known count */
8524 /*-----------------------------------------------------------------*/
8525 static void AccLsh (int shCount, int doMask)
8527 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8533 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8537 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8540 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8541 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8547 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8548 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 /* no masking is required in genPackBits */
8560 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8564 /*-----------------------------------------------------------------*/
8565 /* AccRsh - right shift accumulator by known count */
8566 /*-----------------------------------------------------------------*/
8567 static void AccRsh (int shCount, int andmask)
8569 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8574 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8577 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8578 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8581 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8582 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8585 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8588 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8589 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8592 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8593 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8596 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8601 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8603 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8607 /*-----------------------------------------------------------------*/
8608 /* AccSRsh - signed right shift accumulator by known count */
8609 /*-----------------------------------------------------------------*/
8610 static void AccSRsh (int shCount)
8613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8616 pic16_emitcode("mov","c,acc.7");
8617 pic16_emitcode("rrc","a");
8618 } else if(shCount == 2){
8619 pic16_emitcode("mov","c,acc.7");
8620 pic16_emitcode("rrc","a");
8621 pic16_emitcode("mov","c,acc.7");
8622 pic16_emitcode("rrc","a");
8624 tlbl = newiTempLabel(NULL);
8625 /* rotate right accumulator */
8626 AccRol(8 - shCount);
8627 /* and kill the higher order bits */
8628 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8629 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8630 pic16_emitcode("orl","a,#0x%02x",
8631 (unsigned char)~SRMask[shCount]);
8632 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8638 /*-----------------------------------------------------------------*/
8639 /* shiftR1Left2Result - shift right one byte from left to result */
8640 /*-----------------------------------------------------------------*/
8641 static void shiftR1Left2ResultSigned (operand *left, int offl,
8642 operand *result, int offr,
8647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8649 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8653 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8655 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8657 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8658 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8664 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8666 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8668 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8672 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8678 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8681 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8684 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8685 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8689 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8696 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8697 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8698 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8709 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8710 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8711 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8712 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8717 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8718 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8720 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8721 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
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));
8727 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8728 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8734 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8735 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8736 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8737 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8739 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8740 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8741 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8749 /*-----------------------------------------------------------------*/
8750 /* shiftR1Left2Result - shift right one byte from left to result */
8751 /*-----------------------------------------------------------------*/
8752 static void shiftR1Left2Result (operand *left, int offl,
8753 operand *result, int offr,
8754 int shCount, int sign)
8758 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8760 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8762 /* Copy the msb into the carry if signed. */
8764 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8774 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8789 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8797 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8801 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8802 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8803 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8807 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8808 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8809 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8813 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8814 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8815 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8817 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8822 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8823 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8824 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8825 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8826 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8831 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8832 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8833 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8842 /*-----------------------------------------------------------------*/
8843 /* shiftL1Left2Result - shift left one byte from left to result */
8844 /*-----------------------------------------------------------------*/
8845 static void shiftL1Left2Result (operand *left, int offl,
8846 operand *result, int offr, int shCount)
8851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8853 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8854 DEBUGpic16_emitcode ("; ***","same = %d",same);
8855 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8857 /* shift left accumulator */
8858 //AccLsh(shCount, 1); // don't comment out just yet...
8859 // pic16_aopPut(AOP(result),"a",offr);
8863 /* Shift left 1 bit position */
8864 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8866 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8868 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8869 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8874 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8875 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8880 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8881 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8883 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8886 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8887 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8888 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8892 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8893 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8894 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8898 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8899 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8900 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8904 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8905 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8910 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8915 /*-----------------------------------------------------------------*/
8916 /* movLeft2Result - move byte from left to result */
8917 /*-----------------------------------------------------------------*/
8918 static void movLeft2Result (operand *left, int offl,
8919 operand *result, int offr)
8922 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8923 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8924 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8926 if (*l == '@' && (IS_AOP_PREG(result))) {
8927 pic16_emitcode("mov","a,%s",l);
8928 pic16_aopPut(AOP(result),"a",offr);
8930 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8936 /*-----------------------------------------------------------------*/
8937 /* shiftL2Left2Result - shift left two bytes from left to result */
8938 /*-----------------------------------------------------------------*/
8939 static void shiftL2Left2Result (operand *left, int offl,
8940 operand *result, int offr, int shCount)
8942 int same = pic16_sameRegs(AOP(result), AOP(left));
8945 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8947 if (same && (offl != offr)) { // shift bytes
8950 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8951 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8953 } else { // just treat as different later on
8966 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RLCF, 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));
8979 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8980 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8981 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8982 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8983 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8984 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8985 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8987 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8992 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8993 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8995 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8997 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8998 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8999 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9000 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9004 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9005 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9007 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9008 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9018 /* note, use a mov/add for the shift since the mov has a
9019 chance of getting optimized out */
9020 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9028 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9035 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9036 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9039 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9041 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9046 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9051 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9052 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9053 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9056 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9057 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9059 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9060 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9061 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9063 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9066 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9067 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9068 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9069 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9075 /*-----------------------------------------------------------------*/
9076 /* shiftR2Left2Result - shift right two bytes from left to result */
9077 /*-----------------------------------------------------------------*/
9078 static void shiftR2Left2Result (operand *left, int offl,
9079 operand *result, int offr,
9080 int shCount, int sign)
9082 int same = pic16_sameRegs(AOP(result), AOP(left));
9084 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9086 if (same && (offl != offr)) { // shift right bytes
9089 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9090 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9092 } else { // just treat as different later on
9104 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9109 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9113 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9123 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9124 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9132 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9133 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9136 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9137 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9138 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9141 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9142 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9146 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9147 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9148 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9158 pic16_emitpcode(POC_BTFSC,
9159 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9160 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9169 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9171 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9173 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9176 pic16_emitpcode(POC_BTFSC,
9177 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9178 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9180 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9181 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9182 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9183 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9187 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9189 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9190 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9192 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9194 pic16_emitpcode(POC_BTFSC,
9195 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9196 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9198 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9199 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9206 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9207 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9212 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9214 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9219 /*-----------------------------------------------------------------*/
9220 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9221 /*-----------------------------------------------------------------*/
9222 static void shiftLLeftOrResult (operand *left, int offl,
9223 operand *result, int offr, int shCount)
9225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9227 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9228 /* shift left accumulator */
9230 /* or with result */
9231 /* back to result */
9232 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9235 /*-----------------------------------------------------------------*/
9236 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9237 /*-----------------------------------------------------------------*/
9238 static void shiftRLeftOrResult (operand *left, int offl,
9239 operand *result, int offr, int shCount)
9241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9243 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9244 /* shift right accumulator */
9246 /* or with result */
9247 /* back to result */
9248 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9251 /*-----------------------------------------------------------------*/
9252 /* genlshOne - left shift a one byte quantity by known count */
9253 /*-----------------------------------------------------------------*/
9254 static void genlshOne (operand *result, operand *left, int shCount)
9256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9257 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9260 /*-----------------------------------------------------------------*/
9261 /* genlshTwo - left shift two bytes by known amount != 0 */
9262 /*-----------------------------------------------------------------*/
9263 static void genlshTwo (operand *result,operand *left, int shCount)
9267 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9268 size = pic16_getDataSize(result);
9270 /* if shCount >= 8 */
9276 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9278 movLeft2Result(left, LSB, result, MSB16);
9280 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9283 /* 1 <= shCount <= 7 */
9286 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9288 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9292 /*-----------------------------------------------------------------*/
9293 /* shiftLLong - shift left one long from left to result */
9294 /* offr = LSB or MSB16 */
9295 /*-----------------------------------------------------------------*/
9296 static void shiftLLong (operand *left, operand *result, int offr )
9298 int size = AOP_SIZE(result);
9299 int same = pic16_sameRegs(AOP(left),AOP(result));
9302 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9304 if (same && (offr == MSB16)) { //shift one byte
9305 for(i=size-1;i>=MSB16;i--) {
9306 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9307 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9310 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9313 if (size > LSB+offr ){
9315 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9317 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9318 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9322 if(size > MSB16+offr){
9324 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9326 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9327 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9331 if(size > MSB24+offr){
9333 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9335 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9336 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9340 if(size > MSB32+offr){
9342 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9344 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9345 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9349 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9353 /*-----------------------------------------------------------------*/
9354 /* genlshFour - shift four byte by a known amount != 0 */
9355 /*-----------------------------------------------------------------*/
9356 static void genlshFour (operand *result, operand *left, int shCount)
9360 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9361 size = AOP_SIZE(result);
9363 /* if shifting more that 3 bytes */
9364 if (shCount >= 24 ) {
9367 /* lowest order of left goes to the highest
9368 order of the destination */
9369 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9371 movLeft2Result(left, LSB, result, MSB32);
9373 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9374 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9375 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9380 /* more than two bytes */
9381 else if ( shCount >= 16 ) {
9382 /* lower order two bytes goes to higher order two bytes */
9384 /* if some more remaining */
9386 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9388 movLeft2Result(left, MSB16, result, MSB32);
9389 movLeft2Result(left, LSB, result, MSB24);
9391 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9392 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9396 /* if more than 1 byte */
9397 else if ( shCount >= 8 ) {
9398 /* lower order three bytes goes to higher order three bytes */
9402 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9404 movLeft2Result(left, LSB, result, MSB16);
9406 else{ /* size = 4 */
9408 movLeft2Result(left, MSB24, result, MSB32);
9409 movLeft2Result(left, MSB16, result, MSB24);
9410 movLeft2Result(left, LSB, result, MSB16);
9411 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9413 else if(shCount == 1)
9414 shiftLLong(left, result, MSB16);
9416 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9417 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9418 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9419 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9424 /* 1 <= shCount <= 7 */
9425 else if(shCount <= 3)
9427 shiftLLong(left, result, LSB);
9428 while(--shCount >= 1)
9429 shiftLLong(result, result, LSB);
9431 /* 3 <= shCount <= 7, optimize */
9433 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9434 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9435 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9439 /*-----------------------------------------------------------------*/
9440 /* genLeftShiftLiteral - left shifting by known count */
9441 /*-----------------------------------------------------------------*/
9442 void pic16_genLeftShiftLiteral (operand *left,
9447 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9451 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9452 pic16_freeAsmop(right,NULL,ic,TRUE);
9454 pic16_aopOp(left,ic,FALSE);
9455 pic16_aopOp(result,ic,TRUE);
9457 size = getSize(operandType(result));
9460 pic16_emitcode("; shift left ","result %d, left %d",size,
9464 /* I suppose that the left size >= result size */
9467 movLeft2Result(left, size, result, size);
9471 else if(shCount >= (size * 8))
9473 pic16_aopPut(AOP(result),zero,size);
9477 genlshOne (result,left,shCount);
9482 genlshTwo (result,left,shCount);
9486 genlshFour (result,left,shCount);
9490 pic16_freeAsmop(left,NULL,ic,TRUE);
9491 pic16_freeAsmop(result,NULL,ic,TRUE);
9494 /*-----------------------------------------------------------------*
9495 * genMultiAsm - repeat assembly instruction for size of register.
9496 * if endian == 1, then the high byte (i.e base address + size of
9497 * register) is used first else the low byte is used first;
9498 *-----------------------------------------------------------------*/
9499 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9517 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9523 #if !(USE_GENERIC_SIGNED_SHIFT)
9524 /*-----------------------------------------------------------------*/
9525 /* genLeftShift - generates code for left shifting */
9526 /*-----------------------------------------------------------------*/
9527 static void genLeftShift (iCode *ic)
9529 operand *left,*right, *result;
9532 symbol *tlbl , *tlbl1;
9535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9537 right = IC_RIGHT(ic);
9539 result = IC_RESULT(ic);
9541 pic16_aopOp(right,ic,FALSE);
9543 /* if the shift count is known then do it
9544 as efficiently as possible */
9545 if (AOP_TYPE(right) == AOP_LIT) {
9546 pic16_genLeftShiftLiteral (left,right,result,ic);
9550 /* shift count is unknown then we have to form
9551 * a loop. Get the loop count in WREG : Note: we take
9552 * only the lower order byte since shifting
9553 * more than 32 bits make no sense anyway, ( the
9554 * largest size of an object can be only 32 bits ) */
9556 pic16_aopOp(left,ic,FALSE);
9557 pic16_aopOp(result,ic,FALSE);
9559 /* now move the left to the result if they are not the
9560 * same, and if size > 1,
9561 * and if right is not same to result (!!!) -- VR */
9562 if (!pic16_sameRegs(AOP(left),AOP(result))
9563 && (AOP_SIZE(result) > 1)) {
9565 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9567 size = AOP_SIZE(result);
9572 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9573 if (*l == '@' && (IS_AOP_PREG(result))) {
9575 pic16_emitcode("mov","a,%s",l);
9576 pic16_aopPut(AOP(result),"a",offset);
9580 /* we don't know if left is a literal or a register, take care -- VR */
9581 pic16_mov2f(AOP(result), AOP(left), offset);
9587 size = AOP_SIZE(result);
9589 /* if it is only one byte then */
9591 if(optimized_for_speed) {
9592 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9593 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9594 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9595 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9596 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9597 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9598 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9599 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9600 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9601 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9602 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9603 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9606 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9608 tlbl = newiTempLabel(NULL);
9611 /* this is already done, why change it? */
9612 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9613 pic16_mov2f(AOP(result), AOP(left), 0);
9617 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9618 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9619 pic16_emitpLabel(tlbl->key);
9620 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9621 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9623 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9628 if (pic16_sameRegs(AOP(left),AOP(result))) {
9630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9632 tlbl = newiTempLabel(NULL);
9633 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9634 genMultiAsm(POC_RRCF, result, size,1);
9635 pic16_emitpLabel(tlbl->key);
9636 genMultiAsm(POC_RLCF, result, size,0);
9637 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9639 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9643 //tlbl = newiTempLabel(NULL);
9645 //tlbl1 = newiTempLabel(NULL);
9647 //reAdjustPreg(AOP(result));
9649 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9650 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9651 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9653 //pic16_emitcode("add","a,acc");
9654 //pic16_aopPut(AOP(result),"a",offset++);
9656 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9658 // pic16_emitcode("rlc","a");
9659 // pic16_aopPut(AOP(result),"a",offset++);
9661 //reAdjustPreg(AOP(result));
9663 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9664 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9667 tlbl = newiTempLabel(NULL);
9668 tlbl1= newiTempLabel(NULL);
9670 size = AOP_SIZE(result);
9673 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9675 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9677 /* offset should be 0, 1 or 3 */
9679 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9681 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9683 pic16_emitpcode(POC_MOVWF, pctemp);
9686 pic16_emitpLabel(tlbl->key);
9689 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9691 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9693 pic16_emitpcode(POC_DECFSZ, pctemp);
9694 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9695 pic16_emitpLabel(tlbl1->key);
9697 pic16_popReleaseTempReg(pctemp,1);
9701 pic16_freeAsmop (right,NULL,ic,TRUE);
9702 pic16_freeAsmop(left,NULL,ic,TRUE);
9703 pic16_freeAsmop(result,NULL,ic,TRUE);
9709 #error old code (left here for reference)
9710 /*-----------------------------------------------------------------*/
9711 /* genLeftShift - generates code for left shifting */
9712 /*-----------------------------------------------------------------*/
9713 static void genLeftShift (iCode *ic)
9715 operand *left,*right, *result;
9718 symbol *tlbl , *tlbl1;
9721 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9723 right = IC_RIGHT(ic);
9725 result = IC_RESULT(ic);
9727 pic16_aopOp(right,ic,FALSE);
9729 /* if the shift count is known then do it
9730 as efficiently as possible */
9731 if (AOP_TYPE(right) == AOP_LIT) {
9732 pic16_genLeftShiftLiteral (left,right,result,ic);
9736 /* shift count is unknown then we have to form
9737 a loop get the loop count in B : Note: we take
9738 only the lower order byte since shifting
9739 more that 32 bits make no sense anyway, ( the
9740 largest size of an object can be only 32 bits ) */
9743 pic16_aopOp(left,ic,FALSE);
9744 pic16_aopOp(result,ic,FALSE);
9746 /* now move the left to the result if they are not the
9748 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9749 AOP_SIZE(result) > 1) {
9751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9753 size = AOP_SIZE(result);
9756 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9757 if (*l == '@' && (IS_AOP_PREG(result))) {
9759 pic16_emitcode("mov","a,%s",l);
9760 pic16_aopPut(AOP(result),"a",offset);
9763 /* we don't know if left is a literal or a register, take care -- VR */
9764 pic16_mov2f(AOP(result), AOP(left), offset);
9770 size = AOP_SIZE(result);
9772 /* if it is only one byte then */
9774 if(optimized_for_speed) {
9775 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9777 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9778 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9779 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9780 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9781 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9782 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9783 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9784 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9785 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9786 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9791 tlbl = newiTempLabel(NULL);
9792 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9793 pic16_mov2f(AOP(result), AOP(left), 0);
9795 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9796 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9799 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9800 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9801 pic16_emitpLabel(tlbl->key);
9802 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9803 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9805 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9810 if (pic16_sameRegs(AOP(left),AOP(result))) {
9812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9814 tlbl = newiTempLabel(NULL);
9815 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9816 genMultiAsm(POC_RRCF, result, size,1);
9817 pic16_emitpLabel(tlbl->key);
9818 genMultiAsm(POC_RLCF, result, size,0);
9819 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9821 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9825 //tlbl = newiTempLabel(NULL);
9827 //tlbl1 = newiTempLabel(NULL);
9829 //reAdjustPreg(AOP(result));
9831 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9832 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9833 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9835 //pic16_emitcode("add","a,acc");
9836 //pic16_aopPut(AOP(result),"a",offset++);
9838 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9840 // pic16_emitcode("rlc","a");
9841 // pic16_aopPut(AOP(result),"a",offset++);
9843 //reAdjustPreg(AOP(result));
9845 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9846 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9849 tlbl = newiTempLabel(NULL);
9850 tlbl1= newiTempLabel(NULL);
9852 size = AOP_SIZE(result);
9855 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9857 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9859 /* offset should be 0, 1 or 3 */
9861 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9863 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9865 pic16_emitpcode(POC_MOVWF, pctemp);
9868 pic16_emitpLabel(tlbl->key);
9871 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9873 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9875 pic16_emitpcode(POC_DECFSZ, pctemp);
9876 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9877 pic16_emitpLabel(tlbl1->key);
9879 pic16_popReleaseTempReg(pctemp,1);
9883 pic16_freeAsmop (right,NULL,ic,TRUE);
9884 pic16_freeAsmop(left,NULL,ic,TRUE);
9885 pic16_freeAsmop(result,NULL,ic,TRUE);
9889 /*-----------------------------------------------------------------*/
9890 /* genrshOne - right shift a one byte quantity by known count */
9891 /*-----------------------------------------------------------------*/
9892 static void genrshOne (operand *result, operand *left,
9893 int shCount, int sign)
9895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9896 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9899 /*-----------------------------------------------------------------*/
9900 /* genrshTwo - right shift two bytes by known amount != 0 */
9901 /*-----------------------------------------------------------------*/
9902 static void genrshTwo (operand *result,operand *left,
9903 int shCount, int sign)
9905 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9906 /* if shCount >= 8 */
9910 shiftR1Left2Result(left, MSB16, result, LSB,
9913 movLeft2Result(left, MSB16, result, LSB);
9915 pic16_addSign (result, 1, sign);
9918 /* 1 <= shCount <= 7 */
9920 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9923 /*-----------------------------------------------------------------*/
9924 /* shiftRLong - shift right one long from left to result */
9925 /* offl = LSB or MSB16 */
9926 /*-----------------------------------------------------------------*/
9927 static void shiftRLong (operand *left, int offl,
9928 operand *result, int sign)
9930 int size = AOP_SIZE(result);
9931 int same = pic16_sameRegs(AOP(left),AOP(result));
9933 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9935 if (same && (offl == MSB16)) { //shift one byte right
9936 for(i=MSB16;i<size;i++) {
9937 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9938 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9943 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9949 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9951 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9956 /* add sign of "a" */
9957 pic16_addSign(result, MSB32, sign);
9961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9963 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9975 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9978 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9979 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9984 /*-----------------------------------------------------------------*/
9985 /* genrshFour - shift four byte by a known amount != 0 */
9986 /*-----------------------------------------------------------------*/
9987 static void genrshFour (operand *result, operand *left,
9988 int shCount, int sign)
9990 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9991 /* if shifting more that 3 bytes */
9992 if(shCount >= 24 ) {
9995 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9997 movLeft2Result(left, MSB32, result, LSB);
9999 pic16_addSign(result, MSB16, sign);
10001 else if(shCount >= 16){
10004 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10006 movLeft2Result(left, MSB24, result, LSB);
10007 movLeft2Result(left, MSB32, result, MSB16);
10009 pic16_addSign(result, MSB24, sign);
10011 else if(shCount >= 8){
10014 shiftRLong(left, MSB16, result, sign);
10015 else if(shCount == 0){
10016 movLeft2Result(left, MSB16, result, LSB);
10017 movLeft2Result(left, MSB24, result, MSB16);
10018 movLeft2Result(left, MSB32, result, MSB24);
10019 pic16_addSign(result, MSB32, sign);
10021 else{ //shcount >= 2
10022 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10023 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10024 /* the last shift is signed */
10025 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10026 pic16_addSign(result, MSB32, sign);
10029 else{ /* 1 <= shCount <= 7 */
10031 shiftRLong(left, LSB, result, sign);
10033 shiftRLong(result, LSB, result, sign);
10036 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10037 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10038 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10043 /*-----------------------------------------------------------------*/
10044 /* genRightShiftLiteral - right shifting by known count */
10045 /*-----------------------------------------------------------------*/
10046 static void genRightShiftLiteral (operand *left,
10052 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10053 int lsize,res_size;
10055 pic16_freeAsmop(right,NULL,ic,TRUE);
10057 pic16_aopOp(left,ic,FALSE);
10058 pic16_aopOp(result,ic,TRUE);
10060 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10063 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10067 lsize = pic16_getDataSize(left);
10068 res_size = pic16_getDataSize(result);
10069 /* test the LEFT size !!! */
10071 /* I suppose that the left size >= result size */
10073 assert (res_size <= lsize);
10074 while (res_size--) {
10075 pic16_mov2f (AOP(result), AOP(left), res_size);
10079 else if(shCount >= (lsize * 8)){
10081 if(res_size == 1) {
10082 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10084 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10085 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10090 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10091 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10092 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10094 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10099 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10104 switch (res_size) {
10106 genrshOne (result,left,shCount,sign);
10110 genrshTwo (result,left,shCount,sign);
10114 genrshFour (result,left,shCount,sign);
10122 pic16_freeAsmop(left,NULL,ic,TRUE);
10123 pic16_freeAsmop(result,NULL,ic,TRUE);
10126 #if !(USE_GENERIC_SIGNED_SHIFT)
10127 /*-----------------------------------------------------------------*/
10128 /* genSignedRightShift - right shift of signed number */
10129 /*-----------------------------------------------------------------*/
10130 static void genSignedRightShift (iCode *ic)
10132 operand *right, *left, *result;
10135 symbol *tlbl, *tlbl1 ;
10138 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10140 /* we do it the hard way put the shift count in b
10141 and loop thru preserving the sign */
10142 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10144 right = IC_RIGHT(ic);
10145 left = IC_LEFT(ic);
10146 result = IC_RESULT(ic);
10148 pic16_aopOp(right,ic,FALSE);
10149 pic16_aopOp(left,ic,FALSE);
10150 pic16_aopOp(result,ic,FALSE);
10153 if ( AOP_TYPE(right) == AOP_LIT) {
10154 genRightShiftLiteral (left,right,result,ic,1);
10157 /* shift count is unknown then we have to form
10158 a loop get the loop count in B : Note: we take
10159 only the lower order byte since shifting
10160 more that 32 bits make no sense anyway, ( the
10161 largest size of an object can be only 32 bits ) */
10163 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10164 //pic16_emitcode("inc","b");
10165 //pic16_freeAsmop (right,NULL,ic,TRUE);
10166 //pic16_aopOp(left,ic,FALSE);
10167 //pic16_aopOp(result,ic,FALSE);
10169 /* now move the left to the result if they are not the
10171 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10172 AOP_SIZE(result) > 1) {
10174 size = AOP_SIZE(result);
10178 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10179 if (*l == '@' && IS_AOP_PREG(result)) {
10181 pic16_emitcode("mov","a,%s",l);
10182 pic16_aopPut(AOP(result),"a",offset);
10184 pic16_aopPut(AOP(result),l,offset);
10186 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10193 /* mov the highest order bit to OVR */
10194 tlbl = newiTempLabel(NULL);
10195 tlbl1= newiTempLabel(NULL);
10197 size = AOP_SIZE(result);
10200 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10202 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10204 /* offset should be 0, 1 or 3 */
10205 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10207 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10209 pic16_emitpcode(POC_MOVWF, pctemp);
10212 pic16_emitpLabel(tlbl->key);
10214 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10215 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10218 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10221 pic16_emitpcode(POC_DECFSZ, pctemp);
10222 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10223 pic16_emitpLabel(tlbl1->key);
10225 pic16_popReleaseTempReg(pctemp,1);
10227 size = AOP_SIZE(result);
10229 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10230 pic16_emitcode("rlc","a");
10231 pic16_emitcode("mov","ov,c");
10232 /* if it is only one byte then */
10234 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10236 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10237 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10238 pic16_emitcode("mov","c,ov");
10239 pic16_emitcode("rrc","a");
10240 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10241 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10242 pic16_aopPut(AOP(result),"a",0);
10246 reAdjustPreg(AOP(result));
10247 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10248 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10249 pic16_emitcode("mov","c,ov");
10251 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10253 pic16_emitcode("rrc","a");
10254 pic16_aopPut(AOP(result),"a",offset--);
10256 reAdjustPreg(AOP(result));
10257 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10258 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10263 pic16_freeAsmop(left,NULL,ic,TRUE);
10264 pic16_freeAsmop(result,NULL,ic,TRUE);
10265 pic16_freeAsmop(right,NULL,ic,TRUE);
10269 #if !(USE_GENERIC_SIGNED_SHIFT)
10270 #warning This implementation of genRightShift() is incomplete!
10271 /*-----------------------------------------------------------------*/
10272 /* genRightShift - generate code for right shifting */
10273 /*-----------------------------------------------------------------*/
10274 static void genRightShift (iCode *ic)
10276 operand *right, *left, *result;
10280 symbol *tlbl, *tlbl1 ;
10282 /* if signed then we do it the hard way preserve the
10283 sign bit moving it inwards */
10284 letype = getSpec(operandType(IC_LEFT(ic)));
10285 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10287 if (!SPEC_USIGN(letype)) {
10288 genSignedRightShift (ic);
10292 /* signed & unsigned types are treated the same : i.e. the
10293 signed is NOT propagated inwards : quoting from the
10294 ANSI - standard : "for E1 >> E2, is equivalent to division
10295 by 2**E2 if unsigned or if it has a non-negative value,
10296 otherwise the result is implementation defined ", MY definition
10297 is that the sign does not get propagated */
10299 right = IC_RIGHT(ic);
10300 left = IC_LEFT(ic);
10301 result = IC_RESULT(ic);
10303 pic16_aopOp(right,ic,FALSE);
10305 /* if the shift count is known then do it
10306 as efficiently as possible */
10307 if (AOP_TYPE(right) == AOP_LIT) {
10308 genRightShiftLiteral (left,right,result,ic, 0);
10312 /* shift count is unknown then we have to form
10313 a loop get the loop count in B : Note: we take
10314 only the lower order byte since shifting
10315 more that 32 bits make no sense anyway, ( the
10316 largest size of an object can be only 32 bits ) */
10318 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10319 pic16_emitcode("inc","b");
10320 pic16_aopOp(left,ic,FALSE);
10321 pic16_aopOp(result,ic,FALSE);
10323 /* now move the left to the result if they are not the
10325 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10326 AOP_SIZE(result) > 1) {
10328 size = AOP_SIZE(result);
10331 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10332 if (*l == '@' && IS_AOP_PREG(result)) {
10334 pic16_emitcode("mov","a,%s",l);
10335 pic16_aopPut(AOP(result),"a",offset);
10337 pic16_aopPut(AOP(result),l,offset);
10342 tlbl = newiTempLabel(NULL);
10343 tlbl1= newiTempLabel(NULL);
10344 size = AOP_SIZE(result);
10347 /* if it is only one byte then */
10350 tlbl = newiTempLabel(NULL);
10351 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10352 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10353 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10356 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10357 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10358 pic16_emitpLabel(tlbl->key);
10359 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10360 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10362 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10367 reAdjustPreg(AOP(result));
10368 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10369 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10372 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10374 pic16_emitcode("rrc","a");
10375 pic16_aopPut(AOP(result),"a",offset--);
10377 reAdjustPreg(AOP(result));
10379 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10380 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10383 pic16_freeAsmop(left,NULL,ic,TRUE);
10384 pic16_freeAsmop (right,NULL,ic,TRUE);
10385 pic16_freeAsmop(result,NULL,ic,TRUE);
10389 #if (USE_GENERIC_SIGNED_SHIFT)
10390 /*-----------------------------------------------------------------*/
10391 /* genGenericShift - generates code for left or right shifting */
10392 /*-----------------------------------------------------------------*/
10393 static void genGenericShift (iCode *ic, int isShiftLeft) {
10394 operand *left,*right, *result;
10396 int sign, signedCount;
10397 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10398 PIC_OPCODE pos_shift, neg_shift;
10402 right = IC_RIGHT(ic);
10403 left = IC_LEFT(ic);
10404 result = IC_RESULT(ic);
10406 pic16_aopOp(right,ic,FALSE);
10407 pic16_aopOp(left,ic,FALSE);
10408 pic16_aopOp(result,ic,TRUE);
10410 sign = !SPEC_USIGN(operandType (left));
10411 signedCount = !SPEC_USIGN(operandType (right));
10413 /* if the shift count is known then do it
10414 as efficiently as possible */
10415 if (AOP_TYPE(right) == AOP_LIT) {
10416 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10417 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10418 // we should modify right->aopu.aop_lit here!
10419 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10420 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10422 pic16_genLeftShiftLiteral (left,right,result,ic);
10424 genRightShiftLiteral (left,right,result,ic, sign);
10427 } // if (right is literal)
10429 /* shift count is unknown then we have to form a loop.
10430 * Note: we take only the lower order byte since shifting
10431 * more than 32 bits make no sense anyway, ( the
10432 * largest size of an object can be only 32 bits )
10433 * Note: we perform arithmetic shifts if the left operand is
10434 * signed and we do an (effective) right shift, i. e. we
10435 * shift in the sign bit from the left. */
10437 label_complete = newiTempLabel ( NULL );
10438 label_loop_pos = newiTempLabel ( NULL );
10439 label_loop_neg = NULL;
10440 label_negative = NULL;
10441 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10442 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10445 // additional labels needed
10446 label_loop_neg = newiTempLabel ( NULL );
10447 label_negative = newiTempLabel ( NULL );
10450 // copy source to result -- this will effectively truncate the left operand to the size of result!
10451 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10452 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10453 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10454 pic16_mov2f (AOP(result),AOP(left), offset);
10457 // if result is longer than left, fill with zeros (or sign)
10458 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10459 if (sign && AOP_SIZE(left) > 0) {
10460 // shift signed operand -- fill with sign
10461 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10462 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10463 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10464 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10465 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10468 // shift unsigned operand -- fill result with zeros
10469 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10470 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10473 } // if (size mismatch)
10475 pic16_mov2w (AOP(right), 0);
10476 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10477 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10480 // perform a shift by one (shift count is positive)
10481 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10482 // 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])
10483 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_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10491 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10493 // perform a shift by one (shift count is positive)
10494 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10495 // 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])
10496 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10497 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10499 pic16_emitpLabel (label_loop_pos->key);
10500 if (sign && (pos_shift == POC_RRCF)) {
10501 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10504 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10505 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10506 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10507 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10511 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10513 pic16_emitpLabel (label_negative->key);
10514 // perform a shift by -1 (shift count is negative)
10515 // 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)
10517 pic16_emitpLabel (label_loop_neg->key);
10518 if (sign && (neg_shift == POC_RRCF)) {
10519 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10522 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10523 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10524 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10525 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10526 } // if (signedCount)
10528 pic16_emitpLabel (label_complete->key);
10531 pic16_freeAsmop (right,NULL,ic,TRUE);
10532 pic16_freeAsmop(left,NULL,ic,TRUE);
10533 pic16_freeAsmop(result,NULL,ic,TRUE);
10536 static void genLeftShift (iCode *ic) {
10537 genGenericShift (ic, 1);
10540 static void genRightShift (iCode *ic) {
10541 genGenericShift (ic, 0);
10546 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10547 void pic16_loadFSR0(operand *op, int lit)
10549 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10550 if (AOP_TYPE(op) == AOP_LIT) {
10551 /* handle 12 bit integers correctly */
10552 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10553 if ((val & 0x0fff) != val) {
10554 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10555 val, (val & 0x0fff) );
10558 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10560 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10563 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10564 // set up FSR0 with address of result
10565 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10566 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10570 /*----------------------------------------------------------------*/
10571 /* pic16_derefPtr - move one byte from the location ptr points to */
10572 /* to WREG (doWrite == 0) or one byte from WREG */
10573 /* to the location ptr points to (doWrite != 0) */
10574 /*----------------------------------------------------------------*/
10575 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10577 if (!IS_PTR(operandType(ptr)))
10579 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10580 else pic16_mov2w (AOP(ptr), 0);
10584 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10585 /* We might determine pointer type right here: */
10586 p_type = DCL_TYPE(operandType(ptr));
10591 if (!fsr0_setup || !*fsr0_setup)
10593 pic16_loadFSR0( ptr, 0 );
10594 if (fsr0_setup) *fsr0_setup = 1;
10597 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10599 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10603 if (AOP(ptr)->aopu.aop_reg[2]) {
10604 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10605 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10606 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10607 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10608 pic16_mov2w(AOP(ptr), 2);
10609 pic16_callGenericPointerRW(doWrite, 1);
10611 // data pointer (just 2 byte given)
10612 if (!fsr0_setup || !*fsr0_setup)
10614 pic16_loadFSR0( ptr, 0 );
10615 if (fsr0_setup) *fsr0_setup = 1;
10618 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10620 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10625 assert (0 && "invalid pointer type specified");
10630 /*-----------------------------------------------------------------*/
10631 /* genUnpackBits - generates code for unpacking bits */
10632 /*-----------------------------------------------------------------*/
10633 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10636 sym_link *etype, *letype;
10637 int blen=0, bstr=0;
10642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10643 etype = getSpec(operandType(result));
10644 letype = getSpec(operandType(left));
10646 // if(IS_BITFIELD(etype)) {
10647 blen = SPEC_BLEN(etype);
10648 bstr = SPEC_BSTR(etype);
10651 lbstr = SPEC_BSTR( letype );
10653 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10654 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10657 if((blen == 1) && (bstr < 8)
10658 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10659 /* it is a single bit, so use the appropriate bit instructions */
10660 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10662 same = pic16_sameRegs(AOP(left),AOP(result));
10663 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10664 pic16_emitpcode(POC_CLRF, op);
10666 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10667 /* workaround to reduce the extra lfsr instruction */
10668 pic16_emitpcode(POC_BTFSC,
10669 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10671 assert (PIC_IS_DATA_PTR (operandType(left)));
10672 pic16_loadFSR0 (left, 0);
10673 pic16_emitpcode(POC_BTFSC,
10674 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10677 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10678 /* unsigned bitfields result in either 0 or 1 */
10679 pic16_emitpcode(POC_INCF, op);
10681 /* signed bitfields result in either 0 or -1 */
10682 pic16_emitpcode(POC_DECF, op);
10685 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10688 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10694 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10695 // access symbol directly
10696 pic16_mov2w (AOP(left), 0);
10698 pic16_derefPtr (left, ptype, 0, NULL);
10701 /* if we have bitdisplacement then it fits */
10702 /* into this byte completely or if length is */
10703 /* less than a byte */
10704 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10706 /* shift right acc */
10709 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10710 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10712 /* VR -- normally I would use the following, but since we use the hack,
10713 * to avoid the masking from AccRsh, why not mask it right now? */
10716 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10719 /* extend signed bitfields to 8 bits */
10720 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10722 assert (blen + bstr > 0);
10723 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10724 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10729 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10733 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10734 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10741 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10743 int size, offset = 0, leoffset=0 ;
10745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10746 pic16_aopOp(result, ic, TRUE);
10750 size = AOP_SIZE(result);
10751 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10755 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10756 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10757 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10762 if(AOP(left)->aopu.pcop->type == PO_DIR)
10763 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10765 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10768 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10770 // pic16_DumpOp("(result)",result);
10771 if(is_LitAOp(AOP(result))) {
10772 pic16_mov2w(AOP(left), offset); // patch 8
10773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10775 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10776 pic16_popGet(AOP(left), offset), //patch 8
10777 pic16_popGet(AOP(result), offset)));
10785 pic16_freeAsmop(result,NULL,ic,TRUE);
10790 /*-----------------------------------------------------------------*/
10791 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10792 /*-----------------------------------------------------------------*/
10793 static void genNearPointerGet (operand *left,
10797 // asmop *aop = NULL;
10798 //regs *preg = NULL ;
10799 sym_link *rtype, *retype;
10800 sym_link *ltype, *letype;
10804 rtype = operandType(result);
10805 retype= getSpec(rtype);
10806 ltype = operandType(left);
10807 letype= getSpec(ltype);
10809 pic16_aopOp(left,ic,FALSE);
10811 // pic16_DumpOp("(left)",left);
10812 // pic16_DumpOp("(result)",result);
10814 /* if left is rematerialisable and
10815 * result is not bit variable type and
10816 * the left is pointer to data space i.e
10817 * lower 128 bytes of space */
10819 if (AOP_TYPE(left) == AOP_PCODE
10820 && !IS_BITFIELD(retype)
10821 && DCL_TYPE(ltype) == POINTER) {
10823 genDataPointerGet (left,result,ic);
10824 pic16_freeAsmop(left, NULL, ic, TRUE);
10828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10829 pic16_aopOp (result,ic,TRUE);
10831 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10834 if(IS_BITFIELD( retype )
10835 && (SPEC_BLEN(operandType(result))==1)
10839 int bitstrt, bytestrt;
10841 /* if this is bitfield of size 1, see if we are checking the value
10842 * of a single bit in an if-statement,
10843 * if yes, then don't generate usual code, but execute the
10844 * genIfx directly -- VR */
10848 /* CHECK: if next iCode is IFX
10849 * and current result operand is nextic's conditional operand
10850 * and current result operand live ranges ends at nextic's key number
10852 if((nextic->op == IFX)
10853 && (result == IC_COND(nextic))
10854 && (OP_LIVETO(result) == nextic->seq)
10855 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10857 /* everything is ok then */
10858 /* find a way to optimize the genIfx iCode */
10860 bytestrt = SPEC_BSTR(operandType(result))/8;
10861 bitstrt = SPEC_BSTR(operandType(result))%8;
10863 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10865 genIfxpCOpJump(nextic, jop);
10867 pic16_freeAsmop(left, NULL, ic, TRUE);
10868 pic16_freeAsmop(result, NULL, ic, TRUE);
10874 /* if bitfield then unpack the bits */
10875 if (IS_BITFIELD(letype))
10876 genUnpackBits (result, left, NULL, POINTER);
10878 /* we have can just get the values */
10879 int size = AOP_SIZE(result);
10882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10884 pic16_loadFSR0( left, 0 );
10888 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10889 pic16_popGet(AOP(result), offset++)));
10891 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10892 pic16_popGet(AOP(result), offset++)));
10898 /* now some housekeeping stuff */
10900 /* we had to allocate for this iCode */
10901 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10902 pic16_freeAsmop(NULL,aop,ic,TRUE);
10904 /* we did not allocate which means left
10905 * already in a pointer register, then
10906 * if size > 0 && this could be used again
10907 * we have to point it back to where it
10909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10910 if (AOP_SIZE(result) > 1
10911 && !OP_SYMBOL(left)->remat
10912 && ( OP_SYMBOL(left)->liveTo > ic->seq
10914 // int size = AOP_SIZE(result) - 1;
10916 // pic16_emitcode("dec","%s",rname);
10922 pic16_freeAsmop(left,NULL,ic,TRUE);
10923 pic16_freeAsmop(result,NULL,ic,TRUE);
10926 /*-----------------------------------------------------------------*/
10927 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10928 /*-----------------------------------------------------------------*/
10929 static void genPagedPointerGet (operand *left,
10934 regs *preg = NULL ;
10936 sym_link *rtype, *retype;
10938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10940 rtype = operandType(result);
10941 retype= getSpec(rtype);
10943 pic16_aopOp(left,ic,FALSE);
10945 /* if the value is already in a pointer register
10946 then don't need anything more */
10947 if (!AOP_INPREG(AOP(left))) {
10948 /* otherwise get a free pointer register */
10950 preg = getFreePtr(ic,&aop,FALSE);
10951 pic16_emitcode("mov","%s,%s",
10953 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10954 rname = preg->name ;
10956 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10958 pic16_freeAsmop(left,NULL,ic,TRUE);
10959 pic16_aopOp (result,ic,TRUE);
10961 /* if bitfield then unpack the bits */
10962 if (IS_BITFIELD(retype))
10963 genUnpackBits (result,left,rname,PPOINTER);
10965 /* we have can just get the values */
10966 int size = AOP_SIZE(result);
10971 pic16_emitcode("movx","a,@%s",rname);
10972 pic16_aopPut(AOP(result),"a",offset);
10977 pic16_emitcode("inc","%s",rname);
10981 /* now some housekeeping stuff */
10983 /* we had to allocate for this iCode */
10984 pic16_freeAsmop(NULL,aop,ic,TRUE);
10986 /* we did not allocate which means left
10987 already in a pointer register, then
10988 if size > 0 && this could be used again
10989 we have to point it back to where it
10991 if (AOP_SIZE(result) > 1 &&
10992 !OP_SYMBOL(left)->remat &&
10993 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10995 int size = AOP_SIZE(result) - 1;
10997 pic16_emitcode("dec","%s",rname);
11002 pic16_freeAsmop(result,NULL,ic,TRUE);
11008 /* This code is not adjusted to PIC16 and fails utterly.
11009 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11011 /*-----------------------------------------------------------------*/
11012 /* genFarPointerGet - gget value from far space */
11013 /*-----------------------------------------------------------------*/
11014 static void genFarPointerGet (operand *left,
11015 operand *result, iCode *ic)
11018 sym_link *retype = getSpec(operandType(result));
11020 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11022 pic16_aopOp(left,ic,FALSE);
11024 /* if the operand is already in dptr
11025 then we do nothing else we move the value to dptr */
11026 if (AOP_TYPE(left) != AOP_STR) {
11027 /* if this is remateriazable */
11028 if (AOP_TYPE(left) == AOP_IMMD)
11029 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11030 else { /* we need to get it byte by byte */
11031 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11032 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11033 if (options.model == MODEL_FLAT24)
11035 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11039 /* so dptr know contains the address */
11040 pic16_freeAsmop(left,NULL,ic,TRUE);
11041 pic16_aopOp(result,ic,TRUE);
11043 /* if bit then unpack */
11044 if (IS_BITFIELD(retype))
11045 genUnpackBits(result,left,"dptr",FPOINTER);
11047 size = AOP_SIZE(result);
11051 pic16_emitcode("movx","a,@dptr");
11052 pic16_aopPut(AOP(result),"a",offset++);
11054 pic16_emitcode("inc","dptr");
11058 pic16_freeAsmop(result,NULL,ic,TRUE);
11063 /*-----------------------------------------------------------------*/
11064 /* genCodePointerGet - get value from code space */
11065 /*-----------------------------------------------------------------*/
11066 static void genCodePointerGet (operand *left,
11067 operand *result, iCode *ic)
11070 sym_link *retype = getSpec(operandType(result));
11072 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11074 pic16_aopOp(left,ic,FALSE);
11076 /* if the operand is already in dptr
11077 then we do nothing else we move the value to dptr */
11078 if (AOP_TYPE(left) != AOP_STR) {
11079 /* if this is remateriazable */
11080 if (AOP_TYPE(left) == AOP_IMMD)
11081 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11082 else { /* we need to get it byte by byte */
11083 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11084 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11085 if (options.model == MODEL_FLAT24)
11087 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11091 /* so dptr know contains the address */
11092 pic16_freeAsmop(left,NULL,ic,TRUE);
11093 pic16_aopOp(result,ic,FALSE);
11095 /* if bit then unpack */
11096 if (IS_BITFIELD(retype))
11097 genUnpackBits(result,left,"dptr",CPOINTER);
11099 size = AOP_SIZE(result);
11103 pic16_emitcode("clr","a");
11104 pic16_emitcode("movc","a,@a+dptr");
11105 pic16_aopPut(AOP(result),"a",offset++);
11107 pic16_emitcode("inc","dptr");
11111 pic16_freeAsmop(result,NULL,ic,TRUE);
11116 /*-----------------------------------------------------------------*/
11117 /* genGenPointerGet - gget value from generic pointer space */
11118 /*-----------------------------------------------------------------*/
11119 static void genGenPointerGet (operand *left,
11120 operand *result, iCode *ic)
11122 int size, offset, lit;
11123 sym_link *retype = getSpec(operandType(result));
11125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11126 pic16_aopOp(left,ic,FALSE);
11127 pic16_aopOp(result,ic,FALSE);
11128 size = AOP_SIZE(result);
11130 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11132 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11134 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11135 // load FSR0 from immediate
11136 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11138 // pic16_loadFSR0( left );
11143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11152 else { /* we need to get it byte by byte */
11153 // set up FSR0 with address from left
11154 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11155 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11161 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11163 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11170 /* if bit then unpack */
11171 if (IS_BITFIELD(retype))
11172 genUnpackBits(result,left,"BAD",GPOINTER);
11175 pic16_freeAsmop(left,NULL,ic,TRUE);
11176 pic16_freeAsmop(result,NULL,ic,TRUE);
11182 /*-----------------------------------------------------------------*/
11183 /* genGenPointerGet - gget value from generic pointer space */
11184 /*-----------------------------------------------------------------*/
11185 static void genGenPointerGet (operand *left,
11186 operand *result, iCode *ic)
11188 int size, offset, lit;
11189 sym_link *letype = getSpec(operandType(left));
11191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11192 pic16_aopOp(left,ic,FALSE);
11193 pic16_aopOp(result,ic,TRUE);
11194 size = AOP_SIZE(result);
11196 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11198 /* if bit then unpack */
11199 if (IS_BITFIELD(letype)) {
11200 genUnpackBits(result,left,"BAD",GPOINTER);
11204 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11206 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11207 // load FSR0 from immediate
11208 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11210 werror(W_POSSBUG2, __FILE__, __LINE__);
11215 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11217 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11224 } else { /* we need to get it byte by byte */
11226 /* set up WREG:PRODL:FSR0L with address from left */
11227 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11228 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11229 pic16_mov2w(AOP(left), 2);
11230 pic16_callGenericPointerRW(0, size);
11232 assignResultValue(result, 1);
11238 pic16_freeAsmop(left,NULL,ic,TRUE);
11239 pic16_freeAsmop(result,NULL,ic,TRUE);
11242 /*-----------------------------------------------------------------*/
11243 /* genConstPointerGet - get value from const generic pointer space */
11244 /*-----------------------------------------------------------------*/
11245 static void genConstPointerGet (operand *left,
11246 operand *result, iCode *ic)
11248 //sym_link *retype = getSpec(operandType(result));
11249 // symbol *albl = newiTempLabel(NULL); // patch 15
11250 // symbol *blbl = newiTempLabel(NULL); //
11251 // PIC_OPCODE poc; // patch 15
11255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11256 pic16_aopOp(left,ic,FALSE);
11257 pic16_aopOp(result,ic,TRUE);
11258 size = AOP_SIZE(result);
11260 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11262 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11264 // set up table pointer
11265 if( (AOP_TYPE(left) == AOP_PCODE)
11266 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11267 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11269 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11270 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11271 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11272 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11273 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11274 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11276 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11277 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11278 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11282 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11283 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11287 pic16_freeAsmop(left,NULL,ic,TRUE);
11288 pic16_freeAsmop(result,NULL,ic,TRUE);
11292 /*-----------------------------------------------------------------*/
11293 /* genPointerGet - generate code for pointer get */
11294 /*-----------------------------------------------------------------*/
11295 static void genPointerGet (iCode *ic)
11297 operand *left, *result ;
11298 sym_link *type, *etype;
11303 left = IC_LEFT(ic);
11304 result = IC_RESULT(ic) ;
11306 /* depending on the type of pointer we need to
11307 move it to the correct pointer register */
11308 type = operandType(left);
11309 etype = getSpec(type);
11312 if (IS_PTR_CONST(type))
11314 if (IS_CODEPTR(type))
11316 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11318 /* if left is of type of pointer then it is simple */
11319 if (IS_PTR(type) && !IS_FUNC(type->next))
11320 p_type = DCL_TYPE(type);
11322 /* we have to go by the storage class */
11323 p_type = PTR_TYPE(SPEC_OCLS(etype));
11325 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11327 if (SPEC_OCLS(etype)->codesp ) {
11328 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11329 //p_type = CPOINTER ;
11331 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11332 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11333 /*p_type = FPOINTER ;*/
11335 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11336 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11337 /* p_type = PPOINTER; */
11339 if (SPEC_OCLS(etype) == idata ) {
11340 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11341 /* p_type = IPOINTER; */
11343 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11344 /* p_type = POINTER ; */
11348 /* now that we have the pointer type we assign
11349 the pointer values */
11354 genNearPointerGet (left,result,ic);
11358 genPagedPointerGet(left,result,ic);
11362 /* PICs do not support FAR pointers... */
11363 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11365 genFarPointerGet (left,result,ic);
11370 genConstPointerGet (left,result,ic);
11371 //pic16_emitcodePointerGet (left,result,ic);
11376 if (IS_PTR_CONST(type))
11377 genConstPointerGet (left,result,ic);
11380 genGenPointerGet (left,result,ic);
11384 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11385 "genPointerGet: illegal pointer type");
11390 /*-----------------------------------------------------------------*/
11391 /* genPackBits - generates code for packed bit storage */
11392 /*-----------------------------------------------------------------*/
11393 static void genPackBits (sym_link *etype , operand *result,
11395 char *rname, int p_type)
11401 int shifted_and_masked = 0;
11402 unsigned long lit = (unsigned long)-1;
11405 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11406 blen = SPEC_BLEN(etype);
11407 bstr = SPEC_BSTR(etype);
11409 retype = getSpec(operandType(right));
11411 if(AOP_TYPE(right) == AOP_LIT) {
11412 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11414 if((blen == 1) && (bstr < 8)) {
11415 /* it is a single bit, so use the appropriate bit instructions */
11417 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11419 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11420 /* workaround to reduce the extra lfsr instruction */
11422 pic16_emitpcode(POC_BSF,
11423 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11425 pic16_emitpcode(POC_BCF,
11426 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11429 if (PIC_IS_DATA_PTR(operandType(result))) {
11430 pic16_loadFSR0(result, 0);
11431 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11432 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11434 /* get old value */
11435 pic16_derefPtr (result, p_type, 0, NULL);
11436 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11437 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11438 /* write back new value */
11439 pic16_derefPtr (result, p_type, 1, NULL);
11445 /* IORLW below is more efficient */
11446 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11447 lit = (lit & ((1UL << blen) - 1)) << bstr;
11448 shifted_and_masked = 1;
11451 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11452 && IS_BITFIELD(retype)
11453 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11457 rblen = SPEC_BLEN( retype );
11458 rbstr = SPEC_BSTR( retype );
11460 if(IS_BITFIELD(etype)) {
11461 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11462 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11464 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11467 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11469 if(IS_BITFIELD(etype)) {
11470 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11472 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11475 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11479 /* move right to W */
11480 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11483 /* if the bit length is less than or */
11484 /* it exactly fits a byte then */
11485 if((shCnt=SPEC_BSTR(etype))
11486 || SPEC_BLEN(etype) <= 8 ) {
11487 int fsr0_setup = 0;
11489 if (blen != 8 || bstr != 0) {
11490 // we need to combine the value with the old value
11491 if(!shifted_and_masked)
11493 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11495 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11496 SPEC_BSTR(etype), SPEC_BLEN(etype));
11498 /* shift left acc, do NOT mask the result again */
11501 /* using PRODH as a temporary register here */
11502 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11505 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11506 || IS_DIRECT(result)) {
11507 /* access symbol directly */
11508 pic16_mov2w (AOP(result), 0);
11510 /* get old value */
11511 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11514 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11515 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11516 (unsigned char)(0xff >> (8-bstr))) ));
11517 if (!shifted_and_masked) {
11518 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11520 /* We have the shifted and masked (literal) right value in `lit' */
11522 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11524 } // if (blen != 8 || bstr != 0)
11526 /* write new value back */
11527 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11528 || IS_DIRECT(result)) {
11529 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11531 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11540 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11541 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11546 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11547 rLen = SPEC_BLEN(etype)-8;
11549 /* now generate for lengths greater than one byte */
11553 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11559 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11565 pic16_emitcode("movx","@dptr,a");
11570 DEBUGpic16_emitcode(";lcall","__gptrput");
11578 pic16_mov2w(AOP(right), offset++);
11581 /* last last was not complete */
11583 /* save the byte & read byte */
11586 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11587 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11592 pic16_emitcode ("mov","b,a");
11593 pic16_emitcode("movx","a,@dptr");
11597 pic16_emitcode ("push","b");
11598 pic16_emitcode ("push","acc");
11599 pic16_emitcode ("lcall","__gptrget");
11600 pic16_emitcode ("pop","b");
11606 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11607 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11608 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11609 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11610 // pic16_emitcode ("orl","a,b");
11613 // if (p_type == GPOINTER)
11614 // pic16_emitcode("pop","b");
11619 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11620 // pic16_emitcode("mov","@%s,a",rname);
11624 pic16_emitcode("movx","@dptr,a");
11628 DEBUGpic16_emitcode(";lcall","__gptrput");
11635 // pic16_freeAsmop(right, NULL, ic, TRUE);
11638 /*-----------------------------------------------------------------*/
11639 /* genDataPointerSet - remat pointer to data space */
11640 /*-----------------------------------------------------------------*/
11641 static void genDataPointerSet(operand *right,
11645 int size, offset = 0, resoffset=0 ;
11647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11648 pic16_aopOp(right,ic,FALSE);
11650 size = AOP_SIZE(right);
11652 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11655 if ( AOP_TYPE(result) == AOP_PCODE) {
11656 fprintf(stderr,"genDataPointerSet %s, %d\n",
11657 AOP(result)->aopu.pcop->name,
11658 (AOP(result)->aopu.pcop->type == PO_DIR)?
11659 PCOR(AOP(result)->aopu.pcop)->instance:
11660 PCOI(AOP(result)->aopu.pcop)->offset);
11664 if(AOP(result)->aopu.pcop->type == PO_DIR)
11665 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11668 if (AOP_TYPE(right) == AOP_LIT) {
11671 if(!IS_FLOAT(operandType( right )))
11672 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11675 unsigned long lit_int;
11679 /* take care if literal is a float */
11680 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11681 lit = info.lit_int;
11683 lit = lit >> (8*offset);
11684 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11686 pic16_mov2w(AOP(right), offset);
11687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11693 pic16_freeAsmop(right,NULL,ic,TRUE);
11698 /*-----------------------------------------------------------------*/
11699 /* genNearPointerSet - pic16_emitcode for near pointer put */
11700 /*-----------------------------------------------------------------*/
11701 static void genNearPointerSet (operand *right,
11707 sym_link *ptype = operandType(result);
11708 sym_link *resetype;
11710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11711 retype= getSpec(operandType(right));
11712 resetype = getSpec(operandType(result));
11714 pic16_aopOp(result,ic,FALSE);
11716 /* if the result is rematerializable &
11717 * in data space & not a bit variable */
11719 /* and result is not a bit variable */
11720 if (AOP_TYPE(result) == AOP_PCODE
11721 // && AOP_TYPE(result) == AOP_IMMD
11722 && DCL_TYPE(ptype) == POINTER
11723 && !IS_BITFIELD(retype)
11724 && !IS_BITFIELD(resetype)) {
11726 genDataPointerSet (right,result,ic);
11727 pic16_freeAsmop(result,NULL,ic,TRUE);
11731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11732 pic16_aopOp(right,ic,FALSE);
11733 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11735 /* if bitfield then unpack the bits */
11736 if (IS_BITFIELD(resetype)) {
11737 genPackBits (resetype, result, right, NULL, POINTER);
11739 /* we have can just get the values */
11740 int size = AOP_SIZE(right);
11743 pic16_loadFSR0(result, 0);
11745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11747 if (AOP_TYPE(right) == AOP_LIT) {
11748 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11750 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11752 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11754 } else { // no literal
11756 pic16_emitpcode(POC_MOVFF,
11757 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11758 pic16_popCopyReg(&pic16_pc_postinc0)));
11760 pic16_emitpcode(POC_MOVFF,
11761 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11762 pic16_popCopyReg(&pic16_pc_indf0)));
11770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11771 /* now some housekeeping stuff */
11773 /* we had to allocate for this iCode */
11774 pic16_freeAsmop(NULL,aop,ic,TRUE);
11776 /* we did not allocate which means left
11777 * already in a pointer register, then
11778 * if size > 0 && this could be used again
11779 * we have to point it back to where it
11781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11782 if (AOP_SIZE(right) > 1
11783 && !OP_SYMBOL(result)->remat
11784 && ( OP_SYMBOL(result)->liveTo > ic->seq
11787 int size = AOP_SIZE(right) - 1;
11790 pic16_emitcode("decf","fsr0,f");
11791 //pic16_emitcode("dec","%s",rname);
11795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11798 pic16_freeAsmop(right,NULL,ic,TRUE);
11799 pic16_freeAsmop(result,NULL,ic,TRUE);
11802 /*-----------------------------------------------------------------*/
11803 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11804 /*-----------------------------------------------------------------*/
11805 static void genPagedPointerSet (operand *right,
11810 regs *preg = NULL ;
11814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11816 retype= getSpec(operandType(right));
11818 pic16_aopOp(result,ic,FALSE);
11820 /* if the value is already in a pointer register
11821 then don't need anything more */
11822 if (!AOP_INPREG(AOP(result))) {
11823 /* otherwise get a free pointer register */
11825 preg = getFreePtr(ic,&aop,FALSE);
11826 pic16_emitcode("mov","%s,%s",
11828 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11829 rname = preg->name ;
11831 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11833 pic16_freeAsmop(result,NULL,ic,TRUE);
11834 pic16_aopOp (right,ic,FALSE);
11836 /* if bitfield then unpack the bits */
11837 if (IS_BITFIELD(retype))
11838 genPackBits (retype,result,right,rname,PPOINTER);
11840 /* we have can just get the values */
11841 int size = AOP_SIZE(right);
11845 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11848 pic16_emitcode("movx","@%s,a",rname);
11851 pic16_emitcode("inc","%s",rname);
11857 /* now some housekeeping stuff */
11859 /* we had to allocate for this iCode */
11860 pic16_freeAsmop(NULL,aop,ic,TRUE);
11862 /* we did not allocate which means left
11863 already in a pointer register, then
11864 if size > 0 && this could be used again
11865 we have to point it back to where it
11867 if (AOP_SIZE(right) > 1 &&
11868 !OP_SYMBOL(result)->remat &&
11869 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11871 int size = AOP_SIZE(right) - 1;
11873 pic16_emitcode("dec","%s",rname);
11878 pic16_freeAsmop(right,NULL,ic,TRUE);
11884 /* This code is not adjusted to PIC16 and fails utterly...
11885 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11887 /*-----------------------------------------------------------------*/
11888 /* genFarPointerSet - set value from far space */
11889 /*-----------------------------------------------------------------*/
11890 static void genFarPointerSet (operand *right,
11891 operand *result, iCode *ic)
11894 sym_link *retype = getSpec(operandType(right));
11896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11897 pic16_aopOp(result,ic,FALSE);
11899 /* if the operand is already in dptr
11900 then we do nothing else we move the value to dptr */
11901 if (AOP_TYPE(result) != AOP_STR) {
11902 /* if this is remateriazable */
11903 if (AOP_TYPE(result) == AOP_IMMD)
11904 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11905 else { /* we need to get it byte by byte */
11906 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11907 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11908 if (options.model == MODEL_FLAT24)
11910 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11914 /* so dptr know contains the address */
11915 pic16_freeAsmop(result,NULL,ic,TRUE);
11916 pic16_aopOp(right,ic,FALSE);
11918 /* if bit then unpack */
11919 if (IS_BITFIELD(retype))
11920 genPackBits(retype,result,right,"dptr",FPOINTER);
11922 size = AOP_SIZE(right);
11926 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11928 pic16_emitcode("movx","@dptr,a");
11930 pic16_emitcode("inc","dptr");
11934 pic16_freeAsmop(right,NULL,ic,TRUE);
11938 /*-----------------------------------------------------------------*/
11939 /* genGenPointerSet - set value from generic pointer space */
11940 /*-----------------------------------------------------------------*/
11942 static void genGenPointerSet (operand *right,
11943 operand *result, iCode *ic)
11945 int i, size, offset, lit;
11946 sym_link *retype = getSpec(operandType(right));
11948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11950 pic16_aopOp(result,ic,FALSE);
11951 pic16_aopOp(right,ic,FALSE);
11952 size = AOP_SIZE(right);
11955 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11957 /* if the operand is already in dptr
11958 then we do nothing else we move the value to dptr */
11959 if (AOP_TYPE(result) != AOP_STR) {
11960 /* if this is remateriazable */
11961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11962 // WARNING: anythig until "else" is untested!
11963 if (AOP_TYPE(result) == AOP_IMMD) {
11964 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11965 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11966 // load FSR0 from immediate
11967 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11971 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11973 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11979 else { /* we need to get it byte by byte */
11980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11981 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11983 // set up FSR0 with address of result
11984 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11985 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11987 /* hack hack! see if this the FSR. If so don't load W */
11988 if(AOP_TYPE(right) != AOP_ACC) {
11990 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11992 if(AOP_TYPE(right) == AOP_LIT)
11995 // note: pic16_popGet handles sign extension
11996 for(i=0;i<size;i++) {
11997 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11999 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12001 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12006 for(i=0;i<size;i++) {
12008 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12009 pic16_popCopyReg(&pic16_pc_postinc0)));
12011 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12012 pic16_popCopyReg(&pic16_pc_indf0)));
12018 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12019 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12021 } // if (AOP_TYPE(result) != AOP_IMMD)
12023 } // if (AOP_TYPE(result) != AOP_STR)
12024 /* so dptr know contains the address */
12027 /* if bit then unpack */
12028 if (IS_BITFIELD(retype))
12029 genPackBits(retype,result,right,"dptr",GPOINTER);
12031 size = AOP_SIZE(right);
12034 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12036 // set up FSR0 with address of result
12037 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12038 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12041 if (AOP_TYPE(right) == AOP_LIT) {
12042 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12044 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12046 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12048 } else { // no literal
12050 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12052 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12060 pic16_freeAsmop(right,NULL,ic,TRUE);
12061 pic16_freeAsmop(result,NULL,ic,TRUE);
12065 static void genGenPointerSet (operand *right,
12066 operand *result, iCode *ic)
12069 sym_link *retype = getSpec(operandType(result));
12071 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12073 pic16_aopOp(result,ic,FALSE);
12074 pic16_aopOp(right,ic,FALSE);
12075 size = AOP_SIZE(right);
12077 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12080 /* if bit then unpack */
12081 if (IS_BITFIELD(retype)) {
12082 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12083 genPackBits(retype,result,right,"dptr",GPOINTER);
12087 size = AOP_SIZE(right);
12089 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12092 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12094 /* value of right+0 is placed on stack, which will be retrieved
12095 * by the support function thus restoring the stack. The important
12096 * thing is that there is no need to manually restore stack pointer
12098 pushaop(AOP(right), 0);
12099 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12100 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12101 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12102 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12104 /* load address to write to in WREG:FSR0H:FSR0L */
12105 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12106 pic16_popCopyReg(&pic16_pc_fsr0l)));
12107 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12108 pic16_popCopyReg(&pic16_pc_prodl)));
12109 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12111 pic16_callGenericPointerRW(1, size);
12114 pic16_freeAsmop(right,NULL,ic,TRUE);
12115 pic16_freeAsmop(result,NULL,ic,TRUE);
12118 /*-----------------------------------------------------------------*/
12119 /* genPointerSet - stores the value into a pointer location */
12120 /*-----------------------------------------------------------------*/
12121 static void genPointerSet (iCode *ic)
12123 operand *right, *result ;
12124 sym_link *type, *etype;
12129 right = IC_RIGHT(ic);
12130 result = IC_RESULT(ic) ;
12132 /* depending on the type of pointer we need to
12133 move it to the correct pointer register */
12134 type = operandType(result);
12135 etype = getSpec(type);
12137 /* if left is of type of pointer then it is simple */
12138 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12139 p_type = DCL_TYPE(type);
12142 /* we have to go by the storage class */
12143 p_type = PTR_TYPE(SPEC_OCLS(etype));
12145 /* if (SPEC_OCLS(etype)->codesp ) { */
12146 /* p_type = CPOINTER ; */
12149 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12150 /* p_type = FPOINTER ; */
12152 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12153 /* p_type = PPOINTER ; */
12155 /* if (SPEC_OCLS(etype) == idata ) */
12156 /* p_type = IPOINTER ; */
12158 /* p_type = POINTER ; */
12161 /* now that we have the pointer type we assign
12162 the pointer values */
12167 genNearPointerSet (right,result,ic);
12171 genPagedPointerSet (right,result,ic);
12175 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12177 genFarPointerSet (right,result,ic);
12182 genGenPointerSet (right,result,ic);
12186 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12187 "genPointerSet: illegal pointer type");
12191 /*-----------------------------------------------------------------*/
12192 /* genIfx - generate code for Ifx statement */
12193 /*-----------------------------------------------------------------*/
12194 static void genIfx (iCode *ic, iCode *popIc)
12196 operand *cond = IC_COND(ic);
12201 pic16_aopOp(cond,ic,FALSE);
12203 /* get the value into acc */
12204 if (AOP_TYPE(cond) != AOP_CRY)
12205 pic16_toBoolean(cond);
12208 /* the result is now in the accumulator */
12209 pic16_freeAsmop(cond,NULL,ic,TRUE);
12211 /* if there was something to be popped then do it */
12215 /* if the condition is a bit variable */
12216 if (isbit && IS_ITEMP(cond) &&
12218 genIfxJump(ic,"c");
12219 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12221 if (isbit && !IS_ITEMP(cond))
12222 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12224 genIfxJump(ic,"a");
12229 /*-----------------------------------------------------------------*/
12230 /* genAddrOf - generates code for address of */
12231 /*-----------------------------------------------------------------*/
12232 static void genAddrOf (iCode *ic)
12234 operand *result, *left;
12236 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12237 pCodeOp *pcop0, *pcop1, *pcop2;
12241 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12243 sym = OP_SYMBOL( IC_LEFT(ic) );
12246 /* get address of symbol on stack */
12247 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12249 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12250 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12253 // operands on stack are accessible via "FSR2 + index" with index
12254 // starting at 2 for arguments and growing from 0 downwards for
12255 // local variables (index == 0 is not assigned so we add one here)
12257 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12260 assert (soffs < 0);
12264 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12265 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12266 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12267 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12268 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12269 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12270 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12276 // if(pic16_debug_verbose) {
12277 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12278 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12281 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12282 size = AOP_SIZE(IC_RESULT(ic));
12284 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12285 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12286 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12289 pic16_emitpcode(POC_MOVLW, pcop0);
12290 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12291 pic16_emitpcode(POC_MOVLW, pcop1);
12292 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12293 pic16_emitpcode(POC_MOVLW, pcop2);
12294 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12297 pic16_emitpcode(POC_MOVLW, pcop0);
12298 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12299 pic16_emitpcode(POC_MOVLW, pcop1);
12300 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12302 pic16_emitpcode(POC_MOVLW, pcop0);
12303 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12306 pic16_freeAsmop(left, NULL, ic, FALSE);
12308 pic16_freeAsmop(result,NULL,ic,TRUE);
12313 /*-----------------------------------------------------------------*/
12314 /* genFarFarAssign - assignment when both are in far space */
12315 /*-----------------------------------------------------------------*/
12316 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12318 int size = AOP_SIZE(right);
12321 /* first push the right side on to the stack */
12323 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12325 pic16_emitcode ("push","acc");
12328 pic16_freeAsmop(right,NULL,ic,FALSE);
12329 /* now assign DPTR to result */
12330 pic16_aopOp(result,ic,FALSE);
12331 size = AOP_SIZE(result);
12333 pic16_emitcode ("pop","acc");
12334 pic16_aopPut(AOP(result),"a",--offset);
12336 pic16_freeAsmop(result,NULL,ic,FALSE);
12341 /*-----------------------------------------------------------------*/
12342 /* genAssign - generate code for assignment */
12343 /*-----------------------------------------------------------------*/
12344 static void genAssign (iCode *ic)
12346 operand *result, *right;
12347 sym_link *restype, *rtype;
12348 int size, offset,know_W;
12349 unsigned long lit = 0L;
12351 result = IC_RESULT(ic);
12352 right = IC_RIGHT(ic) ;
12356 /* if they are the same */
12357 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12360 /* reversed order operands are aopOp'ed so that result operand
12361 * is effective in case right is a stack symbol. This maneauver
12362 * allows to use the _G.resDirect flag later */
12363 pic16_aopOp(result,ic,TRUE);
12364 pic16_aopOp(right,ic,FALSE);
12366 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12368 /* if they are the same registers */
12369 if (pic16_sameRegs(AOP(right),AOP(result)))
12372 /* if the result is a bit */
12373 if (AOP_TYPE(result) == AOP_CRY) {
12374 /* if the right size is a literal then
12375 we know what the value is */
12376 if (AOP_TYPE(right) == AOP_LIT) {
12378 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12379 pic16_popGet(AOP(result),0));
12381 if (((int) operandLitValue(right)))
12382 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12383 AOP(result)->aopu.aop_dir,
12384 AOP(result)->aopu.aop_dir);
12386 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12387 AOP(result)->aopu.aop_dir,
12388 AOP(result)->aopu.aop_dir);
12393 /* the right is also a bit variable */
12394 if (AOP_TYPE(right) == AOP_CRY) {
12395 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12396 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12397 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12402 /* we need to or */
12403 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12404 pic16_toBoolean(right);
12406 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12407 //pic16_aopPut(AOP(result),"a",0);
12411 /* bit variables done */
12413 size = AOP_SIZE(result);
12416 /* bit variables done */
12418 size = AOP_SIZE(result);
12419 restype = operandType(result);
12420 rtype = operandType(right);
12423 if(AOP_TYPE(right) == AOP_LIT) {
12424 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12426 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12428 /* patch tag for literals that are cast to pointers */
12429 if (IS_CODEPTR(restype)) {
12430 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12431 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12433 if (IS_GENPTR(restype))
12435 if (IS_CODEPTR(rtype)) {
12436 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12437 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12438 } else if (PIC_IS_DATA_PTR(rtype)) {
12439 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12440 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12441 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12442 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12443 } else if (IS_PTR(rtype)) {
12444 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12445 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12451 unsigned long lit_int;
12456 if(IS_FIXED16X16(operandType(right))) {
12457 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12459 /* take care if literal is a float */
12460 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12461 lit = info.lit_int;
12466 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12467 // sizeof(unsigned long int), sizeof(float));
12470 if (AOP_TYPE(right) == AOP_REG) {
12471 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12473 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12478 /* when do we have to read the program memory?
12479 * - if right itself is a symbol in code space
12480 * (we don't care what it points to if it's a pointer)
12481 * - AND right is not a function (we would want its address)
12483 if(AOP_TYPE(right) != AOP_LIT
12484 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12485 && !IS_FUNC(OP_SYM_TYPE(right))
12486 && !IS_ITEMP(right)) {
12488 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12489 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12491 // set up table pointer
12492 if(is_LitOp(right)) {
12493 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12494 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12495 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12496 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12497 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12498 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12499 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12501 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12503 pic16_popCopyReg(&pic16_pc_tblptrl)));
12504 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12505 pic16_popCopyReg(&pic16_pc_tblptrh)));
12506 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12507 pic16_popCopyReg(&pic16_pc_tblptru)));
12510 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12511 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12513 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12514 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12515 pic16_popGet(AOP(result),offset)));
12519 /* FIXME: for pointers we need to extend differently (according
12520 * to pointer type DATA/CODE/EEPROM/... :*/
12521 size = getSize(OP_SYM_TYPE(right));
12522 if(AOP_SIZE(result) > size) {
12523 size = AOP_SIZE(result) - size;
12525 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12533 /* VR - What is this?! */
12534 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12537 if(aopIdx(AOP(result),0) == 4) {
12538 /* this is a workaround to save value of right into wreg too,
12539 * value of wreg is going to be used later */
12540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12541 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12542 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12546 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12552 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12553 if(AOP_TYPE(right) == AOP_LIT) {
12555 if(know_W != (lit&0xff))
12556 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12558 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12560 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12564 } else if (AOP_TYPE(right) == AOP_CRY) {
12565 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12567 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12568 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12569 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12571 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12572 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12573 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12575 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12577 if(!_G.resDirect) { /* use this aopForSym feature */
12578 if(AOP_TYPE(result) == AOP_ACC) {
12579 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12581 if(AOP_TYPE(right) == AOP_ACC) {
12582 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12584 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12593 pic16_freeAsmop (right,NULL,ic,FALSE);
12594 pic16_freeAsmop (result,NULL,ic,TRUE);
12597 /*-----------------------------------------------------------------*/
12598 /* genJumpTab - generates code for jump table */
12599 /*-----------------------------------------------------------------*/
12600 static void genJumpTab (iCode *ic)
12605 pCodeOp *jt_offs_hi;
12610 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12611 /* get the condition into accumulator */
12612 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12614 /* multiply by three */
12615 pic16_emitcode("add","a,acc");
12616 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12618 jtab = newiTempLabel(NULL);
12619 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12620 pic16_emitcode("jmp","@a+dptr");
12621 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12624 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12625 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12627 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12628 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12629 pic16_emitpLabel(jtab->key);
12633 jt_offs = pic16_popGetTempReg(0);
12634 jt_offs_hi = pic16_popGetTempReg(1);
12635 jt_label = pic16_popGetLabel (jtab->key);
12636 //fprintf (stderr, "Creating jump table...\n");
12638 // calculate offset into jump table (idx * sizeof (GOTO))
12639 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12640 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12641 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12642 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12643 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12644 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12645 pic16_emitpcode(POC_MOVWF , jt_offs);
12647 // prepare PCLATx (set to first entry in jump table)
12648 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12649 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12650 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12651 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12652 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12654 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12655 pic16_emitpcode(POC_ADDWF , jt_offs);
12656 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12657 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12659 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12661 // release temporaries and prepare jump into table (new PCL --> WREG)
12662 pic16_emitpcode(POC_MOVFW , jt_offs);
12663 pic16_popReleaseTempReg (jt_offs_hi, 1);
12664 pic16_popReleaseTempReg (jt_offs, 0);
12666 // jump into the table
12667 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12669 pic16_emitpLabelFORCE(jtab->key);
12672 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12673 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12675 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12676 /* now generate the jump labels */
12677 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12678 jtab = setNextItem(IC_JTLABELS(ic))) {
12679 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12680 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12683 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12687 /*-----------------------------------------------------------------*/
12688 /* genMixedOperation - gen code for operators between mixed types */
12689 /*-----------------------------------------------------------------*/
12691 TSD - Written for the PIC port - but this unfortunately is buggy.
12692 This routine is good in that it is able to efficiently promote
12693 types to different (larger) sizes. Unfortunately, the temporary
12694 variables that are optimized out by this routine are sometimes
12695 used in other places. So until I know how to really parse the
12696 iCode tree, I'm going to not be using this routine :(.
12698 static int genMixedOperation (iCode *ic)
12701 operand *result = IC_RESULT(ic);
12702 sym_link *ctype = operandType(IC_LEFT(ic));
12703 operand *right = IC_RIGHT(ic);
12709 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12711 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12717 nextright = IC_RIGHT(nextic);
12718 nextleft = IC_LEFT(nextic);
12719 nextresult = IC_RESULT(nextic);
12721 pic16_aopOp(right,ic,FALSE);
12722 pic16_aopOp(result,ic,FALSE);
12723 pic16_aopOp(nextright, nextic, FALSE);
12724 pic16_aopOp(nextleft, nextic, FALSE);
12725 pic16_aopOp(nextresult, nextic, FALSE);
12727 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12729 operand *t = right;
12733 pic16_emitcode(";remove right +","");
12735 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12737 operand *t = right;
12741 pic16_emitcode(";remove left +","");
12745 big = AOP_SIZE(nextleft);
12746 small = AOP_SIZE(nextright);
12748 switch(nextic->op) {
12751 pic16_emitcode(";optimize a +","");
12752 /* if unsigned or not an integral type */
12753 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12754 pic16_emitcode(";add a bit to something","");
12757 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12759 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12760 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12761 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12763 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12771 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12772 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12773 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12776 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12778 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12779 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12780 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12781 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12782 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12785 pic16_emitcode("rlf","known_zero,w");
12792 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12793 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12794 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12796 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12806 pic16_freeAsmop(right,NULL,ic,TRUE);
12807 pic16_freeAsmop(result,NULL,ic,TRUE);
12808 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12809 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12811 nextic->generated = 1;
12818 /*-----------------------------------------------------------------*/
12819 /* genCast - gen code for casting */
12820 /*-----------------------------------------------------------------*/
12821 static void genCast (iCode *ic)
12823 operand *result = IC_RESULT(ic);
12824 sym_link *ctype = operandType(IC_LEFT(ic));
12825 sym_link *rtype = operandType(IC_RIGHT(ic));
12826 sym_link *restype = operandType(IC_RESULT(ic));
12827 operand *right = IC_RIGHT(ic);
12833 /* if they are equivalent then do nothing */
12834 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12837 pic16_aopOp(result,ic,FALSE);
12838 pic16_aopOp(right,ic,FALSE) ;
12840 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12843 /* if the result is a bit */
12844 if (AOP_TYPE(result) == AOP_CRY) {
12846 /* if the right size is a literal then
12847 * we know what the value is */
12848 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12850 if (AOP_TYPE(right) == AOP_LIT) {
12851 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12852 pic16_popGet(AOP(result),0));
12854 if (((int) operandLitValue(right)))
12855 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12856 AOP(result)->aopu.aop_dir,
12857 AOP(result)->aopu.aop_dir);
12859 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12860 AOP(result)->aopu.aop_dir,
12861 AOP(result)->aopu.aop_dir);
12865 /* the right is also a bit variable */
12866 if (AOP_TYPE(right) == AOP_CRY) {
12868 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12870 pic16_emitcode("clrc","");
12871 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12872 AOP(right)->aopu.aop_dir,
12873 AOP(right)->aopu.aop_dir);
12874 pic16_aopPut(AOP(result),"c",0);
12878 /* we need to or */
12879 if (AOP_TYPE(right) == AOP_REG) {
12880 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12881 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12882 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12884 pic16_toBoolean(right);
12885 pic16_aopPut(AOP(result),"a",0);
12889 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12892 size = AOP_SIZE(result);
12894 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12896 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12897 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12898 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12901 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12906 if(IS_BITFIELD(getSpec(restype))
12907 && IS_BITFIELD(getSpec(rtype))) {
12908 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12911 /* port from pic14 to cope with generic pointers */
12912 if (PIC_IS_TAGGED(restype))
12914 operand *result = IC_RESULT(ic);
12915 //operand *left = IC_LEFT(ic);
12916 operand *right = IC_RIGHT(ic);
12919 /* copy common part */
12920 int max, size = AOP_SIZE(result);
12921 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12922 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12927 pic16_mov2w (AOP(right), size);
12928 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12931 /* upcast into generic pointer type? */
12932 if (IS_GENPTR(restype)
12933 && !PIC_IS_TAGGED(rtype)
12934 && (AOP_SIZE(result) > max))
12936 /* determine appropriate tag for right */
12937 if (PIC_IS_DATA_PTR(rtype))
12938 tag = GPTR_TAG_DATA;
12939 else if (IS_CODEPTR(rtype))
12940 tag = GPTR_TAG_CODE;
12941 else if (PIC_IS_DATA_PTR(ctype)) {
12942 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12943 tag = GPTR_TAG_DATA;
12944 } else if (IS_CODEPTR(ctype)) {
12945 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12946 tag = GPTR_TAG_CODE;
12947 } else if (IS_PTR(rtype)) {
12948 PERFORM_ONCE(weirdcast,
12949 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12951 tag = GPTR_TAG_DATA;
12953 PERFORM_ONCE(weirdcast,
12954 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12956 tag = GPTR_TAG_DATA;
12959 assert (AOP_SIZE(result) == 3);
12960 /* zero-extend address... */
12961 for (size = max; size < AOP_SIZE(result)-1; size++)
12962 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12963 /* ...and add tag */
12964 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12965 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12966 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12967 for (size = max; size < AOP_SIZE(result)-1; size++)
12968 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12969 /* add __code tag */
12970 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12971 } else if (AOP_SIZE(result) > max) {
12972 /* extend non-pointers */
12973 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12974 pic16_addSign(result, max, 0);
12979 /* if they are the same size : or less */
12980 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12982 /* if they are in the same place */
12983 if (pic16_sameRegs(AOP(right),AOP(result)))
12986 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12988 if (IS_PTR_CONST(rtype))
12990 if (IS_CODEPTR(rtype))
12992 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12995 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12997 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12999 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13002 if(AOP_TYPE(right) == AOP_IMMD) {
13003 pCodeOp *pcop0, *pcop1, *pcop2;
13004 symbol *sym = OP_SYMBOL( right );
13006 size = AOP_SIZE(result);
13008 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13010 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13012 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13015 pic16_emitpcode(POC_MOVLW, pcop0);
13016 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13017 pic16_emitpcode(POC_MOVLW, pcop1);
13018 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13019 pic16_emitpcode(POC_MOVLW, pcop2);
13020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13023 pic16_emitpcode(POC_MOVLW, pcop0);
13024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13025 pic16_emitpcode(POC_MOVLW, pcop1);
13026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13028 pic16_emitpcode(POC_MOVLW, pcop0);
13029 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13033 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13034 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13035 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13036 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13038 if(AOP_SIZE(result) <2)
13039 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13041 /* if they in different places then copy */
13042 size = AOP_SIZE(result);
13045 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13046 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13053 /* if the result is of type pointer */
13054 if (IS_PTR(ctype)) {
13056 sym_link *type = operandType(right);
13057 sym_link *etype = getSpec(type);
13059 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13061 /* pointer to generic pointer */
13062 if (IS_GENPTR(ctype)) {
13066 p_type = DCL_TYPE(type);
13068 /* we have to go by the storage class */
13069 p_type = PTR_TYPE(SPEC_OCLS(etype));
13071 /* if (SPEC_OCLS(etype)->codesp ) */
13072 /* p_type = CPOINTER ; */
13074 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13075 /* p_type = FPOINTER ; */
13077 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13078 /* p_type = PPOINTER; */
13080 /* if (SPEC_OCLS(etype) == idata ) */
13081 /* p_type = IPOINTER ; */
13083 /* p_type = POINTER ; */
13086 /* the first two bytes are known */
13087 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13088 size = GPTRSIZE - 1;
13091 if(offset < AOP_SIZE(right)) {
13092 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13093 pic16_mov2f(AOP(result), AOP(right), offset);
13095 if ((AOP_TYPE(right) == AOP_PCODE) &&
13096 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13097 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13098 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13101 pic16_aopPut(AOP(result),
13102 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13107 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13110 /* the last byte depending on type */
13115 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13119 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13123 pic16_emitcode(";BUG!? ","%d",__LINE__);
13128 if (GPTRSIZE > AOP_SIZE(right)) {
13129 // assume __data pointer... THIS MIGHT BE WRONG!
13130 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13132 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13137 /* this should never happen */
13138 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13139 "got unknown pointer type");
13142 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13148 /* just copy the pointers */
13149 size = AOP_SIZE(result);
13152 pic16_aopPut(AOP(result),
13153 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13162 /* so we now know that the size of destination is greater
13163 than the size of the source.
13164 Now, if the next iCode is an operator then we might be
13165 able to optimize the operation without performing a cast.
13167 if(genMixedOperation(ic))
13170 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13172 /* we move to result for the size of source */
13173 size = AOP_SIZE(right);
13178 pic16_mov2f(AOP(result), AOP(right), offset);
13182 /* now depending on the sign of the destination */
13183 size = AOP_SIZE(result) - AOP_SIZE(right);
13184 /* if unsigned or not an integral type */
13185 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13187 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13189 /* we need to extend the sign :( */
13192 /* Save one instruction of casting char to int */
13193 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13194 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13195 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13197 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13200 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13202 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13204 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13212 pic16_freeAsmop(right,NULL,ic,TRUE);
13213 pic16_freeAsmop(result,NULL,ic,TRUE);
13217 /*-----------------------------------------------------------------*/
13218 /* genDjnz - generate decrement & jump if not zero instrucion */
13219 /*-----------------------------------------------------------------*/
13220 static int genDjnz (iCode *ic, iCode *ifx)
13222 symbol *lbl, *lbl1;
13223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13228 /* if the if condition has a false label
13229 then we cannot save */
13233 /* if the minus is not of the form
13235 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13236 !IS_OP_LITERAL(IC_RIGHT(ic)))
13239 if (operandLitValue(IC_RIGHT(ic)) != 1)
13242 /* if the size of this greater than one then no
13244 if (getSize(operandType(IC_RESULT(ic))) > 1)
13247 /* otherwise we can save BIG */
13248 lbl = newiTempLabel(NULL);
13249 lbl1= newiTempLabel(NULL);
13251 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13253 if (IS_AOP_PREG(IC_RESULT(ic))) {
13254 pic16_emitcode("dec","%s",
13255 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13256 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13257 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13261 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13262 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13264 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13265 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13269 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13270 ifx->generated = 1;
13274 /*-----------------------------------------------------------------*/
13275 /* genReceive - generate code for a receive iCode */
13276 /*-----------------------------------------------------------------*/
13277 static void genReceive (iCode *ic)
13283 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13284 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13286 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13288 if (isOperandInFarSpace(IC_RESULT(ic))
13289 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13290 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13292 int size = getSize(operandType(IC_RESULT(ic)));
13293 int offset = pic16_fReturnSizePic - size;
13297 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13298 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13302 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13304 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13305 size = AOP_SIZE(IC_RESULT(ic));
13308 pic16_emitcode ("pop","acc");
13309 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13312 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13314 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13317 /* set pseudo stack pointer to where it should be - dw*/
13318 GpsuedoStkPtr = ic->parmBytes;
13320 /* setting GpsuedoStkPtr has side effects here: */
13321 assignResultValue(IC_RESULT(ic), 0);
13324 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13327 /*-----------------------------------------------------------------*/
13328 /* genDummyRead - generate code for dummy read of volatiles */
13329 /*-----------------------------------------------------------------*/
13331 genDummyRead (iCode * ic)
13337 if (op && IS_SYMOP(op)) {
13338 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13339 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13342 pic16_aopOp (op, ic, FALSE);
13343 for (i=0; i < AOP_SIZE(op); i++) {
13344 // may need to protect this from the peepholer -- this is not nice but works...
13345 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13346 pic16_mov2w (AOP(op),i);
13347 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13349 pic16_freeAsmop (op, NULL, ic, TRUE);
13351 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13355 /*-----------------------------------------------------------------*/
13356 /* genpic16Code - generate code for pic16 based controllers */
13357 /*-----------------------------------------------------------------*/
13359 * At this point, ralloc.c has gone through the iCode and attempted
13360 * to optimize in a way suitable for a PIC. Now we've got to generate
13361 * PIC instructions that correspond to the iCode.
13363 * Once the instructions are generated, we'll pass through both the
13364 * peep hole optimizer and the pCode optimizer.
13365 *-----------------------------------------------------------------*/
13367 void genpic16Code (iCode *lic)
13372 lineHead = lineCurr = NULL;
13374 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13375 pic16_addpBlock(pb);
13378 /* if debug information required */
13379 if (options.debug && currFunc) {
13381 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13386 for (ic = lic ; ic ; ic = ic->next ) {
13388 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13389 if ( cln != ic->lineno ) {
13390 if ( options.debug ) {
13391 debugFile->writeCLine (ic);
13394 if(!options.noCcodeInAsm) {
13395 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13396 printCLine(ic->filename, ic->lineno)));
13402 if(options.iCodeInAsm) {
13405 /* insert here code to print iCode as comment */
13406 l = Safe_strdup(printILine(ic));
13407 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13410 /* if the result is marked as
13411 * spilt and rematerializable or code for
13412 * this has already been generated then
13414 if (resultRemat(ic) || ic->generated )
13417 /* depending on the operation */
13436 /* IPOP happens only when trying to restore a
13437 * spilt live range, if there is an ifx statement
13438 * following this pop then the if statement might
13439 * be using some of the registers being popped which
13440 * would destroy the contents of the register so
13441 * we need to check for this condition and handle it */
13443 && ic->next->op == IFX
13444 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13445 genIfx (ic->next,ic);
13463 genEndFunction (ic);
13479 pic16_genPlus (ic) ;
13483 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13484 pic16_genMinus (ic);
13500 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13504 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13510 /* note these two are xlated by algebraic equivalence
13511 * during parsing SDCC.y */
13512 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13513 "got '>=' or '<=' shouldn't have come here");
13517 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13529 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13533 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13537 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13561 genRightShift (ic);
13564 case GET_VALUE_AT_ADDRESS:
13569 if (POINTER_SET(ic))
13596 addSet(&_G.sendSet,ic);
13599 case DUMMY_READ_VOLATILE:
13609 /* now we are ready to call the
13610 peep hole optimizer */
13611 if (!options.nopeep)
13612 peepHole (&lineHead);
13614 /* now do the actual printing */
13615 printLine (lineHead, codeOutFile);
13618 DFPRINTF((stderr,"printing pBlock\n\n"));
13619 pic16_printpBlock(stdout,pb);