1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10 Bug Fixes - Raphael Neider <rneider AT web.de> (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
66 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
68 /* If you change these, you also have to update the library files
69 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
70 #define GPTR_TAG_DATA 0x80
71 #define GPTR_TAG_EEPROM 0x40
72 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
74 /* Wrapper to execute `code' at most once. */
75 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
77 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
79 void pic16_genMult8X8_8 (operand *, operand *,operand *);
80 void pic16_genMult16X16_16(operand *, operand *, operand *);
81 void pic16_genMult32X32_32(operand *, operand *, operand *);
82 pCode *pic16_AssembleLine(char *line, int peeps);
83 extern void pic16_printpBlock(FILE *of, pBlock *pb);
84 static asmop *newAsmop (short type);
85 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
86 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
87 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
88 static pCodeOp *pic16_popRegFromIdx(int rIdx);
90 //static int aopIdx (asmop *aop, int offset);
92 int pic16_labelOffset=0;
93 extern int pic16_debug_verbose;
94 #if !(USE_GENERIC_SIGNED_SHIFT)
95 static int optimized_for_speed = 0;
104 /* max_key keeps track of the largest label number used in
105 a function. This is then used to adjust the label offset
106 for the next function.
108 static int max_key=0;
109 static int GpsuedoStkPtr=0;
111 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
113 unsigned int pic16aopLiteral (value *val, int offset);
114 const char *pic16_AopType(short type);
115 static iCode *ifxForOp ( operand *op, iCode *ic );
117 void pic16_pushpCodeOp(pCodeOp *pcop);
118 void pic16_poppCodeOp(pCodeOp *pcop);
120 static bool is_LitOp(operand *op);
121 static bool is_LitAOp(asmop *aop);
124 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
126 /* set the following macro to 1 to enable passing the
127 * first byte of functions parameters via WREG */
128 #define USE_WREG_IN_FUNC_PARAMS 0
131 /* this is the down and dirty file with all kinds of
132 kludgy & hacky stuff. This is what it is all about
133 CODE GENERATION for a specific MCU . some of the
134 routines may be reusable, will have to see */
136 static char *zero = "#0x00";
137 static char *one = "#0x01";
138 //static char *spname = "sp";
142 * Function return value policy (MSB-->LSB):
144 * 16 bits -> PRODL:WREG
145 * 24 bits -> PRODH:PRODL:WREG
146 * 32 bits -> FSR0L:PRODH:PRODL:WREG
147 * >32 bits -> on stack, and FSR0 points to the beginning
152 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
153 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
154 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
155 static char **fReturn = fReturnpic16;
157 static char *accUse[] = {"WREG"};
159 //static short rbank = -1;
173 bitVect *fregsUsed; /* registers used in function */
175 set *sregsAllocSet; /* registers used to store stack variables */
176 int stack_lat; /* stack offset latency */
178 int useWreg; /* flag when WREG is used to pass function parameter */
181 extern int pic16_ptrRegReq ;
182 extern int pic16_nRegs;
183 extern FILE *codeOutFile;
184 //static void saverbank (int, iCode *,bool);
186 static lineNode *lineHead = NULL;
187 static lineNode *lineCurr = NULL;
189 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
190 0xE0, 0xC0, 0x80, 0x00};
191 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
192 0x07, 0x03, 0x01, 0x00};
196 /*-----------------------------------------------------------------*/
197 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
198 /* exponent of 2 is returned, otherwise -1 is */
200 /* note that this is similar to the function `powof2' in SDCCsymt */
204 /*-----------------------------------------------------------------*/
205 int pic16_my_powof2 (unsigned long num)
208 if( (num & (num-1)) == 0) {
221 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
223 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
225 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
226 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
227 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
228 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
229 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
230 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
231 ((result) ? AOP_SIZE(result) : 0));
234 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
237 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
239 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
240 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
241 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
242 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
243 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
244 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
248 void pic16_emitpcomment (char *fmt, ...)
251 char lb[INITIAL_INLINEASM];
252 unsigned char *lbp = (unsigned char *)lb;
257 vsprintf(lb+1,fmt,ap);
259 while (isspace(*lbp)) lbp++;
262 lineCurr = (lineCurr ?
263 connectLine(lineCurr,newLineNode(lb)) :
264 (lineHead = newLineNode(lb)));
265 lineCurr->isInline = _G.inLine;
266 lineCurr->isDebug = _G.debugLine;
268 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
271 // fprintf(stderr, "%s\n", lb);
274 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
277 char lb[INITIAL_INLINEASM];
278 unsigned char *lbp = (unsigned char *)lb;
280 if(!pic16_debug_verbose)
287 sprintf(lb,"%s\t",inst);
289 sprintf(lb,"%s",inst);
290 vsprintf(lb+(strlen(lb)),fmt,ap);
294 while (isspace(*lbp)) lbp++;
297 lineCurr = (lineCurr ?
298 connectLine(lineCurr,newLineNode(lb)) :
299 (lineHead = newLineNode(lb)));
300 lineCurr->isInline = _G.inLine;
301 lineCurr->isDebug = _G.debugLine;
303 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
306 // fprintf(stderr, "%s\n", lb);
311 void pic16_emitpLabel(int key)
313 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
316 void pic16_emitpLabelFORCE(int key)
318 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322 * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
327 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
329 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
335 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
337 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
343 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
349 #define pic16_emitcode DEBUGpic16_emitcode
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
357 char lb[INITIAL_INLINEASM];
358 unsigned char *lbp = lb;
364 sprintf(lb,"%s\t",inst);
366 sprintf(lb,"%s",inst);
367 vsprintf(lb+(strlen(lb)),fmt,ap);
371 while (isspace(*lbp)) lbp++;
374 lineCurr = (lineCurr ?
375 connectLine(lineCurr,newLineNode(lb)) :
376 (lineHead = newLineNode(lb)));
377 lineCurr->isInline = _G.inLine;
378 lineCurr->isDebug = _G.debugLine;
380 // VR fprintf(stderr, "lb = <%s>\n", lbp);
382 // if(pic16_debug_verbose)
383 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location */
392 /* with a debugger symbol */
393 /*-----------------------------------------------------------------*/
395 pic16_emitDebuggerSymbol (char * debugSym)
398 pic16_emitcode (";", "%s ==.", debugSym);
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
408 // bool r0iu = FALSE , r1iu = FALSE;
409 // bool r0ou = FALSE , r1ou = FALSE;
410 bool fsr0iu = FALSE, fsr0ou;
411 bool fsr2iu = FALSE, fsr2ou;
413 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
416 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
419 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
422 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
427 if(!fsr0iu && !fsr0ou) {
428 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429 (*aopp)->type = AOP_FSR0;
431 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
433 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
437 /* no usage of FSR2 */
438 if(!fsr2iu && !fsr2ou) {
439 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440 (*aopp)->type = AOP_FSR2;
442 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
446 /* now we know they both have usage */
447 /* if fsr0 not used in this instruction */
449 if (!_G.fsr0Pushed) {
450 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
455 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456 (*aopp)->type = AOP_FSR0;
458 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
460 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
464 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
469 /* the logic: if r0 & r1 used in the instruction
470 then we are in trouble otherwise */
472 /* first check if r0 & r1 are used by this
473 instruction, in which case we are in trouble */
474 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
480 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
483 /* if no usage of r0 then return it */
484 if (!r0iu && !r0ou) {
485 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486 (*aopp)->type = AOP_R0;
488 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491 /* if no usage of r1 then return it */
492 if (!r1iu && !r1ou) {
493 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494 (*aopp)->type = AOP_R1;
496 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
499 /* now we know they both have usage */
500 /* if r0 not used in this instruction */
502 /* push it if not already pushed */
504 //pic16_emitcode ("push","%s",
505 // pic16_regWithIdx(R0_IDX)->dname);
509 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510 (*aopp)->type = AOP_R0;
512 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
515 /* if r1 not used then */
518 /* push it if not already pushed */
520 //pic16_emitcode ("push","%s",
521 // pic16_regWithIdx(R1_IDX)->dname);
525 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526 (*aopp)->type = AOP_R1;
527 return pic16_regWithIdx(R1_IDX);
531 /* I said end of world but not quite end of world yet */
532 /* if this is a result then we can push it on the stack*/
534 (*aopp)->type = AOP_STK;
538 /* other wise this is true end of the world */
539 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540 "getFreePtr should never reach here");
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
552 aop = Safe_calloc(1,sizeof(asmop));
557 static void genSetDPTR(int n)
561 pic16_emitcode(";", "Select standard DPTR");
562 pic16_emitcode("mov", "dps, #0x00");
566 pic16_emitcode(";", "Select alternate DPTR");
567 pic16_emitcode("mov", "dps, #0x01");
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for */
573 /* generating code */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
579 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585 resIfx->condition = 1; /* assume that the ifx is true */
586 resIfx->generated = 0; /* indicate that the ifx has not been used */
589 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
592 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593 __FUNCTION__,__LINE__,resIfx->lbl->key);
598 resIfx->lbl = IC_TRUE(ifx);
600 resIfx->lbl = IC_FALSE(ifx);
601 resIfx->condition = 0;
606 DEBUGpic16_emitcode("; +++","ifx true is non-null");
608 DEBUGpic16_emitcode("; +++","ifx true is null");
610 DEBUGpic16_emitcode("; +++","ifx false is non-null");
612 DEBUGpic16_emitcode("; +++","ifx false is null");
616 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
626 return PTR_TYPE(SPEC_OCLS(etype));
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
636 symbol *sym=OP_SYMBOL(op);
638 memmap *space= SPEC_OCLS(sym->etype);
642 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
644 // sym = OP_SYMBOL(op);
646 /* if already has one */
648 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
653 /* if symbol was initially placed onStack then we must re-place it
654 * to direct memory, since pic16 does not have a specific stack */
656 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
664 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
666 sym->aop = aop = newAsmop (AOP_PAGED);
667 aop->aopu.aop_dir = sym->rname ;
668 aop->size = getSize(sym->type);
669 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670 pic16_allocDirReg( IC_LEFT(ic) );
678 /* assign depending on the storage class */
679 /* if it is on the stack or indirectly addressable */
680 /* space we need to assign either r0 or r1 to it */
681 if (sym->onStack) // || sym->iaccess)
686 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
689 /* acquire a temporary register -- it is saved in function */
691 sym->aop = aop = newAsmop(AOP_STA);
692 aop->aopu.stk.stk = sym->stack;
693 aop->size = getSize(sym->type);
696 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
701 for(i=0;i<aop->size;i++)
702 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
705 if(1 && ic->op == SEND) {
707 /* if SEND do the send here */
710 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
711 for(i=0;i<aop->size;i++) {
712 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
713 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
718 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
721 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
723 // we do not need to load the value if it is to be defined...
724 if (result) return aop;
727 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730 for(i=0;i<aop->size;i++) {
732 /* initialise for stack access via frame pointer */
733 // operands on stack are accessible via "{FRAME POINTER} + index" with index
734 // starting at 2 for arguments and growing from 0 downwards for
735 // local variables (index == 0 is not assigned so we add one here)
737 int soffs = sym->stack;
743 if(1 && ic->op == SEND) {
744 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
745 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
746 pic16_popCopyReg( pic16_frame_plusw ),
747 pic16_popCopyReg(pic16_stack_postdec )));
749 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
750 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
757 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
764 /* now assign the address of the variable to
765 the pointer register */
766 if (aop->type != AOP_STK) {
770 pic16_emitcode("push","acc");
772 pic16_emitcode("mov","a,_bp");
773 pic16_emitcode("add","a,#0x%02x",
775 ((char)(sym->stack - _G.nRegsSaved )) :
776 ((char)sym->stack)) & 0xff);
777 pic16_emitcode("mov","%s,a",
778 aop->aopu.aop_ptr->name);
781 pic16_emitcode("pop","acc");
783 pic16_emitcode("mov","%s,#%s",
784 aop->aopu.aop_ptr->name,
786 aop->paged = space->paged;
788 aop->aopu.aop_stk = sym->stack;
796 if (sym->onStack && options.stack10bit)
798 /* It's on the 10 bit stack, which is located in
802 //DEBUGpic16_emitcode(";","%d",__LINE__);
805 pic16_emitcode("push","acc");
807 pic16_emitcode("mov","a,_bp");
808 pic16_emitcode("add","a,#0x%02x",
810 ((char)(sym->stack - _G.nRegsSaved )) :
811 ((char)sym->stack)) & 0xff);
814 pic16_emitcode ("mov","dpx1,#0x40");
815 pic16_emitcode ("mov","dph1,#0x00");
816 pic16_emitcode ("mov","dpl1, a");
820 pic16_emitcode("pop","acc");
822 sym->aop = aop = newAsmop(AOP_DPTR2);
823 aop->size = getSize(sym->type);
829 /* special case for a function */
830 if (IS_FUNC(sym->type)) {
831 sym->aop = aop = newAsmop(AOP_PCODE);
832 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
833 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
834 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
835 PCOI(aop->aopu.pcop)->index = 0;
836 aop->size = FPTRSIZE;
837 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
844 //DEBUGpic16_emitcode(";","%d",__LINE__);
845 /* if in bit space */
846 if (IN_BITSPACE(space)) {
847 sym->aop = aop = newAsmop (AOP_CRY);
848 aop->aopu.aop_dir = sym->rname ;
849 aop->size = getSize(sym->type);
850 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853 /* if it is in direct space */
854 if (IN_DIRSPACE(space)) {
855 if(!strcmp(sym->rname, "_WREG")) {
856 sym->aop = aop = newAsmop (AOP_ACC);
857 aop->size = getSize(sym->type); /* should always be 1 */
858 assert(aop->size == 1);
859 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
862 sym->aop = aop = newAsmop (AOP_DIR);
863 aop->aopu.aop_dir = sym->rname ;
864 aop->size = getSize(sym->type);
865 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
866 pic16_allocDirReg( IC_LEFT(ic) );
871 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
872 sym->aop = aop = newAsmop (AOP_DIR);
873 aop->aopu.aop_dir = sym->rname ;
874 aop->size = getSize(sym->type);
875 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
876 pic16_allocDirReg( IC_LEFT(ic) );
881 /* only remaining is far space */
882 sym->aop = aop = newAsmop(AOP_PCODE);
884 /* change the next if to 1 to revert to good old immediate code */
885 if(IN_CODESPACE(space)) {
886 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
887 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
888 PCOI(aop->aopu.pcop)->index = 0;
890 /* try to allocate via direct register */
891 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
892 // aop->size = getSize( sym->type );
895 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
896 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
899 if(!pic16_allocDirReg (IC_LEFT(ic)))
903 if(IN_DIRSPACE( space ))
905 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
906 aop->size = FPTRSIZE;
907 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
908 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
909 else if(sym->onStack) {
912 if(SPEC_SCLS(sym->etype) == S_PDATA) {
913 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
914 aop->size = FPTRSIZE;
919 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
921 /* if it is in code space */
922 if (IN_CODESPACE(space))
928 /*-----------------------------------------------------------------*/
929 /* aopForRemat - rematerialzes an object */
930 /*-----------------------------------------------------------------*/
931 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
933 symbol *sym = OP_SYMBOL(op);
935 iCode *ic = NULL, *oldic;
936 asmop *aop = newAsmop(AOP_PCODE);
943 ic = sym->rematiCode;
945 if(IS_OP_POINTER(op)) {
946 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
949 // if(!result) /* fixme-vr */
953 // pic16_emitpcomment("ic: %s\n", printILine(ic));
956 val += (int) operandLitValue(IC_RIGHT(ic));
957 } else if (ic->op == '-') {
958 val -= (int) operandLitValue(IC_RIGHT(ic));
962 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
965 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
968 if(!op->isaddr)viaimmd++; else viaimmd=0;
970 /* set the following if to 1 to revert to good old immediate code */
971 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
974 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
976 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
979 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
981 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
984 PCOI(aop->aopu.pcop)->index = val;
986 aop->size = getSize( sym->type );
988 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
990 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
991 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
993 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
997 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
998 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1000 val, IS_PTR_CONST(operandType(op)));
1002 val, IS_CODEPTR(operandType(op)));
1005 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1007 pic16_allocDirReg (IC_LEFT(ic));
1009 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1016 static int aopIdx (asmop *aop, int offset)
1021 if(aop->type != AOP_REG)
1024 return aop->aopu.aop_reg[offset]->rIdx;
1029 /*-----------------------------------------------------------------*/
1030 /* regsInCommon - two operands have some registers in common */
1031 /*-----------------------------------------------------------------*/
1032 static bool regsInCommon (operand *op1, operand *op2)
1034 symbol *sym1, *sym2;
1037 /* if they have registers in common */
1038 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1041 sym1 = OP_SYMBOL(op1);
1042 sym2 = OP_SYMBOL(op2);
1044 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1047 for (i = 0 ; i < sym1->nRegs ; i++) {
1052 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1056 if (sym2->regs[j] == sym1->regs[i])
1064 /*-----------------------------------------------------------------*/
1065 /* operandsEqu - equivalent */
1066 /*-----------------------------------------------------------------*/
1067 static bool operandsEqu ( operand *op1, operand *op2)
1069 symbol *sym1, *sym2;
1071 /* if they not symbols */
1072 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1075 sym1 = OP_SYMBOL(op1);
1076 sym2 = OP_SYMBOL(op2);
1078 /* if both are itemps & one is spilt
1079 and the other is not then false */
1080 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1081 sym1->isspilt != sym2->isspilt )
1084 /* if they are the same */
1088 if (sym1->rname[0] && sym2->rname[0]
1089 && strcmp (sym1->rname, sym2->rname) == 0)
1093 /* if left is a tmp & right is not */
1094 if (IS_ITEMP(op1) &&
1097 (sym1->usl.spillLoc == sym2))
1100 if (IS_ITEMP(op2) &&
1104 (sym2->usl.spillLoc == sym1))
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_sameRegs - two asmops have the same registers */
1112 /*-----------------------------------------------------------------*/
1113 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1120 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1121 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1123 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1125 if (aop1->type != AOP_REG ||
1126 aop2->type != AOP_REG )
1129 /* This is a bit too restrictive if one is a subset of the other...
1130 if (aop1->size != aop2->size )
1134 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1135 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1137 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1138 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1145 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1147 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1148 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1150 if(aop1 == aop2)return TRUE;
1151 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1153 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1159 /*-----------------------------------------------------------------*/
1160 /* pic16_aopOp - allocates an asmop for an operand : */
1161 /*-----------------------------------------------------------------*/
1162 void pic16_aopOp (operand *op, iCode *ic, bool result)
1171 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1173 /* if this a literal */
1174 if (IS_OP_LITERAL(op)) {
1175 op->aop = aop = newAsmop(AOP_LIT);
1176 aop->aopu.aop_lit = op->operand.valOperand;
1177 aop->size = getSize(operandType(op));
1182 sym_link *type = operandType(op);
1184 if(IS_PTR_CONST(type))
1186 if(IS_CODEPTR(type))
1188 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1191 /* if already has a asmop then continue */
1195 /* if the underlying symbol has a aop */
1196 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1197 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1198 op->aop = OP_SYMBOL(op)->aop;
1202 /* if this is a true symbol */
1203 if (IS_TRUE_SYMOP(op)) {
1204 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1205 op->aop = aopForSym(ic, op, result);
1209 /* this is a temporary : this has
1215 e) can be a return use only */
1217 sym = OP_SYMBOL(op);
1219 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1220 /* if the type is a conditional */
1221 if (sym->regType == REG_CND) {
1222 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1227 /* if it is spilt then two situations
1229 b) has a spill location */
1230 if (sym->isspilt || sym->nRegs == 0) {
1232 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1233 DEBUGpic16_emitcode(";","%d",__LINE__);
1234 /* rematerialize it NOW */
1237 sym->aop = op->aop = aop = aopForRemat (op, result);
1238 // aop->size = getSize(sym->type);
1239 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1246 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1247 aop->size = getSize(sym->type);
1248 for ( i = 0 ; i < 1 ; i++ ) {
1249 aop->aopu.aop_str[i] = accUse[i];
1250 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1252 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1253 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1261 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1262 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1263 //pic16_allocDirReg (IC_LEFT(ic));
1264 aop->size = getSize(sym->type);
1269 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1270 aop->size = getSize(sym->type);
1271 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1272 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1274 DEBUGpic16_emitcode(";","%d",__LINE__);
1278 /* else spill location */
1279 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1280 /* force a new aop if sizes differ */
1281 sym->usl.spillLoc->aop = NULL;
1285 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1286 __FUNCTION__,__LINE__,
1287 sym->usl.spillLoc->rname,
1288 sym->rname, sym->usl.spillLoc->offset);
1291 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1294 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1296 sym->usl.spillLoc->offset, op);
1297 } else if (getSize(sym->type) <= 1) {
1298 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1299 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300 assert (getSize(sym->type) <= 1);
1301 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1304 /* We need some kind of dummy area for getSize(sym->type) byte,
1305 * use WREG for all storage locations.
1306 * XXX: This only works if we are implementing a `dummy read',
1307 * the stored value will not be retrievable...
1308 * See #1503234 for a case requiring this. */
1309 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1310 aop->size = getSize(sym->type);
1311 for ( i = 0 ; i < aop->size ;i++)
1312 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1314 aop->size = getSize(sym->type);
1320 sym_link *type = operandType(op);
1322 if(IS_PTR_CONST(type))
1324 if(IS_CODEPTR(type))
1326 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1329 /* must be in a register */
1330 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1331 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1332 aop->size = sym->nRegs;
1333 for ( i = 0 ; i < sym->nRegs ;i++)
1334 aop->aopu.aop_reg[i] = sym->regs[i];
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_freeAsmop - free up the asmop given to an operand */
1339 /*----------------------------------------------------------------*/
1340 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1357 /* depending on the asmop type only three cases need work AOP_RO
1358 , AOP_R1 && AOP_STK */
1360 switch (aop->type) {
1362 if (_G.fsr0Pushed ) {
1364 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1365 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1366 // pic16_emitcode ("pop","ar0");
1370 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1374 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1380 pic16_emitcode ("pop","ar0");
1384 bitVectUnSetBit(ic->rUsed,R0_IDX);
1390 pic16_emitcode ("pop","ar1");
1394 bitVectUnSetBit(ic->rUsed,R1_IDX);
1401 /* we must store the result on stack */
1402 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1403 // operands on stack are accessible via "FSR2 + index" with index
1404 // starting at 2 for arguments and growing from 0 downwards for
1405 // local variables (index == 0 is not assigned so we add one here)
1406 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1411 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1412 for(i=0;i<aop->size;i++) {
1413 /* initialise for stack access via frame pointer */
1414 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1415 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1416 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1419 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1423 for(i=0;i<aop->size;i++) {
1424 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1426 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1427 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1428 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1435 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1436 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1437 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1438 deleteSetItem( &_G.sregsAllocSet, sr );
1449 int stk = aop->aopu.aop_stk + aop->size;
1450 bitVectUnSetBit(ic->rUsed,R0_IDX);
1451 bitVectUnSetBit(ic->rUsed,R1_IDX);
1453 getFreePtr(ic,&aop,FALSE);
1455 if (options.stack10bit)
1457 /* I'm not sure what to do here yet... */
1460 "*** Warning: probably generating bad code for "
1461 "10 bit stack mode.\n");
1465 pic16_emitcode ("mov","a,_bp");
1466 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1467 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1469 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1473 pic16_emitcode("pop","acc");
1474 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1476 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1479 pic16_freeAsmop(op,NULL,ic,TRUE);
1481 pic16_emitcode("pop","ar0");
1486 pic16_emitcode("pop","ar1");
1496 /* all other cases just dealloc */
1500 OP_SYMBOL(op)->aop = NULL;
1501 /* if the symbol has a spill */
1503 SPIL_LOC(op)->aop = NULL;
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_aopGet - for fetching value of the aop */
1510 /*-----------------------------------------------------------------*/
1511 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1516 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1518 /* offset is greater than size then zero */
1519 if (offset > (aop->size - 1) &&
1520 aop->type != AOP_LIT)
1523 /* depending on type */
1524 switch (aop->type) {
1528 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1529 rs = Safe_calloc(1, strlen(s)+1);
1534 /* if we need to increment it */
1535 while (offset > aop->coff)
1537 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1541 while (offset < aop->coff)
1543 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1549 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1550 return (dname ? "acc" : "a");
1552 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1553 rs = Safe_calloc (1, strlen (s) + 1);
1561 sprintf (s,"%s",aop->aopu.aop_immd);
1564 sprintf(s,"(%s >> %d)",
1569 aop->aopu.aop_immd);
1570 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1571 rs = Safe_calloc(1,strlen(s)+1);
1577 sprintf(s,"(%s + %d)",
1580 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1582 sprintf(s,"%s",aop->aopu.aop_dir);
1583 rs = Safe_calloc(1,strlen(s)+1);
1588 return aop->aopu.aop_reg[offset]->name;
1591 return aop->aopu.aop_dir;
1594 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1595 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1597 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1598 rs = Safe_strdup("WREG");
1602 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1603 rs = Safe_calloc(1,strlen(s)+1);
1608 aop->coff = offset ;
1610 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1613 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1614 aop->type = AOP_ACC;
1615 return Safe_strdup("_WREG");
1617 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1619 return aop->aopu.aop_str[offset];
1623 pCodeOp *pcop = aop->aopu.pcop;
1624 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1626 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1627 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1629 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1631 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1634 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1637 rs = Safe_calloc(1,strlen(s)+1);
1643 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1645 sprintf(s,"(%s + %d)",
1649 sprintf(s,"%s",aop->aopu.aop_dir);
1650 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651 rs = Safe_calloc(1,strlen(s)+1);
1657 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1661 // pCodeOp *pcop = aop->aop
1666 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1667 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1668 "aopget got unsupported aop->type");
1674 /* lock has the following meaning: When allocating temporary registers
1675 * for stack variables storage, the value of the temporary register is
1676 * saved on stack. Its value is restored at the end. This procedure is
1677 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1678 * a possibility that before a call to pic16_aopOp, a temporary register
1679 * is allocated for a while and it is freed after some time, this will
1680 * mess the stack and values will not be restored properly. So use lock=1
1681 * to allocate temporary registers used internally by the programmer, and
1682 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1683 * to inform the compiler developer about a possible bug. This is an internal
1684 * feature for developing the compiler -- VR */
1686 int _TempReg_lock = 0;
1687 /*-----------------------------------------------------------------*/
1688 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1689 /*-----------------------------------------------------------------*/
1690 pCodeOp *pic16_popGetTempReg(int lock)
1695 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1697 // werror(W_POSSBUG2, __FILE__, __LINE__);
1700 _TempReg_lock += lock;
1710 /* this code might seem better but it does the *same* job with
1711 * the old code, it all depends on ralloc.c to get a free/unused
1715 while(i < pic16_nRegs) {
1716 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1717 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1718 if((!rr || (rr && rr->isFree))
1719 && !bitVectBitValue(cfunc->regsUsed, i)) {
1720 pcop = pic16_newpCodeOpReg( i );
1721 PCOR(pcop)->r->wasUsed = 1;
1722 PCOR(pcop)->r->isFree = 0;
1729 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1733 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1734 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1735 PCOR(pcop)->r->wasUsed=1;
1736 PCOR(pcop)->r->isFree=0;
1738 /* push value on stack */
1739 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1750 /* is not part of f, but don't save if */
1752 /*-----------------------------------------------------------------*/
1753 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1759 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1762 // werror(W_POSSBUG2, __FILE__, __LINE__);
1765 _TempReg_lock += lock;
1770 i = bitVectFirstBit(f);
1773 /* bypass registers that are used by function */
1774 if(!bitVectBitValue(f, i)) {
1776 /* bypass registers that are already allocated for stack access */
1777 if(!bitVectBitValue(v, i)) {
1779 // debugf("getting register rIdx = %d\n", i);
1780 /* ok, get the operand */
1781 pcop = pic16_newpCodeOpReg( i );
1783 /* should never by NULL */
1784 assert( pcop != NULL );
1788 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1791 PCOR(pcop)->r->wasUsed=1;
1792 PCOR(pcop)->r->isFree=0;
1798 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1800 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1801 /* already used in previous steps, break */
1808 /* caller takes care of the following */
1809 // bitVectSetBit(v, i);
1812 /* push value on stack */
1813 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1814 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1832 /*-----------------------------------------------------------------*/
1833 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1837 _TempReg_lock -= lock;
1839 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1840 PCOR(pcop)->r->isFree = 1;
1842 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1845 /*-----------------------------------------------------------------*/
1846 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1847 /*-----------------------------------------------------------------*/
1848 pCodeOp *pic16_popGetLabel(int key)
1851 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1856 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1859 /*-----------------------------------------------------------------*/
1860 /* pic16_popCopyReg - copy a pcode operator */
1861 /*-----------------------------------------------------------------*/
1862 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1866 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1867 memcpy (pcor, pc, sizeof (pCodeOpReg));
1868 pcor->r->wasUsed = 1;
1870 //pcor->pcop.type = pc->pcop.type;
1872 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1873 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1875 pcor->pcop.name = NULL;
1878 //pcor->rIdx = pc->rIdx;
1879 //pcor->r->wasUsed=1;
1880 //pcor->instance = pc->instance;
1882 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetLit - asm operator to pcode operator conversion */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetLit(int lit)
1892 return pic16_newpCodeOpLit(lit);
1895 /* Allow for 12 bit literals (LFSR x, <here!>). */
1896 pCodeOp *pic16_popGetLit12(int lit)
1898 return pic16_newpCodeOpLit12(lit);
1901 /*-----------------------------------------------------------------*/
1902 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1903 /*-----------------------------------------------------------------*/
1904 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1906 return pic16_newpCodeOpLit2(lit, arg2);
1910 /*-----------------------------------------------------------------*/
1911 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1912 /*-----------------------------------------------------------------*/
1913 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1915 return pic16_newpCodeOpImmd(name, offset,index, 0);
1919 /*-----------------------------------------------------------------*/
1920 /* pic16_popGet - asm operator to pcode operator conversion */
1921 /*-----------------------------------------------------------------*/
1922 pCodeOp *pic16_popGetWithString(char *str)
1928 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1932 pcop = pic16_newpCodeOp(str,PO_STR);
1937 /*-----------------------------------------------------------------*/
1938 /* pic16_popRegFromString - */
1939 /*-----------------------------------------------------------------*/
1940 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1943 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1944 pcop->type = PO_DIR;
1946 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1947 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1952 pcop->name = Safe_calloc(1,strlen(str)+1);
1953 strcpy(pcop->name,str);
1955 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1957 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1958 // PCOR(pcop)->r->wasUsed = 1;
1960 /* make sure that register doesn't exist,
1961 * and operand isn't NULL
1962 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1963 if((PCOR(pcop)->r == NULL)
1965 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1966 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1967 // __FUNCTION__, __LINE__, str, size, offset);
1969 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1970 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1973 PCOR(pcop)->instance = offset;
1978 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1982 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1983 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1985 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1986 PCOR(pcop)->rIdx = rIdx;
1987 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1989 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1991 PCOR(pcop)->r->isFree = 0;
1992 PCOR(pcop)->r->wasUsed = 1;
1994 pcop->type = PCOR(pcop)->r->pc_type;
1999 /*---------------------------------------------------------------------------------*/
2000 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2002 /*---------------------------------------------------------------------------------*/
2003 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2005 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2006 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2012 /*--------------------------------------------------------------------------------.-*/
2013 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2014 /* VR 030601 , adapted by Hans Dorn */
2015 /*--------------------------------------------------------------------------------.-*/
2016 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2019 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2023 /*---------------------------------------------------------------------------------*/
2024 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2025 /* movff instruction */
2026 /*---------------------------------------------------------------------------------*/
2027 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2029 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2030 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2036 /*-----------------------------------------------------------------*/
2037 /* pic16_popGet - asm operator to pcode operator conversion */
2038 /*-----------------------------------------------------------------*/
2039 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2041 // char *s = buffer ;
2047 /* offset is greater than size then zero */
2049 // if (offset > (aop->size - 1) &&
2050 // aop->type != AOP_LIT)
2051 // return NULL; //zero;
2053 /* depending on type */
2054 switch (aop->type) {
2059 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2060 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2066 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2067 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2068 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2069 PCOR(pcop)->r->wasUsed = 1;
2070 PCOR(pcop)->r->isFree = 0;
2072 PCOR(pcop)->instance = offset;
2073 pcop->type = PCOR(pcop)->r->pc_type;
2077 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2078 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2081 /* pCodeOp is already allocated from aopForSym */
2082 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2083 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2088 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2090 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2092 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2094 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2095 PCOR(pcop)->rIdx = rIdx;
2096 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2097 PCOR(pcop)->r->wasUsed=1;
2098 PCOR(pcop)->r->isFree=0;
2100 PCOR(pcop)->instance = offset;
2101 pcop->type = PCOR(pcop)->r->pc_type;
2102 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2106 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2107 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2113 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2114 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2118 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2119 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2126 // debugf2("aop = %p\toffset = %d\n", aop, offset);
2127 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
2128 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2130 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2132 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2133 // pcop->type = PO_GPR_REGISTER;
2134 PCOR(pcop)->rIdx = rIdx;
2135 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2136 PCOR(pcop)->r->wasUsed=1;
2137 PCOR(pcop)->r->isFree=0;
2139 PCOR(pcop)->instance = offset;
2140 pcop->type = PCOR(pcop)->r->pc_type;
2142 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2143 // rs = aop->aopu.aop_reg[offset]->name;
2144 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2149 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2151 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2152 PCOR(pcop)->instance = offset;
2153 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2154 //if(PCOR(pcop)->r == NULL)
2155 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2159 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2160 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2163 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2164 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2167 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2168 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2169 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2170 pcop->type = PCOR(pcop)->r->pc_type;
2171 pcop->name = PCOR(pcop)->r->name;
2177 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2179 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2180 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2181 switch( aop->aopu.pcop->type ) {
2182 case PO_DIR: PCOR(pcop)->instance += offset; break;
2183 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2188 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2189 assert( 0 ); /* should never reach here */;
2194 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2195 "pic16_popGet got unsupported aop->type");
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_aopPut - puts a string for a aop */
2200 /*-----------------------------------------------------------------*/
2201 void pic16_aopPut (asmop *aop, char *s, int offset)
2208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2210 if (aop->size && offset > ( aop->size - 1)) {
2211 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2212 "pic16_aopPut got offset > aop->size");
2216 /* will assign value to value */
2217 /* depending on where it is ofcourse */
2218 switch (aop->type) {
2221 sprintf(d,"(%s + %d)",
2222 aop->aopu.aop_dir,offset);
2223 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2226 sprintf(d,"%s",aop->aopu.aop_dir);
2229 DEBUGpic16_emitcode(";","%d",__LINE__);
2231 pic16_emitcode("movf","%s,w",s);
2232 pic16_emitcode("movwf","%s",d);
2235 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2236 if(offset >= aop->size) {
2237 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2240 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2243 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2250 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2251 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2254 strcmp(s,"r0") == 0 ||
2255 strcmp(s,"r1") == 0 ||
2256 strcmp(s,"r2") == 0 ||
2257 strcmp(s,"r3") == 0 ||
2258 strcmp(s,"r4") == 0 ||
2259 strcmp(s,"r5") == 0 ||
2260 strcmp(s,"r6") == 0 ||
2261 strcmp(s,"r7") == 0 )
2262 pic16_emitcode("mov","%s,%s ; %d",
2263 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2267 if(strcmp(s,"W")==0 )
2268 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2270 pic16_emitcode("movwf","%s",
2271 aop->aopu.aop_reg[offset]->name);
2273 if(strcmp(s,zero)==0) {
2274 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2276 } else if(strcmp(s,"W")==0) {
2277 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2278 pcop->type = PO_GPR_REGISTER;
2280 PCOR(pcop)->rIdx = -1;
2281 PCOR(pcop)->r = NULL;
2283 DEBUGpic16_emitcode(";","%d",__LINE__);
2284 pcop->name = Safe_strdup(s);
2285 pic16_emitpcode(POC_MOVFW,pcop);
2286 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2287 } else if(strcmp(s,one)==0) {
2288 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2289 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2291 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2299 if (aop->type == AOP_DPTR2)
2305 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2306 "pic16_aopPut writting to code space");
2310 while (offset > aop->coff) {
2312 pic16_emitcode ("inc","dptr");
2315 while (offset < aop->coff) {
2317 pic16_emitcode("lcall","__decdptr");
2322 /* if not in accumulater */
2325 pic16_emitcode ("movx","@dptr,a");
2327 if (aop->type == AOP_DPTR2)
2335 while (offset > aop->coff) {
2337 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2339 while (offset < aop->coff) {
2341 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2347 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2352 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2354 if (strcmp(s,"r0") == 0 ||
2355 strcmp(s,"r1") == 0 ||
2356 strcmp(s,"r2") == 0 ||
2357 strcmp(s,"r3") == 0 ||
2358 strcmp(s,"r4") == 0 ||
2359 strcmp(s,"r5") == 0 ||
2360 strcmp(s,"r6") == 0 ||
2361 strcmp(s,"r7") == 0 ) {
2363 sprintf(buffer,"a%s",s);
2364 pic16_emitcode("mov","@%s,%s",
2365 aop->aopu.aop_ptr->name,buffer);
2367 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2372 if (strcmp(s,"a") == 0)
2373 pic16_emitcode("push","acc");
2375 pic16_emitcode("push","%s",s);
2380 /* if bit variable */
2381 if (!aop->aopu.aop_dir) {
2382 pic16_emitcode("clr","a");
2383 pic16_emitcode("rlc","a");
2386 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2389 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2392 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2394 lbl = newiTempLabel(NULL);
2396 if (strcmp(s,"a")) {
2399 pic16_emitcode("clr","c");
2400 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2401 pic16_emitcode("cpl","c");
2402 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2403 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2410 if (strcmp(aop->aopu.aop_str[offset],s))
2411 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2416 if (!offset && (strcmp(s,"acc") == 0))
2419 if (strcmp(aop->aopu.aop_str[offset],s))
2420 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2424 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2425 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2426 // "pic16_aopPut got unsupported aop->type");
2432 /*-----------------------------------------------------------------*/
2433 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2434 /*-----------------------------------------------------------------*/
2435 void pic16_mov2w (asmop *aop, int offset)
2437 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2440 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2442 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2445 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2447 if(is_LitAOp(src)) {
2448 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2449 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2451 if(pic16_sameRegsOfs(src, dst, offset))return;
2452 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2453 pic16_popGet(dst, offset)));
2457 static void pic16_movLit2f(pCodeOp *pc, int lit)
2459 if (0 == (lit & 0x00ff))
2461 pic16_emitpcode (POC_CLRF, pc);
2462 } else if (0xff == (lit & 0x00ff))
2464 pic16_emitpcode (POC_SETF, pc);
2466 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2467 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2471 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2473 if(is_LitAOp(src)) {
2474 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2475 pic16_emitpcode(POC_MOVWF, dst);
2477 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2481 void pic16_testStackOverflow(void)
2483 #define GSTACK_TEST_NAME "_gstack_test"
2485 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2490 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2491 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2492 // strcpy(sym->rname, GSTACK_TEST_NAME);
2493 checkAddSym(&externs, sym);
2498 /* push pcop into stack */
2499 void pic16_pushpCodeOp(pCodeOp *pcop)
2501 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2503 if(pic16_options.gstack)
2504 pic16_testStackOverflow();
2508 /* pop pcop from stack */
2509 void pic16_poppCodeOp(pCodeOp *pcop)
2511 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2512 if(pic16_options.gstack)
2513 pic16_testStackOverflow();
2517 /*-----------------------------------------------------------------*/
2518 /* pushw - pushes wreg to stack */
2519 /*-----------------------------------------------------------------*/
2522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2523 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2524 if(pic16_options.gstack)
2525 pic16_testStackOverflow();
2529 /*-----------------------------------------------------------------*/
2530 /* pushaop - pushes aop to stack */
2531 /*-----------------------------------------------------------------*/
2532 void pushaop(asmop *aop, int offset)
2534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2536 if(_G.resDirect)return;
2538 if(is_LitAOp(aop)) {
2539 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2540 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2542 pic16_emitpcode(POC_MOVFF,
2543 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2546 if(pic16_options.gstack)
2547 pic16_testStackOverflow();
2550 /*-----------------------------------------------------------------*/
2551 /* popaop - pops aop from stack */
2552 /*-----------------------------------------------------------------*/
2553 void popaop(asmop *aop, int offset)
2555 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2556 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2557 if(pic16_options.gstack)
2558 pic16_testStackOverflow();
2561 void popaopidx(asmop *aop, int offset, int index)
2565 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2567 if(STACK_MODEL_LARGE)ofs++;
2569 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2570 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2571 if(pic16_options.gstack)
2572 pic16_testStackOverflow();
2575 #if !(USE_GENERIC_SIGNED_SHIFT)
2576 /*-----------------------------------------------------------------*/
2577 /* reAdjustPreg - points a register back to where it should */
2578 /*-----------------------------------------------------------------*/
2579 static void reAdjustPreg (asmop *aop)
2583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2585 if ((size = aop->size) <= 1)
2588 switch (aop->type) {
2592 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2596 if (aop->type == AOP_DPTR2)
2602 pic16_emitcode("lcall","__decdptr");
2605 if (aop->type == AOP_DPTR2)
2617 /*-----------------------------------------------------------------*/
2618 /* opIsGptr: returns non-zero if the passed operand is */
2619 /* a generic pointer type. */
2620 /*-----------------------------------------------------------------*/
2621 static int opIsGptr(operand *op)
2623 sym_link *type = operandType(op);
2625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2626 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2634 /*-----------------------------------------------------------------*/
2635 /* pic16_getDataSize - get the operand data size */
2636 /*-----------------------------------------------------------------*/
2637 int pic16_getDataSize(operand *op)
2639 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2642 return AOP_SIZE(op);
2644 // tsd- in the pic port, the genptr size is 1, so this code here
2645 // fails. ( in the 8051 port, the size was 4).
2648 size = AOP_SIZE(op);
2649 if (size == GPTRSIZE)
2651 sym_link *type = operandType(op);
2652 if (IS_GENPTR(type))
2654 /* generic pointer; arithmetic operations
2655 * should ignore the high byte (pointer type).
2658 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2665 /*-----------------------------------------------------------------*/
2666 /* pic16_outAcc - output Acc */
2667 /*-----------------------------------------------------------------*/
2668 void pic16_outAcc(operand *result)
2671 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2672 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2675 size = pic16_getDataSize(result);
2677 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2680 /* unsigned or positive */
2682 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2687 /*-----------------------------------------------------------------*/
2688 /* pic16_outBitC - output a bit C */
2689 /* Move to result the value of Carry flag -- VR */
2690 /*-----------------------------------------------------------------*/
2691 void pic16_outBitC(operand *result)
2695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2697 /* if the result is bit */
2698 if (AOP_TYPE(result) == AOP_CRY) {
2699 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2700 pic16_aopPut(AOP(result),"c",0);
2703 i = AOP_SIZE(result);
2705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2707 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2711 /*-----------------------------------------------------------------*/
2712 /* pic16_outBitOp - output a bit from Op */
2713 /* Move to result the value of set/clr op -- VR */
2714 /*-----------------------------------------------------------------*/
2715 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2721 /* if the result is bit */
2722 if (AOP_TYPE(result) == AOP_CRY) {
2723 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2724 pic16_aopPut(AOP(result),"c",0);
2727 i = AOP_SIZE(result);
2729 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2731 pic16_emitpcode(POC_RRCF, pcop);
2732 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2736 /*-----------------------------------------------------------------*/
2737 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2738 /*-----------------------------------------------------------------*/
2739 void pic16_toBoolean(operand *oper)
2741 int size = AOP_SIZE(oper) - 1;
2744 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2746 if ( AOP_TYPE(oper) != AOP_ACC) {
2747 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2750 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2754 /*-----------------------------------------------------------------*/
2755 /* genUminusFloat - unary minus for floating points */
2756 /*-----------------------------------------------------------------*/
2757 static void genUminusFloat(operand *op,operand *result)
2759 int size ,offset =0 ;
2762 /* for this we just need to flip the
2763 first it then copy the rest in place */
2764 size = AOP_SIZE(op);
2765 assert( size == AOP_SIZE(result) );
2768 pic16_mov2f(AOP(result), AOP(op), offset);
2772 /* toggle the MSB's highest bit */
2773 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2776 /*-----------------------------------------------------------------*/
2777 /* genUminus - unary minus code generation */
2778 /*-----------------------------------------------------------------*/
2779 static void genUminus (iCode *ic)
2782 sym_link *optype, *rtype;
2789 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2790 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2792 /* if both in bit space then special case */
2793 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2794 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2796 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2797 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2798 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2802 optype = operandType(IC_LEFT(ic));
2803 rtype = operandType(IC_RESULT(ic));
2806 /* if float then do float stuff */
2807 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2808 if(IS_FIXED(optype))
2809 debugf("implement fixed16x16 type\n", 0);
2811 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2815 /* otherwise subtract from zero by taking the 2's complement */
2816 size = AOP_SIZE(IC_LEFT(ic));
2817 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2818 label = newiTempLabel ( NULL );
2820 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2821 for (i=size-1; i > 0; i--) {
2822 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2824 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2825 for (i=1; i < size; i++) {
2826 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2827 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2830 for (i=size-1; i >= 0; i--) {
2831 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2832 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2835 for (i=0; i < size-2; i++) {
2836 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2837 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2839 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2841 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2844 pic16_emitpLabel (label->key);
2847 /* release the aops */
2848 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2849 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2853 /*-----------------------------------------------------------------*/
2854 /* saveRegisters - will look for a call and save the registers */
2855 /*-----------------------------------------------------------------*/
2856 static void saveRegisters(iCode *lic)
2863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2865 for (ic = lic ; ic ; ic = ic->next)
2866 if (ic->op == CALL || ic->op == PCALL)
2870 fprintf(stderr,"found parameter push with no function call\n");
2874 /* if the registers have been saved already then
2876 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2879 /* find the registers in use at this time
2880 and push them away to safety */
2881 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2885 if (options.useXstack) {
2886 if (bitVectBitValue(rsave,R0_IDX))
2887 pic16_emitcode("mov","b,r0");
2888 pic16_emitcode("mov","r0,%s",spname);
2889 for (i = 0 ; i < pic16_nRegs ; i++) {
2890 if (bitVectBitValue(rsave,i)) {
2892 pic16_emitcode("mov","a,b");
2894 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2895 pic16_emitcode("movx","@r0,a");
2896 pic16_emitcode("inc","r0");
2899 pic16_emitcode("mov","%s,r0",spname);
2900 if (bitVectBitValue(rsave,R0_IDX))
2901 pic16_emitcode("mov","r0,b");
2903 //for (i = 0 ; i < pic16_nRegs ; i++) {
2904 // if (bitVectBitValue(rsave,i))
2905 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2908 dtype = operandType(IC_LEFT(ic));
2909 if (currFunc && dtype &&
2910 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2911 IFFUNC_ISISR(currFunc->type) &&
2914 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2917 /*-----------------------------------------------------------------*/
2918 /* unsaveRegisters - pop the pushed registers */
2919 /*-----------------------------------------------------------------*/
2920 static void unsaveRegisters (iCode *ic)
2925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2926 /* find the registers in use at this time
2927 and push them away to safety */
2928 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2931 if (options.useXstack) {
2932 pic16_emitcode("mov","r0,%s",spname);
2933 for (i = pic16_nRegs ; i >= 0 ; i--) {
2934 if (bitVectBitValue(rsave,i)) {
2935 pic16_emitcode("dec","r0");
2936 pic16_emitcode("movx","a,@r0");
2938 pic16_emitcode("mov","b,a");
2940 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2944 pic16_emitcode("mov","%s,r0",spname);
2945 if (bitVectBitValue(rsave,R0_IDX))
2946 pic16_emitcode("mov","r0,b");
2948 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2949 // if (bitVectBitValue(rsave,i))
2950 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2957 /*-----------------------------------------------------------------*/
2959 /*-----------------------------------------------------------------*/
2960 static void pushSide(operand * oper, int size)
2963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2965 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2966 if (AOP_TYPE(oper) != AOP_REG &&
2967 AOP_TYPE(oper) != AOP_DIR &&
2969 pic16_emitcode("mov","a,%s",l);
2970 pic16_emitcode("push","acc");
2972 pic16_emitcode("push","%s",l);
2977 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2979 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2980 pic16_emitpcode(POC_MOVFW, src);
2981 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2983 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2984 src, pic16_popGet(AOP(op), offset)));
2989 /*-----------------------------------------------------------------*/
2990 /* assignResultValue - assign results to oper, rescall==1 is */
2991 /* called from genCall() or genPcall() */
2992 /*-----------------------------------------------------------------*/
2993 static void assignResultValue(operand * oper, int rescall)
2995 int size = AOP_SIZE(oper);
2999 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3000 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3003 /* assign result from a call/pcall function() */
3005 /* function results are stored in a special order,
3006 * see top of file with Function return policy, or manual */
3009 /* 8-bits, result in WREG */
3010 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3013 /* 16-bits, result in PRODL:WREG */
3014 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3018 /* 24-bits, result in PRODH:PRODL:WREG */
3019 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3023 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3024 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3028 /* >32-bits, result on stack, and FSR0 points to beginning.
3029 * Fix stack when done */
3031 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3033 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3034 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3036 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3041 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3042 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3043 if(STACK_MODEL_LARGE) {
3045 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3049 int areg = 0; /* matching argument register */
3051 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3052 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3055 /* its called from genReceive (probably) -- VR */
3056 /* I hope this code will not be called from somewhere else in the future!
3057 * We manually set the pseudo stack pointer in genReceive. - dw
3059 if(!GpsuedoStkPtr && _G.useWreg) {
3060 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3062 /* The last byte in the assignment is in W */
3063 if(areg <= GpsuedoStkPtr) {
3065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3067 // debugf("receive from WREG\n", 0);
3069 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3072 _G.stack_lat = AOP_SIZE(oper)-1;
3077 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3078 // debugf("receive from STACK\n", 0);
3085 /*-----------------------------------------------------------------*/
3086 /* genIpush - generate code for pushing this gets a little complex */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpush (iCode *ic)
3090 // int size, offset=0;
3093 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3096 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3098 /* send to stack as normal */
3099 addSet(&_G.sendSet,ic);
3100 // addSetHead(&_G.sendSet,ic);
3101 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3106 int size, offset = 0 ;
3110 /* if this is not a parm push : ie. it is spill push
3111 and spill push is always done on the local stack */
3112 if (!ic->parmPush) {
3114 /* and the item is spilt then do nothing */
3115 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3118 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3119 size = AOP_SIZE(IC_LEFT(ic));
3120 /* push it on the stack */
3122 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3127 pic16_emitcode("push","%s",l);
3132 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3136 /*-----------------------------------------------------------------*/
3137 /* genIpop - recover the registers: can happen only for spilling */
3138 /*-----------------------------------------------------------------*/
3139 static void genIpop (iCode *ic)
3142 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3147 /* if the temp was not pushed then */
3148 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3151 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3152 size = AOP_SIZE(IC_LEFT(ic));
3155 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3158 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3163 /*-----------------------------------------------------------------*/
3164 /* unsaverbank - restores the resgister bank from stack */
3165 /*-----------------------------------------------------------------*/
3166 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3168 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3176 if (options.useXstack) {
3178 r = getFreePtr(ic,&aop,FALSE);
3181 pic16_emitcode("mov","%s,_spx",r->name);
3182 pic16_emitcode("movx","a,@%s",r->name);
3183 pic16_emitcode("mov","psw,a");
3184 pic16_emitcode("dec","%s",r->name);
3187 pic16_emitcode ("pop","psw");
3190 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3191 if (options.useXstack) {
3192 pic16_emitcode("movx","a,@%s",r->name);
3193 //pic16_emitcode("mov","(%s+%d),a",
3194 // regspic16[i].base,8*bank+regspic16[i].offset);
3195 pic16_emitcode("dec","%s",r->name);
3198 pic16_emitcode("pop",""); //"(%s+%d)",
3199 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3202 if (options.useXstack) {
3204 pic16_emitcode("mov","_spx,%s",r->name);
3205 pic16_freeAsmop(NULL,aop,ic,TRUE);
3211 /*-----------------------------------------------------------------*/
3212 /* saverbank - saves an entire register bank on the stack */
3213 /*-----------------------------------------------------------------*/
3214 static void saverbank (int bank, iCode *ic, bool pushPsw)
3216 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3223 if (options.useXstack) {
3226 r = getFreePtr(ic,&aop,FALSE);
3227 pic16_emitcode("mov","%s,_spx",r->name);
3231 for (i = 0 ; i < pic16_nRegs ;i++) {
3232 if (options.useXstack) {
3233 pic16_emitcode("inc","%s",r->name);
3234 //pic16_emitcode("mov","a,(%s+%d)",
3235 // regspic16[i].base,8*bank+regspic16[i].offset);
3236 pic16_emitcode("movx","@%s,a",r->name);
3238 pic16_emitcode("push","");// "(%s+%d)",
3239 //regspic16[i].base,8*bank+regspic16[i].offset);
3243 if (options.useXstack) {
3244 pic16_emitcode("mov","a,psw");
3245 pic16_emitcode("movx","@%s,a",r->name);
3246 pic16_emitcode("inc","%s",r->name);
3247 pic16_emitcode("mov","_spx,%s",r->name);
3248 pic16_freeAsmop (NULL,aop,ic,TRUE);
3251 pic16_emitcode("push","psw");
3253 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3261 static int wparamCmp(void *p1, void *p2)
3263 return (!strcmp((char *)p1, (char *)p2));
3266 int inWparamList(char *s)
3268 return isinSetWith(wparamList, s, wparamCmp);
3272 /*-----------------------------------------------------------------*/
3273 /* genCall - generates a call statement */
3274 /*-----------------------------------------------------------------*/
3275 static void genCall (iCode *ic)
3285 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3286 /* if caller saves & we have not saved then */
3287 // if (!ic->regsSaved)
3288 // saveRegisters(ic);
3290 /* initialise stackParms for IPUSH pushes */
3291 // stackParms = psuedoStkPtr;
3292 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3293 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3294 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3297 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3300 /* if send set is not empty the assign */
3303 int psuedoStkPtr=-1;
3304 int firstTimeThruLoop = 1;
3307 /* reverse sendSet if function is not reentrant */
3308 if(!IFFUNC_ISREENT(ftype))
3309 _G.sendSet = reverseSet(_G.sendSet);
3311 /* First figure how many parameters are getting passed */
3315 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3319 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3320 size = AOP_SIZE(IC_LEFT(sic));
3324 /* pass the last byte through WREG */
3328 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3329 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3330 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3332 if(!firstTimeThruLoop) {
3333 /* If this is not the first time we've been through the loop
3334 * then we need to save the parameter in a temporary
3335 * register. The last byte of the last parameter is
3339 // --psuedoStkPtr; // sanity check
3343 firstTimeThruLoop=0;
3345 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3350 /* all arguments are passed via stack */
3354 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3355 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3356 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3358 // pushaop(AOP(IC_LEFT(sic)), size);
3359 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3366 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3370 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3371 pushw(); /* save last parameter to stack if functions has varargs */
3375 } else use_wreg = 0;
3377 _G.stackRegSet = _G.sendSet;
3382 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3386 /* if we need to assign a result value */
3387 if ((IS_ITEMP(IC_RESULT(ic))
3388 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3389 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3390 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3393 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3396 assignResultValue(IC_RESULT(ic), 1);
3398 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3399 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3401 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3404 if(!stackParms && ic->parmBytes) {
3405 stackParms = ic->parmBytes;
3408 stackParms -= use_wreg;
3411 if(stackParms == 1) {
3412 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3414 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3415 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3417 if(STACK_MODEL_LARGE) {
3419 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3424 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3427 /* adjust the stack for parameters if required */
3428 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3431 /* if register bank was saved then pop them */
3433 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3435 /* if we hade saved some registers then unsave them */
3436 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3437 unsaveRegisters (ic);
3443 /*-----------------------------------------------------------------*/
3444 /* genPcall - generates a call by pointer statement */
3445 /* new version, created from genCall - HJD */
3446 /*-----------------------------------------------------------------*/
3447 static void genPcall (iCode *ic)
3451 symbol *retlbl = newiTempLabel(NULL);
3452 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3456 fntype = operandType( IC_LEFT(ic) )->next;
3458 /* if send set is not empty the assign */
3461 int psuedoStkPtr=-1;
3463 /* reverse sendSet if function is not reentrant */
3464 if(!IFFUNC_ISREENT(fntype))
3465 _G.sendSet = reverseSet(_G.sendSet);
3469 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3472 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3473 size = AOP_SIZE(IC_LEFT(sic));
3476 /* all parameters are passed via stack, since WREG is clobbered
3477 * by the calling sequence */
3479 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3480 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3481 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3483 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3487 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3490 _G.stackRegSet = _G.sendSet;
3494 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3496 // push return address
3497 // push $ on return stack, then replace with retlbl
3499 /* Thanks to Thorsten Klose for pointing out that the following
3500 * snippet should be interrupt safe */
3501 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3502 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3504 pic16_emitpcodeNULLop(POC_PUSH);
3506 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3507 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3508 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3509 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3510 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3511 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3514 /* restore interrupt control register */
3515 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3516 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3518 /* make the call by writing the pointer into pc */
3519 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3520 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3522 // note: MOVFF to PCL not allowed
3523 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3524 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3527 /* return address is here: (X) */
3528 pic16_emitpLabelFORCE(retlbl->key);
3530 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3533 /* if we need assign a result value */
3534 if ((IS_ITEMP(IC_RESULT(ic))
3535 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3536 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3537 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3540 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3543 assignResultValue(IC_RESULT(ic), 1);
3545 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3546 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3548 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3551 // stackParms -= use_wreg;
3554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3555 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3556 if(STACK_MODEL_LARGE) {
3558 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3563 /*-----------------------------------------------------------------*/
3564 /* resultRemat - result is rematerializable */
3565 /*-----------------------------------------------------------------*/
3566 static int resultRemat (iCode *ic)
3568 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3569 if (SKIP_IC(ic) || ic->op == IFX)
3572 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3573 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3574 if (sym->remat && !POINTER_SET(ic))
3581 #if defined(__BORLANDC__) || defined(_MSC_VER)
3582 #define STRCASECMP stricmp
3584 #define STRCASECMP strcasecmp
3588 /*-----------------------------------------------------------------*/
3589 /* inExcludeList - return 1 if the string is in exclude Reg list */
3590 /*-----------------------------------------------------------------*/
3591 static bool inExcludeList(char *s)
3593 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3597 if (options.excludeRegs[i] &&
3598 STRCASECMP(options.excludeRegs[i],"none") == 0)
3601 for ( i = 0 ; options.excludeRegs[i]; i++) {
3602 if (options.excludeRegs[i] &&
3603 STRCASECMP(s,options.excludeRegs[i]) == 0)
3610 /*-----------------------------------------------------------------*/
3611 /* genFunction - generated code for function entry */
3612 /*-----------------------------------------------------------------*/
3613 static void genFunction (iCode *ic)
3619 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3621 pic16_labelOffset += (max_key+4);
3626 ftype = operandType(IC_LEFT(ic));
3627 sym = OP_SYMBOL(IC_LEFT(ic));
3629 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3630 /* create an absolute section at the interrupt vector:
3631 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3636 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3638 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3639 sprintf(asymname, "ivec_%s", sym->name);
3641 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3643 /* when an interrupt is declared as naked, do not emit the special
3644 * wrapper segment at vector address. The user should take care for
3645 * this instead. -- VR */
3647 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3648 asym = newSymbol(asymname, 0);
3649 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3650 pic16_addpBlock( apb );
3652 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3653 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3654 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3655 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3656 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3658 /* mark the end of this tiny function */
3659 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3661 sprintf(asymname, "%s", sym->rname);
3667 abSym = Safe_calloc(1, sizeof(absSym));
3668 strcpy(abSym->name, asymname);
3670 switch( FUNC_INTNO(sym->type) ) {
3671 case 0: abSym->address = 0x000000; break;
3672 case 1: abSym->address = 0x000008; break;
3673 case 2: abSym->address = 0x000018; break;
3676 // fprintf(stderr, "no interrupt number is given\n");
3677 abSym->address = -1; break;
3680 /* relocate interrupt vectors if needed */
3681 if(abSym->address != -1)
3682 abSym->address += pic16_options.ivt_loc;
3684 addSet(&absSymSet, abSym);
3688 /* create the function header */
3689 pic16_emitcode(";","-----------------------------------------");
3690 pic16_emitcode(";"," function %s",sym->name);
3691 pic16_emitcode(";","-----------------------------------------");
3693 pic16_emitcode("","%s:",sym->rname);
3694 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3699 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3700 if(!strcmp(ab->name, sym->rname)) {
3701 pic16_pBlockConvert2Absolute(pb);
3707 if(IFFUNC_ISNAKED(ftype)) {
3708 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3712 /* if critical function then turn interrupts off */
3713 if (IFFUNC_ISCRITICAL(ftype)) {
3714 //pic16_emitcode("clr","ea");
3717 currFunc = sym; /* update the currFunc symbol */
3718 _G.fregsUsed = sym->regsUsed;
3719 _G.sregsAlloc = newBitVect(128);
3722 /* if this is an interrupt service routine then
3723 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3724 if (IFFUNC_ISISR(sym->type)) {
3725 _G.usefastretfie = 1; /* use shadow registers by default */
3727 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3728 if(!FUNC_ISSHADOWREGS(sym->type)) {
3729 /* do not save WREG,STATUS,BSR for high priority interrupts
3730 * because they are stored in the hardware shadow registers already */
3731 _G.usefastretfie = 0;
3732 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3733 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3734 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3737 /* these should really be optimized somehow, because not all
3738 * interrupt handlers modify them */
3739 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3740 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3741 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3742 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3744 // pic16_pBlockConvert2ISR(pb);
3747 /* emit code to setup stack frame if user enabled,
3748 * and function is not main() */
3750 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3751 if(strcmp(sym->name, "main")) {
3753 || !options.ommitFramePtr
3755 || IFFUNC_ARGS(sym->type)
3756 || FUNC_HASSTACKPARM(sym->etype)
3758 /* setup the stack frame */
3759 if(STACK_MODEL_LARGE)
3760 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3761 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3763 if(STACK_MODEL_LARGE)
3764 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3765 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3769 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3772 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3774 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3775 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3777 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3780 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3781 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3788 /* if callee-save to be used for this function
3789 * then save the registers being used in this function */
3790 // if (IFFUNC_CALLEESAVES(sym->type))
3791 if(strcmp(sym->name, "main")) {
3794 /* if any registers used */
3795 if (sym->regsUsed) {
3796 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3799 /* save the registers used */
3800 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3801 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3802 if (bitVectBitValue(sym->regsUsed,i)) {
3804 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3806 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3809 if(!pic16_regWithIdx(i)->wasUsed) {
3810 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3811 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3812 pic16_regWithIdx(i)->wasUsed = 1;
3819 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3820 for(i=0;i<sym->regsUsed->size;i++) {
3821 if(bitVectBitValue(sym->regsUsed, i)) {
3826 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3829 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3834 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3835 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3838 /*-----------------------------------------------------------------*/
3839 /* genEndFunction - generates epilogue for functions */
3840 /*-----------------------------------------------------------------*/
3841 static void genEndFunction (iCode *ic)
3843 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3847 if(IFFUNC_ISNAKED(sym->type)) {
3848 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3854 /* add code for ISCRITICAL */
3855 if(IFFUNC_ISCRITICAL(sym->type)) {
3856 /* if critical function, turn on interrupts */
3858 /* TODO: add code here -- VR */
3861 // sym->regsUsed = _G.fregsUsed;
3863 /* now we need to restore the registers */
3864 /* if any registers used */
3866 /* first restore registers that might be used for stack access */
3867 if(_G.sregsAllocSet) {
3870 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3871 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3872 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3876 if (strcmp(sym->name, "main") && sym->regsUsed) {
3879 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3880 /* restore registers used */
3881 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3882 for ( i = sym->regsUsed->size; i >= 0; i--) {
3883 if (bitVectBitValue(sym->regsUsed,i)) {
3884 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3888 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3893 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3895 if (sym->stack == 1) {
3896 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3897 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3899 // we have to add more than one...
3900 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3901 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3902 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3904 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3905 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3906 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3910 if(strcmp(sym->name, "main")) {
3912 || !options.ommitFramePtr
3914 || IFFUNC_ARGS(sym->type)
3915 || FUNC_HASSTACKPARM(sym->etype)
3917 /* restore stack frame */
3918 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3919 if(STACK_MODEL_LARGE)
3920 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3926 if (IFFUNC_ISISR(sym->type)) {
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3928 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3929 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3930 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3932 if(!FUNC_ISSHADOWREGS(sym->type)) {
3933 /* do not restore interrupt vector for WREG,STATUS,BSR
3934 * for high priority interrupt, see genFunction */
3935 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3936 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3937 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3939 // _G.interruptvector = 0; /* sanity check */
3942 /* if debug then send end of function */
3943 /* if (options.debug && currFunc) */
3945 debugFile->writeEndFunction (currFunc, ic, 1);
3948 if(_G.usefastretfie)
3949 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3951 pic16_emitpcodeNULLop(POC_RETFIE);
3953 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3955 _G.usefastretfie = 0;
3959 if (IFFUNC_ISCRITICAL(sym->type)) {
3960 pic16_emitcode("setb","ea");
3963 /* if debug then send end of function */
3965 debugFile->writeEndFunction (currFunc, ic, 1);
3968 /* insert code to restore stack frame, if user enabled it
3969 * and function is not main() */
3972 pic16_emitpcodeNULLop(POC_RETURN);
3974 /* Mark the end of a function */
3975 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3979 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3981 unsigned long lit=1;
3986 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3987 if(AOP_TYPE(op) == AOP_LIT) {
3988 if(!IS_FLOAT(operandType( op ))) {
3989 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3992 unsigned long lit_int;
3996 /* take care if literal is a float */
3997 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4002 if (AOP_TYPE(op) == AOP_LIT) {
4003 /* FIXME: broken for
4004 * char __at(0x456) foo;
4006 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4007 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4008 } else if (AOP_TYPE(op) == AOP_PCODE
4009 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4010 /* char *s= "aaa"; return s; */
4011 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4012 * that the generic pointer is interpreted correctly
4013 * as referring to __code space, but this is fragile! */
4014 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4015 /* XXX: should check that dest != WREG */
4016 pic16_emitpcode(POC_MOVWF, dest);
4018 if(dest->type == PO_WREG && (offset == 0)) {
4019 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4026 /*-----------------------------------------------------------------*/
4027 /* genRet - generate code for return statement */
4028 /*-----------------------------------------------------------------*/
4029 static void genRet (iCode *ic)
4035 /* if we have no return value then
4036 * just generate the "ret" */
4041 /* we have something to return then
4042 * move the return value into place */
4043 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4044 size = AOP_SIZE(IC_LEFT(ic));
4048 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4051 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4054 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4056 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4059 /* >32-bits, setup stack and FSR0 */
4061 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4062 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4064 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4066 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4071 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4074 if(STACK_MODEL_LARGE) {
4075 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4076 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4078 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4083 /* old code, left here for reference -- VR */
4087 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4089 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4090 pic16_emitpcomment("push %s",l);
4093 DEBUGpic16_emitcode(";", "%d", __LINE__);
4094 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4095 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4097 if (strcmp(fReturn[offset],l)) {
4098 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4099 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4100 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4102 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4106 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4116 if (strcmp(fReturn[pushed],"a"))
4117 pic16_emitcode("pop",fReturn[pushed]);
4119 pic16_emitcode("pop","acc");
4125 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4128 /* generate a jump to the return label
4129 * if the next is not the return statement */
4130 if (!(ic->next && ic->next->op == LABEL
4131 && IC_LABEL(ic->next) == returnLabel)) {
4133 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4134 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4138 /*-----------------------------------------------------------------*/
4139 /* genLabel - generates a label */
4140 /*-----------------------------------------------------------------*/
4141 static void genLabel (iCode *ic)
4145 /* special case never generate */
4146 if (IC_LABEL(ic) == entryLabel)
4149 pic16_emitpLabel(IC_LABEL(ic)->key);
4150 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a goto */
4155 /*-----------------------------------------------------------------*/
4157 static void genGoto (iCode *ic)
4160 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4161 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4165 /*-----------------------------------------------------------------*/
4166 /* genMultbits :- multiplication of bits */
4167 /*-----------------------------------------------------------------*/
4168 static void genMultbits (operand *left,
4174 if(!pic16_sameRegs(AOP(result),AOP(right)))
4175 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4177 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4178 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4179 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneByte : 8 bit multiplication & division */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneByte (operand *left,
4193 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4194 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4196 /* (if two literals, the value is computed before) */
4197 /* if one literal, literal on the right */
4198 if (AOP_TYPE(left) == AOP_LIT){
4204 /* size is already checked in genMult == 1 */
4205 // size = AOP_SIZE(result);
4207 if (AOP_TYPE(right) == AOP_LIT){
4208 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4209 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4211 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4214 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4215 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4216 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4219 pic16_genMult8X8_8 (left, right,result);
4222 /*-----------------------------------------------------------------*/
4223 /* genMultOneWord : 16 bit multiplication */
4224 /*-----------------------------------------------------------------*/
4225 static void genMultOneWord (operand *left,
4230 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4231 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4233 /* (if two literals, the value is computed before)
4234 * if one literal, literal on the right */
4235 if (AOP_TYPE(left) == AOP_LIT){
4241 /* size is checked already == 2 */
4242 // size = AOP_SIZE(result);
4244 if (AOP_TYPE(right) == AOP_LIT) {
4245 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4246 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4247 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4248 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4250 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4251 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4252 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4253 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4256 pic16_genMult16X16_16(left, right,result);
4259 /*-----------------------------------------------------------------*/
4260 /* genMultOneLong : 32 bit multiplication */
4261 /*-----------------------------------------------------------------*/
4262 static void genMultOneLong (operand *left,
4267 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4268 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4270 /* (if two literals, the value is computed before)
4271 * if one literal, literal on the right */
4272 if (AOP_TYPE(left) == AOP_LIT){
4278 /* size is checked already == 4 */
4279 // size = AOP_SIZE(result);
4281 if (AOP_TYPE(right) == AOP_LIT) {
4282 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4283 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4284 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4285 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4287 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4288 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4289 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4290 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4293 pic16_genMult32X32_32(left, right,result);
4298 /*-----------------------------------------------------------------*/
4299 /* genMult - generates code for multiplication */
4300 /*-----------------------------------------------------------------*/
4301 static void genMult (iCode *ic)
4303 operand *left = IC_LEFT(ic);
4304 operand *right = IC_RIGHT(ic);
4305 operand *result= IC_RESULT(ic);
4308 /* assign the amsops */
4309 pic16_aopOp (left,ic,FALSE);
4310 pic16_aopOp (right,ic,FALSE);
4311 pic16_aopOp (result,ic,TRUE);
4313 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4315 /* special cases first *
4317 if (AOP_TYPE(left) == AOP_CRY
4318 && AOP_TYPE(right)== AOP_CRY) {
4319 genMultbits(left,right,result);
4323 /* if both are of size == 1 */
4324 if(AOP_SIZE(left) == 1
4325 && AOP_SIZE(right) == 1) {
4326 genMultOneByte(left,right,result);
4330 /* if both are of size == 2 */
4331 if(AOP_SIZE(left) == 2
4332 && AOP_SIZE(right) == 2) {
4333 genMultOneWord(left, right, result);
4337 /* if both are of size == 4 */
4338 if(AOP_SIZE(left) == 4
4339 && AOP_SIZE(right) == 4) {
4340 genMultOneLong(left, right, result);
4344 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4347 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4348 /* should have been converted to function call */
4352 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354 pic16_freeAsmop(result,NULL,ic,TRUE);
4357 /*-----------------------------------------------------------------*/
4358 /* genDivbits :- division of bits */
4359 /*-----------------------------------------------------------------*/
4360 static void genDivbits (operand *left,
4367 /* the result must be bit */
4368 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4369 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4373 pic16_emitcode("div","ab");
4374 pic16_emitcode("rrc","a");
4375 pic16_aopPut(AOP(result),"c",0);
4378 /*-----------------------------------------------------------------*/
4379 /* genDivOneByte : 8 bit division */
4380 /*-----------------------------------------------------------------*/
4381 static void genDivOneByte (operand *left,
4385 sym_link *opetype = operandType(result);
4390 /* result = divident / divisor
4391 * - divident may be a register or a literal,
4392 * - divisor may be a register or a literal,
4393 * so there are 3 cases (literal / literal is optimized
4394 * by the front-end) to handle.
4395 * In addition we must handle signed and unsigned, which
4396 * result in 6 final different cases -- VR */
4400 size = AOP_SIZE(result) - 1;
4402 /* signed or unsigned */
4403 if (SPEC_USIGN(opetype)) {
4404 pCodeOp *pct1, /* count */
4407 symbol *label1, *label2, *label3;;
4410 /* unsigned is easy */
4412 pct1 = pic16_popGetTempReg(1);
4413 pct2 = pic16_popGetTempReg(1);
4414 pct3 = pic16_popGetTempReg(1);
4416 label1 = newiTempLabel(NULL);
4417 label2 = newiTempLabel(NULL);
4418 label3 = newiTempLabel(NULL);
4420 /* the following algorithm is extracted from divuint.c */
4422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4423 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4425 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4427 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4429 pic16_emitpLabel(label1->key);
4432 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4436 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4440 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4442 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4443 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4445 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4446 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4447 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4449 pic16_emitpLabel( label3->key );
4450 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4451 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4455 pic16_emitpLabel(label2->key);
4456 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4457 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4458 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4460 /* result is in wreg */
4461 if(AOP_TYPE(result) != AOP_ACC)
4462 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4464 pic16_popReleaseTempReg( pct3, 1);
4465 pic16_popReleaseTempReg( pct2, 1);
4466 pic16_popReleaseTempReg( pct1, 1);
4471 /* signed is a little bit more difficult */
4473 /* save the signs of the operands */
4474 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4476 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4477 pic16_emitcode("push","acc"); /* save it on the stack */
4479 /* now sign adjust for both left & right */
4480 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4482 lbl = newiTempLabel(NULL);
4483 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4484 pic16_emitcode("cpl","a");
4485 pic16_emitcode("inc","a");
4486 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4487 pic16_emitcode("mov","b,a");
4489 /* sign adjust left side */
4490 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4493 lbl = newiTempLabel(NULL);
4494 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4495 pic16_emitcode("cpl","a");
4496 pic16_emitcode("inc","a");
4497 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4499 /* now the division */
4500 pic16_emitcode("div","ab");
4501 /* we are interested in the lower order
4503 pic16_emitcode("mov","b,a");
4504 lbl = newiTempLabel(NULL);
4505 pic16_emitcode("pop","acc");
4506 /* if there was an over flow we don't
4507 adjust the sign of the result */
4508 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4509 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4511 pic16_emitcode("clr","a");
4512 pic16_emitcode("subb","a,b");
4513 pic16_emitcode("mov","b,a");
4514 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4516 /* now we are done */
4517 pic16_aopPut(AOP(result),"b",0);
4519 pic16_emitcode("mov","c,b.7");
4520 pic16_emitcode("subb","a,acc");
4523 pic16_aopPut(AOP(result),"a",offset++);
4527 /*-----------------------------------------------------------------*/
4528 /* genDiv - generates code for division */
4529 /*-----------------------------------------------------------------*/
4530 static void genDiv (iCode *ic)
4532 operand *left = IC_LEFT(ic);
4533 operand *right = IC_RIGHT(ic);
4534 operand *result= IC_RESULT(ic);
4537 /* Division is a very lengthy algorithm, so it is better
4538 * to call support routines than inlining algorithm.
4539 * Division functions written here just in case someone
4540 * wants to inline and not use the support libraries -- VR */
4544 /* assign the amsops */
4545 pic16_aopOp (left,ic,FALSE);
4546 pic16_aopOp (right,ic,FALSE);
4547 pic16_aopOp (result,ic,TRUE);
4549 /* special cases first */
4551 if (AOP_TYPE(left) == AOP_CRY &&
4552 AOP_TYPE(right)== AOP_CRY) {
4553 genDivbits(left,right,result);
4557 /* if both are of size == 1 */
4558 if (AOP_SIZE(left) == 1 &&
4559 AOP_SIZE(right) == 1 ) {
4560 genDivOneByte(left,right,result);
4564 /* should have been converted to function call */
4567 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4568 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569 pic16_freeAsmop(result,NULL,ic,TRUE);
4572 /*-----------------------------------------------------------------*/
4573 /* genModbits :- modulus of bits */
4574 /*-----------------------------------------------------------------*/
4575 static void genModbits (operand *left,
4583 werror(W_POSSBUG2, __FILE__, __LINE__);
4584 /* the result must be bit */
4585 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4586 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4590 pic16_emitcode("div","ab");
4591 pic16_emitcode("mov","a,b");
4592 pic16_emitcode("rrc","a");
4593 pic16_aopPut(AOP(result),"c",0);
4596 /*-----------------------------------------------------------------*/
4597 /* genModOneByte : 8 bit modulus */
4598 /*-----------------------------------------------------------------*/
4599 static void genModOneByte (operand *left,
4603 sym_link *opetype = operandType(result);
4608 werror(W_POSSBUG2, __FILE__, __LINE__);
4610 /* signed or unsigned */
4611 if (SPEC_USIGN(opetype)) {
4612 /* unsigned is easy */
4613 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4614 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4616 pic16_emitcode("div","ab");
4617 pic16_aopPut(AOP(result),"b",0);
4621 /* signed is a little bit more difficult */
4623 /* save the signs of the operands */
4624 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4627 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4628 pic16_emitcode("push","acc"); /* save it on the stack */
4630 /* now sign adjust for both left & right */
4631 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4634 lbl = newiTempLabel(NULL);
4635 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4636 pic16_emitcode("cpl","a");
4637 pic16_emitcode("inc","a");
4638 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4639 pic16_emitcode("mov","b,a");
4641 /* sign adjust left side */
4642 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4645 lbl = newiTempLabel(NULL);
4646 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4647 pic16_emitcode("cpl","a");
4648 pic16_emitcode("inc","a");
4649 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4651 /* now the multiplication */
4652 pic16_emitcode("div","ab");
4653 /* we are interested in the lower order
4655 lbl = newiTempLabel(NULL);
4656 pic16_emitcode("pop","acc");
4657 /* if there was an over flow we don't
4658 adjust the sign of the result */
4659 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4660 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4662 pic16_emitcode("clr","a");
4663 pic16_emitcode("subb","a,b");
4664 pic16_emitcode("mov","b,a");
4665 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4667 /* now we are done */
4668 pic16_aopPut(AOP(result),"b",0);
4672 /*-----------------------------------------------------------------*/
4673 /* genMod - generates code for division */
4674 /*-----------------------------------------------------------------*/
4675 static void genMod (iCode *ic)
4677 operand *left = IC_LEFT(ic);
4678 operand *right = IC_RIGHT(ic);
4679 operand *result= IC_RESULT(ic);
4683 /* assign the amsops */
4684 pic16_aopOp (left,ic,FALSE);
4685 pic16_aopOp (right,ic,FALSE);
4686 pic16_aopOp (result,ic,TRUE);
4688 /* special cases first */
4690 if (AOP_TYPE(left) == AOP_CRY &&
4691 AOP_TYPE(right)== AOP_CRY) {
4692 genModbits(left,right,result);
4696 /* if both are of size == 1 */
4697 if (AOP_SIZE(left) == 1 &&
4698 AOP_SIZE(right) == 1 ) {
4699 genModOneByte(left,right,result);
4703 /* should have been converted to function call */
4707 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4708 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709 pic16_freeAsmop(result,NULL,ic,TRUE);
4712 /*-----------------------------------------------------------------*/
4713 /* genIfxJump :- will create a jump depending on the ifx */
4714 /*-----------------------------------------------------------------*/
4716 note: May need to add parameter to indicate when a variable is in bit space.
4718 static void genIfxJump (iCode *ic, char *jval)
4722 /* if true label then we jump if condition
4724 if ( IC_TRUE(ic) ) {
4726 if(strcmp(jval,"a") == 0)
4728 else if (strcmp(jval,"c") == 0)
4731 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4732 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4736 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4740 /* false label is present */
4741 if(strcmp(jval,"a") == 0)
4743 else if (strcmp(jval,"c") == 0)
4746 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4747 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4751 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4756 /* mark the icode as generated */
4760 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4764 /* if true label then we jump if condition
4766 if ( IC_TRUE(ic) ) {
4767 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4768 pic16_emitpcode(POC_BTFSC, jop);
4770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4771 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4774 /* false label is present */
4775 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4776 pic16_emitpcode(POC_BTFSS, jop);
4778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4779 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4783 /* mark the icode as generated */
4790 /*-----------------------------------------------------------------*/
4792 /*-----------------------------------------------------------------*/
4793 static void genSkip(iCode *ifx,int status_bit)
4795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4799 if ( IC_TRUE(ifx) ) {
4800 switch(status_bit) {
4815 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4816 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4820 switch(status_bit) {
4834 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4835 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4842 /*-----------------------------------------------------------------*/
4844 /*-----------------------------------------------------------------*/
4845 static void genSkipc(resolvedIfx *rifx)
4847 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4857 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4858 rifx->generated = 1;
4861 #if !(USE_SIMPLE_GENCMP)
4862 /*-----------------------------------------------------------------*/
4864 /*-----------------------------------------------------------------*/
4865 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4867 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4872 if( (rifx->condition ^ invert_condition) & 1)
4877 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4878 rifx->generated = 1;
4883 /*-----------------------------------------------------------------*/
4885 /*-----------------------------------------------------------------*/
4886 static void genSkipz(iCode *ifx, int condition)
4897 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4902 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4904 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4909 #if !(USE_SIMPLE_GENCMP)
4910 /*-----------------------------------------------------------------*/
4912 /*-----------------------------------------------------------------*/
4913 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4919 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4921 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4925 rifx->generated = 1;
4930 /*-----------------------------------------------------------------*/
4931 /* genChkZeroes :- greater or less than comparison */
4932 /* For each byte in a literal that is zero, inclusive or the */
4933 /* the corresponding byte in the operand with W */
4934 /* returns true if any of the bytes are zero */
4935 /*-----------------------------------------------------------------*/
4936 static int genChkZeroes(operand *op, int lit, int size)
4943 i = (lit >> (size*8)) & 0xff;
4947 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4949 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4959 /*-----------------------------------------------------------------*/
4960 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4961 /* aop (if it's NOT a literal) or from lit (if */
4962 /* aop is a literal) */
4963 /*-----------------------------------------------------------------*/
4964 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4965 if (aop->type == AOP_LIT) {
4966 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4968 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4972 /*-----------------------------------------------------------------*/
4973 /* genCmp :- greater or less than comparison */
4974 /*-----------------------------------------------------------------*/
4976 #if USE_SIMPLE_GENCMP /* { */
4978 /* genCmp performs a left < right comparison, stores
4979 * the outcome in result (if != NULL) and generates
4980 * control flow code for the ifx (if != NULL).
4982 * This version leaves in sequences like
4983 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4984 * which should be optmized by the peephole
4985 * optimizer - RN 2005-01-01 */
4986 static void genCmp (operand *left,operand *right,
4987 operand *result, iCode *ifx, int sign)
5000 assert (left && right);
5001 assert (AOP_SIZE(left) == AOP_SIZE(right));
5003 size = AOP_SIZE(right) - 1;
5004 mask = (0x100UL << (size*8)) - 1;
5005 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5010 resolveIfx (&rIfx, ifx);
5012 /* handle for special cases */
5013 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5016 /**********************************************************************
5017 * handle bits - bit compares are promoted to int compares seemingly! *
5018 **********************************************************************/
5020 // THIS IS COMPLETELY UNTESTED!
5021 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5022 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5023 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5024 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5027 // 1 < {0,1} is false --> clear C by skipping the next instruction
5028 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5029 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5030 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5031 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5032 emitCLRC; // only skipped for left=0 && right=1
5034 goto correct_result_in_carry;
5038 /*************************************************
5039 * make sure that left is register (or the like) *
5040 *************************************************/
5041 if (!isAOP_REGlike(left)) {
5042 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5043 assert (isAOP_LIT(left));
5044 assert (isAOP_REGlike(right));
5045 // swap left and right
5046 // left < right <==> right > left <==> (right >= left + 1)
5047 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5049 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5050 // MAXVALUE < right? always false
5051 if (performedLt) emitCLRC; else emitSETC;
5052 goto correct_result_in_carry;
5055 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5056 // that's why we handled it above.
5063 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5064 } else if (isAOP_LIT(right)) {
5065 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5068 assert (isAOP_REGlike(left)); // left must be register or the like
5069 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5071 /*************************************************
5072 * special cases go here *
5073 *************************************************/
5075 if (isAOP_LIT(right)) {
5077 // unsigned comparison to a literal
5078 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5080 // unsigned left < 0? always false
5081 if (performedLt) emitCLRC; else emitSETC;
5082 goto correct_result_in_carry;
5085 // signed comparison to a literal
5086 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5087 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5088 // signed left < 0x80000000? always false
5089 if (performedLt) emitCLRC; else emitSETC;
5090 goto correct_result_in_carry;
5091 } else if (lit == 0) {
5092 // compare left < 0; set CARRY if SIGNBIT(left) is set
5093 if (performedLt) emitSETC; else emitCLRC;
5094 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5095 if (performedLt) emitCLRC; else emitSETC;
5096 goto correct_result_in_carry;
5099 } // right is literal
5101 /*************************************************
5102 * perform a general case comparison *
5103 * make sure we get CARRY==1 <==> left >= right *
5104 *************************************************/
5105 // compare most significant bytes
5106 //DEBUGpc ("comparing bytes at offset %d", size);
5108 // unsigned comparison
5109 mov2w_regOrLit (AOP(right), lit, size);
5110 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5112 // signed comparison
5113 // (add 2^n to both operands then perform an unsigned comparison)
5114 if (isAOP_LIT(right)) {
5115 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5116 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5118 if (litbyte == 0x80) {
5119 // left >= 0x80 -- always true, but more bytes to come
5120 pic16_mov2w (AOP(left), size);
5121 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5124 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5125 pic16_mov2w (AOP(left), size);
5126 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5130 /* using PRODL as a temporary register here */
5131 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133 pic16_mov2w (AOP(left), size);
5134 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135 pic16_emitpcode (POC_MOVWF, pctemp);
5136 pic16_mov2w (AOP(right), size);
5137 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138 pic16_emitpcode (POC_SUBFW, pctemp);
5139 //pic16_popReleaseTempReg(pctemp, 1);
5143 // compare remaining bytes (treat as unsigned case from above)
5144 templbl = newiTempLabel ( NULL );
5147 //DEBUGpc ("comparing bytes at offset %d", offs);
5148 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149 mov2w_regOrLit (AOP(right), lit, offs);
5150 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5152 pic16_emitpLabel (templbl->key);
5153 goto result_in_carry;
5157 /****************************************************
5158 * now CARRY contains the result of the comparison: *
5159 * SUBWF sets CARRY iff *
5160 * F-W >= 0 <==> F >= W <==> !(F < W) *
5161 * (F=left, W=right) *
5162 ****************************************************/
5165 if (result && AOP_TYPE(result) != AOP_CRY) {
5166 // value will be stored
5169 // value wil only be used in the following genSkipc()
5170 rIfx.condition ^= 1;
5174 correct_result_in_carry:
5176 // assign result to variable (if neccessary)
5177 if (result && AOP_TYPE(result) != AOP_CRY) {
5178 //DEBUGpc ("assign result");
5179 size = AOP_SIZE(result);
5181 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5183 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5186 // perform conditional jump
5188 //DEBUGpc ("generate control flow");
5197 static void genCmp (operand *left,operand *right,
5198 operand *result, iCode *ifx, int sign)
5200 int size; //, offset = 0 ;
5201 unsigned long lit = 0L,i = 0;
5202 resolvedIfx rFalseIfx;
5203 // resolvedIfx rTrueIfx;
5205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5208 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5215 resolveIfx(&rFalseIfx,ifx);
5216 truelbl = newiTempLabel(NULL);
5217 size = max(AOP_SIZE(left),AOP_SIZE(right));
5219 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5223 /* if literal is on the right then swap with left */
5224 if ((AOP_TYPE(right) == AOP_LIT)) {
5225 operand *tmp = right ;
5226 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5230 lit = (lit - 1) & mask;
5233 rFalseIfx.condition ^= 1;
5236 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5241 //if(IC_TRUE(ifx) == NULL)
5242 /* if left & right are bit variables */
5243 if (AOP_TYPE(left) == AOP_CRY &&
5244 AOP_TYPE(right) == AOP_CRY ) {
5245 assert (0 && "bit variables used in genCmp");
5246 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5249 /* subtract right from left if at the
5250 end the carry flag is set then we know that
5251 left is greater than right */
5253 symbol *lbl = newiTempLabel(NULL);
5256 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5261 if(AOP_TYPE(right) == AOP_LIT) {
5263 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5265 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5272 genSkipCond(&rFalseIfx,left,size-1,7);
5274 /* no need to compare to 0...*/
5275 /* NOTE: this is a de-generate compare that most certainly
5276 * creates some dead code. */
5277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5279 if(ifx) ifx->generated = 1;
5286 //i = (lit >> (size*8)) & 0xff;
5287 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5289 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291 i = ((0-lit) & 0xff);
5294 /* lit is 0x7f, all signed chars are less than
5295 * this except for 0x7f itself */
5296 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297 genSkipz2(&rFalseIfx,0);
5299 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301 genSkipc(&rFalseIfx);
5306 genSkipz2(&rFalseIfx,1);
5308 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309 genSkipc(&rFalseIfx);
5313 if(ifx) ifx->generated = 1;
5317 /* chars are out of the way. now do ints and longs */
5320 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5327 genSkipCond(&rFalseIfx,left,size,7);
5328 if(ifx) ifx->generated = 1;
5333 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5335 //rFalseIfx.condition ^= 1;
5336 //genSkipCond(&rFalseIfx,left,size,7);
5337 //rFalseIfx.condition ^= 1;
5339 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340 if(rFalseIfx.condition)
5341 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5343 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5350 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5352 if(rFalseIfx.condition) {
5354 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5360 genSkipc(&rFalseIfx);
5361 pic16_emitpLabel(truelbl->key);
5362 if(ifx) ifx->generated = 1;
5369 if( (lit & 0xff) == 0) {
5370 /* lower byte is zero */
5371 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372 i = ((lit >> 8) & 0xff) ^0x80;
5373 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376 genSkipc(&rFalseIfx);
5379 if(ifx) ifx->generated = 1;
5384 /* Special cases for signed longs */
5385 if( (lit & 0xffffff) == 0) {
5386 /* lower byte is zero */
5387 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388 i = ((lit >> 8*3) & 0xff) ^0x80;
5389 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392 genSkipc(&rFalseIfx);
5395 if(ifx) ifx->generated = 1;
5403 if(lit & (0x80 << (size*8))) {
5404 /* lit is negative */
5405 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5407 //genSkipCond(&rFalseIfx,left,size,7);
5409 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5411 if(rFalseIfx.condition)
5412 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5414 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5418 /* lit is positive */
5419 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421 if(rFalseIfx.condition)
5422 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5424 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5429 This works, but is only good for ints.
5430 It also requires a "known zero" register.
5431 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5434 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436 genSkipc(&rFalseIfx);
5438 pic16_emitpLabel(truelbl->key);
5439 if(ifx) ifx->generated = 1;
5443 /* There are no more special cases, so perform a general compare */
5445 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5450 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5452 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5454 //rFalseIfx.condition ^= 1;
5455 genSkipc(&rFalseIfx);
5457 pic16_emitpLabel(truelbl->key);
5459 if(ifx) ifx->generated = 1;
5466 /* sign is out of the way. So now do an unsigned compare */
5467 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5470 /* General case - compare to an unsigned literal on the right.*/
5472 i = (lit >> (size*8)) & 0xff;
5473 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5476 i = (lit >> (size*8)) & 0xff;
5479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5481 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5483 /* this byte of the lit is zero,
5484 *if it's not the last then OR in the variable */
5486 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5491 pic16_emitpLabel(lbl->key);
5492 // pic16_emitpLabel(truelbl->key);
5493 //if(emitFinalCheck)
5494 genSkipc(&rFalseIfx);
5496 pic16_emitpLabel(truelbl->key);
5498 if(ifx) ifx->generated = 1;
5505 if(AOP_TYPE(left) == AOP_LIT) {
5506 //symbol *lbl = newiTempLabel(NULL);
5508 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5511 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5514 if((lit == 0) && (sign == 0)){
5517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5519 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5521 genSkipz2(&rFalseIfx,0);
5522 if(ifx) ifx->generated = 1;
5529 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530 /* degenerate compare can never be true */
5531 if(rFalseIfx.condition == 0)
5532 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5534 if(ifx) ifx->generated = 1;
5539 /* signed comparisons to a literal byte */
5541 int lp1 = (lit+1) & 0xff;
5543 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5546 rFalseIfx.condition ^= 1;
5547 genSkipCond(&rFalseIfx,right,0,7);
5550 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552 genSkipz2(&rFalseIfx,1);
5555 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558 rFalseIfx.condition ^= 1;
5559 genSkipc(&rFalseIfx);
5563 /* unsigned comparisons to a literal byte */
5565 switch(lit & 0xff ) {
5567 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568 genSkipz2(&rFalseIfx,0);
5571 rFalseIfx.condition ^= 1;
5572 genSkipCond(&rFalseIfx,right,0,7);
5576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5579 rFalseIfx.condition ^= 1;
5580 if (AOP_TYPE(result) == AOP_CRY)
5581 genSkipc(&rFalseIfx);
5583 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5590 if(ifx) ifx->generated = 1;
5591 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5597 /* Size is greater than 1 */
5605 /* this means lit = 0xffffffff, or -1 */
5608 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609 rFalseIfx.condition ^= 1;
5610 genSkipCond(&rFalseIfx,right,size,7);
5611 if(ifx) ifx->generated = 1;
5613 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5622 if(rFalseIfx.condition) {
5623 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5627 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5629 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5633 if(rFalseIfx.condition) {
5634 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5635 pic16_emitpLabel(truelbl->key);
5637 rFalseIfx.condition ^= 1;
5638 genSkipCond(&rFalseIfx,right,s,7);
5641 if(ifx) ifx->generated = 1;
5643 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649 if((size == 1) && (0 == (lp1&0xff))) {
5650 /* lower byte of signed word is zero */
5651 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5652 i = ((lp1 >> 8) & 0xff) ^0x80;
5653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5657 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5659 if(ifx) ifx->generated = 1;
5662 rFalseIfx.condition ^= 1;
5663 genSkipc(&rFalseIfx);
5664 if(ifx) ifx->generated = 1;
5670 if(lit & (0x80 << (size*8))) {
5671 /* Lit is less than zero */
5672 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5673 //rFalseIfx.condition ^= 1;
5674 //genSkipCond(&rFalseIfx,left,size,7);
5675 //rFalseIfx.condition ^= 1;
5676 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5679 if(rFalseIfx.condition)
5680 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5682 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5686 /* Lit is greater than or equal to zero */
5687 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5688 //rFalseIfx.condition ^= 1;
5689 //genSkipCond(&rFalseIfx,right,size,7);
5690 //rFalseIfx.condition ^= 1;
5692 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5695 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696 if(rFalseIfx.condition)
5697 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5699 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5710 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5712 rFalseIfx.condition ^= 1;
5713 //rFalseIfx.condition = 1;
5714 genSkipc(&rFalseIfx);
5716 pic16_emitpLabel(truelbl->key);
5718 if(ifx) ifx->generated = 1;
5721 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5728 /* compare word or long to an unsigned literal on the right.*/
5733 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5736 break; /* handled above */
5739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742 genSkipz2(&rFalseIfx,0);
5746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5748 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5751 if(rFalseIfx.condition)
5752 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5754 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5757 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5760 rFalseIfx.condition ^= 1;
5761 genSkipc(&rFalseIfx);
5764 pic16_emitpLabel(truelbl->key);
5766 if(ifx) ifx->generated = 1;
5768 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777 i = (lit >> (size*8)) & 0xff;
5779 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5783 i = (lit >> (size*8)) & 0xff;
5786 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5788 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5790 /* this byte of the lit is zero,
5791 * if it's not the last then OR in the variable */
5793 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5798 pic16_emitpLabel(lbl->key);
5800 rFalseIfx.condition ^= 1;
5802 genSkipc(&rFalseIfx);
5806 pic16_emitpLabel(truelbl->key);
5807 if(ifx) ifx->generated = 1;
5809 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5815 /* Compare two variables */
5817 DEBUGpic16_emitcode(";sign","%d",sign);
5821 /* Sigh. thus sucks... */
5825 pctemp = pic16_popGetTempReg(1);
5826 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832 pic16_popReleaseTempReg(pctemp, 1);
5834 /* Signed char comparison */
5835 /* Special thanks to Nikolai Golovchenko for this snippet */
5836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5839 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5844 genSkipc(&rFalseIfx);
5846 if(ifx) ifx->generated = 1;
5848 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5856 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5861 /* The rest of the bytes of a multi-byte compare */
5865 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5868 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5874 pic16_emitpLabel(lbl->key);
5876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5877 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5878 (AOP_TYPE(result) == AOP_REG)) {
5879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5882 genSkipc(&rFalseIfx);
5884 //genSkipc(&rFalseIfx);
5885 if(ifx) ifx->generated = 1;
5888 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5896 if ((AOP_TYPE(result) != AOP_CRY)
5897 && AOP_SIZE(result)) {
5898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5900 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5902 pic16_outBitC(result);
5904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5905 /* if the result is used in the next
5906 ifx conditional branch then generate
5907 code a little differently */
5909 genIfxJump (ifx,"c");
5911 pic16_outBitC(result);
5912 /* leave the result in acc */
5917 #elif 0 /* VR version of genCmp() */ /* } else { */
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921 operand *result, int offset, int invert_op)
5925 /* check condition, > or < ?? */
5926 if(rIfx->condition != 0)invert_op ^= 1;
5928 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5930 if(!ifx)invert_op ^= 1;
5932 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5936 if(!invert_op)return POC_CPFSGT;
5937 else return POC_CPFSLT;
5940 static int compareAopfirstpass=1;
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943 operand *oper, int offset, operand *result,
5944 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5950 /* invert if there is a result to be loaded, in order to fit,
5951 * SETC/CLRC sequence */
5952 if(AOP_SIZE(result))invert_op ^= 1;
5954 // if(sign && !offset)invert_op ^= 1;
5956 // if(sign)invert_op ^= 1;
5958 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5960 if(AOP_SIZE(result) && compareAopfirstpass) {
5963 pic16_emitpcode(POC_SETF, pcop2);
5968 pic16_emitpcode(POC_CLRF, pcop2);
5974 compareAopfirstpass = 0;
5976 /* there is a bug when comparing operands with size > 1,
5977 * because higher bytes can be equal and test should be performed
5978 * to the next lower byte, current algorithm, considers operands
5979 * inequal in these cases! -- VR 20041107 */
5983 pic16_emitpcode(op, pcop);
5985 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5988 if((!sign || !offset) && AOP_SIZE(result)) {
5991 pic16_emitpcode(POC_CLRF, pcop2);
5996 pic16_emitpcode(POC_SETF, pcop2);
6001 /* don't emit final branch (offset == 0) */
6005 pic16_emitpcode(POC_RRCF, pcop2);
6007 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6010 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6014 truelbl = newiTempLabel( NULL );
6015 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6019 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020 pic16_emitpLabel(truelbl->key);
6022 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6027 static void genCmp (operand *left, operand *right,
6028 operand *result, iCode *ifx, int sign)
6032 resolvedIfx rFalseIfx;
6033 symbol *falselbl, *tlbl;
6037 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6039 resolveIfx(&rFalseIfx, ifx);
6040 size = max(AOP_SIZE(left), AOP_SIZE(right));
6042 /* if left & right are bit variables */
6043 if(AOP_TYPE(left) == AOP_CRY
6044 && AOP_TYPE(right) == AOP_CRY ) {
6046 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6049 werror(W_POSSBUG2, __FILE__, __LINE__);
6053 /* if literal is on the right then swap with left */
6054 if((AOP_TYPE(right) == AOP_LIT)) {
6055 operand *tmp = right ;
6056 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6058 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6060 // lit = (lit - 1) & mask;
6063 rFalseIfx.condition ^= 1; /* reverse compare */
6065 if ((AOP_TYPE(left) == AOP_LIT)) {
6066 /* float compares are handled by support functions */
6067 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6070 /* actual comparing algorithm */
6071 // size = AOP_SIZE( right );
6073 falselbl = newiTempLabel( NULL );
6074 if(AOP_TYPE(left) == AOP_LIT) {
6075 /* compare to literal */
6076 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6079 pCodeOp *pct, *pct2;
6082 /* signed compare */
6083 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6085 /* using PRODL:PRODH as a temporary register here */
6086 pct = pic16_popCopyReg(&pic16_pc_prodl);
6087 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6088 tlbl = newiTempLabel( NULL );
6090 /* first compare signs:
6091 * a. if both are positive, compare just like unsigned
6092 * b. if both are negative, invert cmpop, compare just like unsigned
6093 * c. if different signs, determine the result directly */
6099 tlbl1 = newiTempLabel( NULL );
6100 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6104 /* literal is zero or positive:
6105 * a. if carry is zero, too, continue compare,
6106 * b. if carry is set, then continue depending on cmpop ^ condition:
6107 * 1. '<' return false (literal < variable),
6108 * 2. '>' return true (literal > variable) */
6109 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6110 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6113 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6118 /* literal is negative:
6119 * a. if carry is set, too, continue compare,
6120 * b. if carry is zero, then continue depending on cmpop ^ condition:
6121 * 1. '<' return true (literal < variable),
6122 * 2. '>' return false (literal > variable) */
6123 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6124 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6126 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6132 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6134 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6135 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6140 pic16_emitpLabel( tlbl1->key );
6143 compareAopfirstpass=1;
6144 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6145 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 // pic16_emitpcode(POC_MOVWF, pct);
6148 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6150 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6155 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6156 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6157 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6158 // pic16_emitpcode(POC_MOVWF, pct);
6160 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6161 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6162 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6163 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6167 if(ifx)ifx->generated = 1;
6169 if(AOP_SIZE(result)) {
6170 pic16_emitpLabel(tlbl->key);
6171 pic16_emitpLabel(falselbl->key);
6172 pic16_outBitOp( result, pct2 );
6174 pic16_emitpLabel(tlbl->key);
6178 /* unsigned compare */
6179 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6181 compareAopfirstpass=1;
6184 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6185 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6188 if(ifx)ifx->generated = 1;
6190 if(AOP_SIZE(result)) {
6191 pic16_emitpLabel(falselbl->key);
6192 pic16_outBitC( result );
6197 /* compare registers */
6198 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6202 pCodeOp *pct, *pct2;
6204 /* signed compare */
6205 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6207 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6208 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6209 tlbl = newiTempLabel( NULL );
6211 compareAopfirstpass=1;
6214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6215 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217 pic16_emitpcode(POC_MOVWF, pct);
6219 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6220 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6221 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6223 /* WREG already holds left + 0x80 */
6224 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6227 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6228 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230 pic16_emitpcode(POC_MOVWF, pct);
6232 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6233 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6234 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6236 /* WREG already holds left + 0x80 */
6237 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6238 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6241 if(ifx)ifx->generated = 1;
6243 if(AOP_SIZE(result)) {
6244 pic16_emitpLabel(tlbl->key);
6245 pic16_emitpLabel(falselbl->key);
6246 pic16_outBitOp( result, pct2 );
6248 pic16_emitpLabel(tlbl->key);
6252 /* unsigned compare */
6253 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6255 compareAopfirstpass=1;
6258 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6259 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6263 if(ifx)ifx->generated = 1;
6264 if(AOP_SIZE(result)) {
6266 pic16_emitpLabel(falselbl->key);
6267 pic16_outBitC( result );
6278 /*-----------------------------------------------------------------*/
6279 /* genCmpGt :- greater than comparison */
6280 /*-----------------------------------------------------------------*/
6281 static void genCmpGt (iCode *ic, iCode *ifx)
6283 operand *left, *right, *result;
6284 sym_link *letype , *retype;
6290 right= IC_RIGHT(ic);
6291 result = IC_RESULT(ic);
6293 letype = getSpec(operandType(left));
6294 retype =getSpec(operandType(right));
6295 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6296 /* assign the amsops */
6297 pic16_aopOp (left,ic,FALSE);
6298 pic16_aopOp (right,ic,FALSE);
6299 pic16_aopOp (result,ic,TRUE);
6301 genCmp(right, left, result, ifx, sign);
6303 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6305 pic16_freeAsmop(result,NULL,ic,TRUE);
6308 /*-----------------------------------------------------------------*/
6309 /* genCmpLt - less than comparisons */
6310 /*-----------------------------------------------------------------*/
6311 static void genCmpLt (iCode *ic, iCode *ifx)
6313 operand *left, *right, *result;
6314 sym_link *letype , *retype;
6320 right= IC_RIGHT(ic);
6321 result = IC_RESULT(ic);
6323 letype = getSpec(operandType(left));
6324 retype =getSpec(operandType(right));
6325 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6327 /* assign the amsops */
6328 pic16_aopOp (left,ic,FALSE);
6329 pic16_aopOp (right,ic,FALSE);
6330 pic16_aopOp (result,ic,TRUE);
6332 genCmp(left, right, result, ifx, sign);
6334 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6336 pic16_freeAsmop(result,NULL,ic,TRUE);
6341 // FIXME reenable literal optimisation when the pic16 port is stable
6343 /*-----------------------------------------------------------------*/
6344 /* genc16bit2lit - compare a 16 bit value to a literal */
6345 /*-----------------------------------------------------------------*/
6346 static void genc16bit2lit(operand *op, int lit, int offset)
6350 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6351 if( (lit&0xff) == 0)
6356 switch( BYTEofLONG(lit,i)) {
6358 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6364 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6367 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6368 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6373 switch( BYTEofLONG(lit,i)) {
6375 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6379 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6383 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6386 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6388 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6397 /*-----------------------------------------------------------------*/
6398 /* gencjneshort - compare and jump if not equal */
6399 /*-----------------------------------------------------------------*/
6400 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6402 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6404 int res_offset = 0; /* the result may be a different size then left or right */
6405 int res_size = AOP_SIZE(result);
6407 symbol *lbl, *lbl_done;
6409 unsigned long lit = 0L;
6410 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6412 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6413 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6415 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6416 resolveIfx(&rIfx,ifx);
6417 lbl = newiTempLabel(NULL);
6418 lbl_done = newiTempLabel(NULL);
6421 /* if the left side is a literal or
6422 if the right is in a pointer register and left
6424 if ((AOP_TYPE(left) == AOP_LIT) ||
6425 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6430 if(AOP_TYPE(right) == AOP_LIT)
6431 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6433 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6434 preserve_result = 1;
6436 if(result && !preserve_result)
6439 for(i = 0; i < AOP_SIZE(result); i++)
6440 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6444 /* if the right side is a literal then anything goes */
6445 if (AOP_TYPE(right) == AOP_LIT &&
6446 AOP_TYPE(left) != AOP_DIR ) {
6449 genc16bit2lit(left, lit, 0);
6451 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6454 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6457 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6458 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6460 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6466 if(res_offset < res_size-1)
6474 /* if the right side is in a register or in direct space or
6475 if the left is a pointer register & right is not */
6476 else if (AOP_TYPE(right) == AOP_REG ||
6477 AOP_TYPE(right) == AOP_DIR ||
6478 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6479 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6480 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6481 int lbl_key = lbl->key;
6484 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6485 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6487 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6488 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6489 __FUNCTION__,__LINE__);
6493 /* switch(size) { */
6495 /* genc16bit2lit(left, lit, 0); */
6497 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6502 if((AOP_TYPE(left) == AOP_DIR) &&
6503 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6505 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6508 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6510 switch (lit & 0xff) {
6512 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6515 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6516 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6521 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6523 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6524 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6528 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6529 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6534 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6537 if(AOP_TYPE(result) == AOP_CRY) {
6538 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6543 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6545 /* fix me. probably need to check result size too */
6546 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6551 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6552 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6559 if(res_offset < res_size-1)
6564 } else if(AOP_TYPE(right) == AOP_REG &&
6565 AOP_TYPE(left) != AOP_DIR){
6568 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6569 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6570 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6575 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6577 if(res_offset < res_size-1)
6582 /* right is a pointer reg need both a & b */
6584 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6586 pic16_emitcode("mov","b,%s",l);
6587 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6593 if(result && preserve_result)
6596 for(i = 0; i < AOP_SIZE(result); i++)
6597 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6600 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6602 if(result && preserve_result)
6603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6606 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6608 pic16_emitpLabel(lbl->key);
6610 if(result && preserve_result)
6613 for(i = 0; i < AOP_SIZE(result); i++)
6614 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6616 pic16_emitpLabel(lbl_done->key);
6619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6627 /*-----------------------------------------------------------------*/
6628 /* gencjne - compare and jump if not equal */
6629 /*-----------------------------------------------------------------*/
6630 static void gencjne(operand *left, operand *right, iCode *ifx)
6632 symbol *tlbl = newiTempLabel(NULL);
6634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6635 gencjneshort(left, right, lbl);
6637 pic16_emitcode("mov","a,%s",one);
6638 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6639 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6640 pic16_emitcode("clr","a");
6641 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6643 pic16_emitpLabel(lbl->key);
6644 pic16_emitpLabel(tlbl->key);
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitOp - check if operand has to be treated as literal */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitOp(operand *op)
6655 return ((AOP_TYPE(op) == AOP_LIT)
6656 || ( (AOP_TYPE(op) == AOP_PCODE)
6657 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6658 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6661 /*-----------------------------------------------------------------*/
6662 /* is_LitAOp - check if operand has to be treated as literal */
6663 /*-----------------------------------------------------------------*/
6664 static bool is_LitAOp(asmop *aop)
6666 return ((aop->type == AOP_LIT)
6667 || ( (aop->type == AOP_PCODE)
6668 && ( (aop->aopu.pcop->type == PO_LITERAL)
6669 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6674 /*-----------------------------------------------------------------*/
6675 /* genCmpEq - generates code for equal to */
6676 /*-----------------------------------------------------------------*/
6677 static void genCmpEq (iCode *ic, iCode *ifx)
6679 operand *left, *right, *result;
6680 symbol *falselbl = newiTempLabel(NULL);
6681 symbol *donelbl = newiTempLabel(NULL);
6683 int preserve_result = 0;
6684 int generate_result = 0;
6686 unsigned long lit = -1;
6690 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6691 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6692 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6694 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6696 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6698 werror(W_POSSBUG2, __FILE__, __LINE__);
6699 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6700 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6704 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6706 operand *tmp = right ;
6711 if (AOP_TYPE(right) == AOP_LIT) {
6712 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6715 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6716 preserve_result = 1;
6718 if(result && AOP_SIZE(result))
6719 generate_result = 1;
6721 if(generate_result && !preserve_result)
6723 for(i = 0; i < AOP_SIZE(result); i++)
6724 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6727 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6728 for(i=0; i < AOP_SIZE(left); i++)
6730 if(AOP_TYPE(left) != AOP_ACC)
6733 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6737 if(is_LitOp(right)) {
6738 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6739 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6742 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6744 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6749 if(generate_result && preserve_result)
6751 for(i = 0; i < AOP_SIZE(result); i++)
6752 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6756 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6758 if(generate_result && preserve_result)
6759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6761 if(ifx && IC_TRUE(ifx))
6762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6764 if(ifx && IC_FALSE(ifx))
6765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6767 pic16_emitpLabel(falselbl->key);
6771 if(ifx && IC_FALSE(ifx))
6772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6774 if(generate_result && preserve_result)
6776 for(i = 0; i < AOP_SIZE(result); i++)
6777 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6780 pic16_emitpLabel(donelbl->key);
6786 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6787 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6788 pic16_freeAsmop(result,NULL,ic,TRUE);
6794 // old version kept for reference
6796 /*-----------------------------------------------------------------*/
6797 /* genCmpEq - generates code for equal to */
6798 /*-----------------------------------------------------------------*/
6799 static void genCmpEq (iCode *ic, iCode *ifx)
6801 operand *left, *right, *result;
6802 unsigned long lit = 0L;
6804 symbol *falselbl = newiTempLabel(NULL);
6807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6810 DEBUGpic16_emitcode ("; ifx is non-null","");
6812 DEBUGpic16_emitcode ("; ifx is null","");
6814 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6815 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6816 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6818 size = max(AOP_SIZE(left),AOP_SIZE(right));
6820 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6822 /* if literal, literal on the right or
6823 if the right is in a pointer register and left
6825 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6826 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6827 operand *tmp = right ;
6833 if(ifx && !AOP_SIZE(result)){
6835 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6836 /* if they are both bit variables */
6837 if (AOP_TYPE(left) == AOP_CRY &&
6838 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6839 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6840 if(AOP_TYPE(right) == AOP_LIT){
6841 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6843 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844 pic16_emitcode("cpl","c");
6845 } else if(lit == 1L) {
6846 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6848 pic16_emitcode("clr","c");
6850 /* AOP_TYPE(right) == AOP_CRY */
6852 symbol *lbl = newiTempLabel(NULL);
6853 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6854 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6855 pic16_emitcode("cpl","c");
6856 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6858 /* if true label then we jump if condition
6860 tlbl = newiTempLabel(NULL);
6861 if ( IC_TRUE(ifx) ) {
6862 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6863 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6865 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6866 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6868 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6871 /* left and right are both bit variables, result is carry */
6874 resolveIfx(&rIfx,ifx);
6876 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6877 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6878 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6879 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6884 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6886 /* They're not both bit variables. Is the right a literal? */
6887 if(AOP_TYPE(right) == AOP_LIT) {
6888 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6893 switch(lit & 0xff) {
6895 if ( IC_TRUE(ifx) ) {
6896 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6900 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6905 if ( IC_TRUE(ifx) ) {
6906 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6910 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6911 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6917 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6922 /* end of size == 1 */
6926 genc16bit2lit(left,lit,offset);
6929 /* end of size == 2 */
6934 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6935 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6936 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6937 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6940 /* search for patterns that can be optimized */
6942 genc16bit2lit(left,lit,0);
6946 emitSKPZ; // if hi word unequal
6948 emitSKPNZ; // if hi word equal
6950 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6951 genc16bit2lit(left,lit,2);
6954 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6955 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6959 pic16_emitpLabel(falselbl->key);
6968 } else if(AOP_TYPE(right) == AOP_CRY ) {
6969 /* we know the left is not a bit, but that the right is */
6970 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6971 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6972 pic16_popGet(AOP(right),offset));
6973 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6975 /* if the two are equal, then W will be 0 and the Z bit is set
6976 * we could test Z now, or go ahead and check the high order bytes if
6977 * the variable we're comparing is larger than a byte. */
6980 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6982 if ( IC_TRUE(ifx) ) {
6984 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6985 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6988 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6989 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6993 /* They're both variables that are larger than bits */
6996 tlbl = newiTempLabel(NULL);
6999 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7000 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7002 if ( IC_TRUE(ifx) ) {
7006 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7009 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7013 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7017 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7022 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7024 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7025 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7029 if(s>1 && IC_TRUE(ifx)) {
7030 pic16_emitpLabel(tlbl->key);
7031 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7035 /* mark the icode as generated */
7040 /* if they are both bit variables */
7041 if (AOP_TYPE(left) == AOP_CRY &&
7042 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7043 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7044 if(AOP_TYPE(right) == AOP_LIT){
7045 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7047 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048 pic16_emitcode("cpl","c");
7049 } else if(lit == 1L) {
7050 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7052 pic16_emitcode("clr","c");
7054 /* AOP_TYPE(right) == AOP_CRY */
7056 symbol *lbl = newiTempLabel(NULL);
7057 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7058 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7059 pic16_emitcode("cpl","c");
7060 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7063 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7064 pic16_outBitC(result);
7068 genIfxJump (ifx,"c");
7071 /* if the result is used in an arithmetic operation
7072 then put the result in place */
7073 pic16_outBitC(result);
7076 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7077 gencjne(left,right,result,ifx);
7080 gencjne(left,right,newiTempLabel(NULL));
7082 if(IC_TRUE(ifx)->key)
7083 gencjne(left,right,IC_TRUE(ifx)->key);
7085 gencjne(left,right,IC_FALSE(ifx)->key);
7089 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7090 pic16_aopPut(AOP(result),"a",0);
7095 genIfxJump (ifx,"a");
7099 /* if the result is used in an arithmetic operation
7100 then put the result in place */
7102 if (AOP_TYPE(result) != AOP_CRY)
7103 pic16_outAcc(result);
7105 /* leave the result in acc */
7109 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7110 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7111 pic16_freeAsmop(result,NULL,ic,TRUE);
7115 /*-----------------------------------------------------------------*/
7116 /* ifxForOp - returns the icode containing the ifx for operand */
7117 /*-----------------------------------------------------------------*/
7118 static iCode *ifxForOp ( operand *op, iCode *ic )
7122 /* if true symbol then needs to be assigned */
7123 if (IS_TRUE_SYMOP(op))
7126 /* if this has register type condition and
7127 the next instruction is ifx with the same operand
7128 and live to of the operand is upto the ifx only then */
7130 && ic->next->op == IFX
7131 && IC_COND(ic->next)->key == op->key
7132 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7134 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7140 ic->next->op == IFX &&
7141 IC_COND(ic->next)->key == op->key) {
7142 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7147 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7149 ic->next->op == IFX)
7150 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7153 ic->next->op == IFX &&
7154 IC_COND(ic->next)->key == op->key) {
7155 DEBUGpic16_emitcode ("; "," key is okay");
7156 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7157 OP_SYMBOL(op)->liveTo,
7162 /* the code below is completely untested
7163 * it just allows ulong2fs.c compile -- VR */
7166 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7167 __FILE__, __FUNCTION__, __LINE__);
7169 /* if this has register type condition and
7170 the next instruction is ifx with the same operand
7171 and live to of the operand is upto the ifx only then */
7173 ic->next->op == IFX &&
7174 IC_COND(ic->next)->key == op->key &&
7175 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7179 ic->next->op == IFX &&
7180 IC_COND(ic->next)->key == op->key) {
7181 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7185 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7186 __FILE__, __FUNCTION__, __LINE__);
7188 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7193 /*-----------------------------------------------------------------*/
7194 /* genAndOp - for && operation */
7195 /*-----------------------------------------------------------------*/
7196 static void genAndOp (iCode *ic)
7198 operand *left,*right, *result;
7203 /* note here that && operations that are in an
7204 if statement are taken away by backPatchLabels
7205 only those used in arthmetic operations remain */
7206 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7207 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7208 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7210 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7212 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7213 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7216 /* if both are bit variables */
7217 /* if (AOP_TYPE(left) == AOP_CRY && */
7218 /* AOP_TYPE(right) == AOP_CRY ) { */
7219 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7220 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7221 /* pic16_outBitC(result); */
7223 /* tlbl = newiTempLabel(NULL); */
7224 /* pic16_toBoolean(left); */
7225 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7226 /* pic16_toBoolean(right); */
7227 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7228 /* pic16_outBitAcc(result); */
7231 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7232 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7233 pic16_freeAsmop(result,NULL,ic,TRUE);
7237 /*-----------------------------------------------------------------*/
7238 /* genOrOp - for || operation */
7239 /*-----------------------------------------------------------------*/
7242 modified this code, but it doesn't appear to ever get called
7245 static void genOrOp (iCode *ic)
7247 operand *left,*right, *result;
7252 /* note here that || operations that are in an
7253 if statement are taken away by backPatchLabels
7254 only those used in arthmetic operations remain */
7255 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7256 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7257 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7259 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7261 /* if both are bit variables */
7262 if (AOP_TYPE(left) == AOP_CRY &&
7263 AOP_TYPE(right) == AOP_CRY ) {
7264 pic16_emitcode("clrc","");
7265 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7266 AOP(left)->aopu.aop_dir,
7267 AOP(left)->aopu.aop_dir);
7268 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7269 AOP(right)->aopu.aop_dir,
7270 AOP(right)->aopu.aop_dir);
7271 pic16_emitcode("setc","");
7274 tlbl = newiTempLabel(NULL);
7275 pic16_toBoolean(left);
7277 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7278 pic16_toBoolean(right);
7279 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7281 pic16_outBitAcc(result);
7284 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7285 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7286 pic16_freeAsmop(result,NULL,ic,TRUE);
7289 /*-----------------------------------------------------------------*/
7290 /* isLiteralBit - test if lit == 2^n */
7291 /*-----------------------------------------------------------------*/
7292 static int isLiteralBit(unsigned long lit)
7294 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7295 0x100L,0x200L,0x400L,0x800L,
7296 0x1000L,0x2000L,0x4000L,0x8000L,
7297 0x10000L,0x20000L,0x40000L,0x80000L,
7298 0x100000L,0x200000L,0x400000L,0x800000L,
7299 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7300 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7303 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7304 for(idx = 0; idx < 32; idx++)
7310 /*-----------------------------------------------------------------*/
7311 /* continueIfTrue - */
7312 /*-----------------------------------------------------------------*/
7313 static void continueIfTrue (iCode *ic)
7317 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7321 /*-----------------------------------------------------------------*/
7323 /*-----------------------------------------------------------------*/
7324 static void jumpIfTrue (iCode *ic)
7328 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7332 /*-----------------------------------------------------------------*/
7333 /* jmpTrueOrFalse - */
7334 /*-----------------------------------------------------------------*/
7335 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7337 // ugly but optimized by peephole
7340 symbol *nlbl = newiTempLabel(NULL);
7341 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7342 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7343 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7344 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7346 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7347 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7352 /*-----------------------------------------------------------------*/
7353 /* genAnd - code for and */
7354 /*-----------------------------------------------------------------*/
7355 static void genAnd (iCode *ic, iCode *ifx)
7357 operand *left, *right, *result;
7359 unsigned long lit = 0L;
7365 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7366 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7367 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7369 resolveIfx(&rIfx,ifx);
7371 /* if left is a literal & right is not then exchange them */
7372 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7373 AOP_NEEDSACC(left)) {
7374 operand *tmp = right ;
7379 /* if result = right then exchange them */
7380 if(pic16_sameRegs(AOP(result),AOP(right))){
7381 operand *tmp = right ;
7386 /* if right is bit then exchange them */
7387 if (AOP_TYPE(right) == AOP_CRY &&
7388 AOP_TYPE(left) != AOP_CRY){
7389 operand *tmp = right ;
7393 if(AOP_TYPE(right) == AOP_LIT)
7394 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7396 size = AOP_SIZE(result);
7398 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7401 // result = bit & yy;
7402 if (AOP_TYPE(left) == AOP_CRY){
7403 // c = bit & literal;
7404 if(AOP_TYPE(right) == AOP_LIT){
7406 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7409 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7412 if(size && (AOP_TYPE(result) == AOP_CRY)){
7413 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7416 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7420 pic16_emitcode("clr","c");
7423 if (AOP_TYPE(right) == AOP_CRY){
7425 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7426 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7429 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7431 pic16_emitcode("rrc","a");
7432 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7438 pic16_outBitC(result);
7440 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7441 genIfxJump(ifx, "c");
7445 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7446 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7447 if((AOP_TYPE(right) == AOP_LIT) &&
7448 (AOP_TYPE(result) == AOP_CRY) &&
7449 (AOP_TYPE(left) != AOP_CRY)){
7450 int posbit = isLiteralBit(lit);
7454 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7457 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7463 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7466 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7467 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7470 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7471 size = AOP_SIZE(left);
7474 int bp = posbit, ofs=0;
7481 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7482 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7486 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7487 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7489 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7496 symbol *tlbl = newiTempLabel(NULL);
7497 int sizel = AOP_SIZE(left);
7503 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7505 /* patch provided by Aaron Colwell */
7506 if((posbit = isLiteralBit(bytelit)) != 0) {
7507 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7508 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7509 (posbit-1),0, PO_GPR_REGISTER));
7511 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7512 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7514 if (bytelit == 0xff) {
7515 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7516 * a peephole could optimize it out -- VR */
7517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7519 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7520 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7523 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7524 pic16_popGetLabel(tlbl->key));
7528 /* old code, left here for reference -- VR 09/2004 */
7529 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7531 if((posbit = isLiteralBit(bytelit)) != 0)
7532 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7534 if(bytelit != 0x0FFL)
7535 pic16_emitcode("anl","a,%s",
7536 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7537 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7543 // bit = left & literal
7546 pic16_emitpLabel(tlbl->key);
7548 // if(left & literal)
7551 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7554 pic16_emitpLabel(tlbl->key);
7559 pic16_outBitC(result);
7563 /* if left is same as result */
7564 if(pic16_sameRegs(AOP(result),AOP(left))){
7566 for(;size--; offset++,lit>>=8) {
7567 if(AOP_TYPE(right) == AOP_LIT){
7568 switch(lit & 0xff) {
7570 /* and'ing with 0 has clears the result */
7571 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7575 /* and'ing with 0xff is a nop when the result and left are the same */
7580 int p = pic16_my_powof2( (~lit) & 0xff );
7582 /* only one bit is set in the literal, so use a bcf instruction */
7583 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7584 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7587 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7588 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7589 if(know_W != (lit&0xff))
7590 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7592 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7597 if (AOP_TYPE(left) == AOP_ACC) {
7598 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7600 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7601 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7608 // left & result in different registers
7609 if(AOP_TYPE(result) == AOP_CRY){
7611 // if(size), result in bit
7612 // if(!size && ifx), conditional oper: if(left & right)
7613 symbol *tlbl = newiTempLabel(NULL);
7614 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7616 pic16_emitcode("setb","c");
7618 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7619 pic16_emitcode("anl","a,%s",
7620 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7621 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7626 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7627 pic16_outBitC(result);
7629 jmpTrueOrFalse(ifx, tlbl);
7631 for(;(size--);offset++) {
7633 // result = left & right
7634 if(AOP_TYPE(right) == AOP_LIT){
7635 int t = (lit >> (offset*8)) & 0x0FFL;
7638 pic16_emitcode("clrf","%s",
7639 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7643 pic16_emitcode("movf","%s,w",
7644 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645 pic16_emitcode("movwf","%s",
7646 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7648 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7651 pic16_emitcode("movlw","0x%x",t);
7652 pic16_emitcode("andwf","%s,w",
7653 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654 pic16_emitcode("movwf","%s",
7655 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7657 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7658 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7659 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7664 if (AOP_TYPE(left) == AOP_ACC) {
7665 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7666 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7668 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7669 pic16_emitcode("andwf","%s,w",
7670 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7671 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7672 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7674 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7675 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7681 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7682 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7683 pic16_freeAsmop(result,NULL,ic,TRUE);
7686 /*-----------------------------------------------------------------*/
7687 /* genOr - code for or */
7688 /*-----------------------------------------------------------------*/
7689 static void genOr (iCode *ic, iCode *ifx)
7691 operand *left, *right, *result;
7693 unsigned long lit = 0L;
7695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7697 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7698 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7699 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7701 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7703 /* if left is a literal & right is not then exchange them */
7704 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7705 AOP_NEEDSACC(left)) {
7706 operand *tmp = right ;
7711 /* if result = right then exchange them */
7712 if(pic16_sameRegs(AOP(result),AOP(right))){
7713 operand *tmp = right ;
7718 /* if right is bit then exchange them */
7719 if (AOP_TYPE(right) == AOP_CRY &&
7720 AOP_TYPE(left) != AOP_CRY){
7721 operand *tmp = right ;
7726 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7728 if(AOP_TYPE(right) == AOP_LIT)
7729 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7731 size = AOP_SIZE(result);
7735 if (AOP_TYPE(left) == AOP_CRY){
7736 if(AOP_TYPE(right) == AOP_LIT){
7737 // c = bit & literal;
7739 // lit != 0 => result = 1
7740 if(AOP_TYPE(result) == AOP_CRY){
7742 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7743 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7744 // AOP(result)->aopu.aop_dir,
7745 // AOP(result)->aopu.aop_dir);
7747 continueIfTrue(ifx);
7751 // lit == 0 => result = left
7752 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7754 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7757 if (AOP_TYPE(right) == AOP_CRY){
7758 if(pic16_sameRegs(AOP(result),AOP(left))){
7760 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7761 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7762 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7764 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7765 AOP(result)->aopu.aop_dir,
7766 AOP(result)->aopu.aop_dir);
7767 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7768 AOP(right)->aopu.aop_dir,
7769 AOP(right)->aopu.aop_dir);
7770 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7771 AOP(result)->aopu.aop_dir,
7772 AOP(result)->aopu.aop_dir);
7774 if( AOP_TYPE(result) == AOP_ACC) {
7775 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7776 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7782 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7783 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7784 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7785 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7787 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7788 AOP(result)->aopu.aop_dir,
7789 AOP(result)->aopu.aop_dir);
7790 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7791 AOP(right)->aopu.aop_dir,
7792 AOP(right)->aopu.aop_dir);
7793 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7794 AOP(left)->aopu.aop_dir,
7795 AOP(left)->aopu.aop_dir);
7796 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7797 AOP(result)->aopu.aop_dir,
7798 AOP(result)->aopu.aop_dir);
7803 symbol *tlbl = newiTempLabel(NULL);
7804 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7807 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7808 if( AOP_TYPE(right) == AOP_ACC) {
7809 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7811 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7812 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7817 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7818 pic16_emitcode(";XXX setb","c");
7819 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7820 AOP(left)->aopu.aop_dir,tlbl->key+100);
7821 pic16_toBoolean(right);
7822 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7823 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7824 jmpTrueOrFalse(ifx, tlbl);
7828 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7835 pic16_outBitC(result);
7837 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7838 genIfxJump(ifx, "c");
7842 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7843 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7844 if((AOP_TYPE(right) == AOP_LIT) &&
7845 (AOP_TYPE(result) == AOP_CRY) &&
7846 (AOP_TYPE(left) != AOP_CRY)){
7848 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7851 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7853 continueIfTrue(ifx);
7856 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7857 // lit = 0, result = boolean(left)
7859 pic16_emitcode(";XXX setb","c");
7860 pic16_toBoolean(right);
7862 symbol *tlbl = newiTempLabel(NULL);
7863 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7865 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7867 genIfxJump (ifx,"a");
7871 pic16_outBitC(result);
7875 /* if left is same as result */
7876 if(pic16_sameRegs(AOP(result),AOP(left))){
7878 for(;size--; offset++,lit>>=8) {
7879 if(AOP_TYPE(right) == AOP_LIT){
7880 if((lit & 0xff) == 0)
7881 /* or'ing with 0 has no effect */
7884 int p = pic16_my_powof2(lit & 0xff);
7886 /* only one bit is set in the literal, so use a bsf instruction */
7887 pic16_emitpcode(POC_BSF,
7888 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7890 if(know_W != (lit & 0xff))
7891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7892 know_W = lit & 0xff;
7893 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7898 if (AOP_TYPE(left) == AOP_ACC) {
7899 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7900 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7903 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7905 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7906 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7912 // left & result in different registers
7913 if(AOP_TYPE(result) == AOP_CRY){
7915 // if(size), result in bit
7916 // if(!size && ifx), conditional oper: if(left | right)
7917 symbol *tlbl = newiTempLabel(NULL);
7918 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7919 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7923 pic16_emitcode(";XXX setb","c");
7925 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926 pic16_emitcode(";XXX orl","a,%s",
7927 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7933 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7934 pic16_outBitC(result);
7936 jmpTrueOrFalse(ifx, tlbl);
7937 } else for(;(size--);offset++){
7939 // result = left & right
7940 if(AOP_TYPE(right) == AOP_LIT){
7941 int t = (lit >> (offset*8)) & 0x0FFL;
7944 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7947 // pic16_emitcode("movf","%s,w",
7948 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7949 // pic16_emitcode("movwf","%s",
7950 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7954 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7957 // pic16_emitcode("movlw","0x%x",t);
7958 // pic16_emitcode("iorwf","%s,w",
7959 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7960 // pic16_emitcode("movwf","%s",
7961 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7967 // faster than result <- left, anl result,right
7968 // and better if result is SFR
7969 if (AOP_TYPE(left) == AOP_ACC) {
7970 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7971 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7973 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7974 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7976 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7977 // pic16_emitcode("iorwf","%s,w",
7978 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7980 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7981 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7986 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7987 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7988 pic16_freeAsmop(result,NULL,ic,TRUE);
7991 /*-----------------------------------------------------------------*/
7992 /* genXor - code for xclusive or */
7993 /*-----------------------------------------------------------------*/
7994 static void genXor (iCode *ic, iCode *ifx)
7996 operand *left, *right, *result;
7998 unsigned long lit = 0L;
8000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8002 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8003 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8004 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8006 /* if left is a literal & right is not ||
8007 if left needs acc & right does not */
8008 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8009 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8010 operand *tmp = right ;
8015 /* if result = right then exchange them */
8016 if(pic16_sameRegs(AOP(result),AOP(right))){
8017 operand *tmp = right ;
8022 /* if right is bit then exchange them */
8023 if (AOP_TYPE(right) == AOP_CRY &&
8024 AOP_TYPE(left) != AOP_CRY){
8025 operand *tmp = right ;
8029 if(AOP_TYPE(right) == AOP_LIT)
8030 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8032 size = AOP_SIZE(result);
8036 if (AOP_TYPE(left) == AOP_CRY){
8037 if(AOP_TYPE(right) == AOP_LIT){
8038 // c = bit & literal;
8040 // lit>>1 != 0 => result = 1
8041 if(AOP_TYPE(result) == AOP_CRY){
8043 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8044 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8046 continueIfTrue(ifx);
8049 pic16_emitcode("setb","c");
8053 // lit == 0, result = left
8054 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8056 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8058 // lit == 1, result = not(left)
8059 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8060 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8061 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8062 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8065 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8066 pic16_emitcode("cpl","c");
8073 symbol *tlbl = newiTempLabel(NULL);
8074 if (AOP_TYPE(right) == AOP_CRY){
8076 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8079 int sizer = AOP_SIZE(right);
8081 // if val>>1 != 0, result = 1
8082 pic16_emitcode("setb","c");
8084 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8086 // test the msb of the lsb
8087 pic16_emitcode("anl","a,#0xfe");
8088 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8092 pic16_emitcode("rrc","a");
8094 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8095 pic16_emitcode("cpl","c");
8096 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8101 pic16_outBitC(result);
8103 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8104 genIfxJump(ifx, "c");
8108 if(pic16_sameRegs(AOP(result),AOP(left))){
8109 /* if left is same as result */
8110 for(;size--; offset++) {
8111 if(AOP_TYPE(right) == AOP_LIT){
8112 int t = (lit >> (offset*8)) & 0x0FFL;
8116 if (IS_AOP_PREG(left)) {
8117 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119 pic16_aopPut(AOP(result),"a",offset);
8121 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8122 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8123 pic16_emitcode("xrl","%s,%s",
8124 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8125 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8128 if (AOP_TYPE(left) == AOP_ACC)
8129 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8131 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8132 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8134 if (IS_AOP_PREG(left)) {
8135 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136 pic16_aopPut(AOP(result),"a",offset);
8138 pic16_emitcode("xrl","%s,a",
8139 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8145 // left & result in different registers
8146 if(AOP_TYPE(result) == AOP_CRY){
8148 // if(size), result in bit
8149 // if(!size && ifx), conditional oper: if(left ^ right)
8150 symbol *tlbl = newiTempLabel(NULL);
8151 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8153 pic16_emitcode("setb","c");
8155 if((AOP_TYPE(right) == AOP_LIT) &&
8156 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8157 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8160 pic16_emitcode("xrl","a,%s",
8161 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8163 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8168 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8169 pic16_outBitC(result);
8171 jmpTrueOrFalse(ifx, tlbl);
8172 } else for(;(size--);offset++){
8174 // result = left & right
8175 if(AOP_TYPE(right) == AOP_LIT){
8176 int t = (lit >> (offset*8)) & 0x0FFL;
8179 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181 pic16_emitcode("movf","%s,w",
8182 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183 pic16_emitcode("movwf","%s",
8184 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189 pic16_emitcode("comf","%s,w",
8190 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191 pic16_emitcode("movwf","%s",
8192 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8195 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8196 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8198 pic16_emitcode("movlw","0x%x",t);
8199 pic16_emitcode("xorwf","%s,w",
8200 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8201 pic16_emitcode("movwf","%s",
8202 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8208 // faster than result <- left, anl result,right
8209 // and better if result is SFR
8210 if (AOP_TYPE(left) == AOP_ACC) {
8211 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8212 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8214 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8215 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8216 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8219 if ( AOP_TYPE(result) != AOP_ACC){
8220 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8221 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8227 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8228 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229 pic16_freeAsmop(result,NULL,ic,TRUE);
8232 /*-----------------------------------------------------------------*/
8233 /* genInline - write the inline code out */
8234 /*-----------------------------------------------------------------*/
8235 static void genInline (iCode *ic)
8237 char *buffer, *bp, *bp1;
8239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8241 _G.inLine += (!options.asmpeep);
8243 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8244 strcpy(buffer,IC_INLINE(ic));
8246 while((bp1=strstr(bp, "\\n"))) {
8254 /* This is an experimental code for #pragma inline
8255 and is temporarily disabled for 2.5.0 release */
8263 cbuf = Safe_strdup(buffer);
8264 cblen = strlen(buffer)+1;
8265 memset(cbuf, 0, cblen);
8270 if(*bp != '%')*bp1++ = *bp++;
8276 if(i>elementsInSet(asmInlineMap))break;
8279 s = indexSet(asmInlineMap, i);
8280 DEBUGpc("searching symbol s = `%s'", s);
8281 sym = findSym(SymbolTab, NULL, s);
8284 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8286 strcat(bp1, sym->rname);
8292 if(strlen(bp1) > cblen - 16) {
8293 int i = strlen(cbuf);
8295 cbuf = realloc(cbuf, cblen);
8296 memset(cbuf+i, 0, 50);
8302 buffer = Safe_strdup( cbuf );
8309 /* emit each line as a code */
8315 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8323 /* print label, use this special format with NULL directive
8324 * to denote that the argument should not be indented with tab */
8325 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8328 /* advance to end of line (prevent splitting of comments at ':' */
8329 while (*bp && *bp != '\n') {
8337 if ((bp1 != bp) && *bp1)
8338 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8343 _G.inLine -= (!options.asmpeep);
8346 /*-----------------------------------------------------------------*/
8347 /* genRRC - rotate right with carry */
8348 /*-----------------------------------------------------------------*/
8349 static void genRRC (iCode *ic)
8351 operand *left , *result ;
8352 int size, offset = 0, same;
8354 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8356 /* rotate right with carry */
8358 result=IC_RESULT(ic);
8359 pic16_aopOp (left,ic,FALSE);
8360 pic16_aopOp (result,ic,TRUE);
8362 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8364 same = pic16_sameRegs(AOP(result),AOP(left));
8366 size = AOP_SIZE(result);
8368 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8370 /* get the lsb and put it into the carry */
8371 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8378 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8380 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8387 pic16_freeAsmop(left,NULL,ic,TRUE);
8388 pic16_freeAsmop(result,NULL,ic,TRUE);
8391 /*-----------------------------------------------------------------*/
8392 /* genRLC - generate code for rotate left with carry */
8393 /*-----------------------------------------------------------------*/
8394 static void genRLC (iCode *ic)
8396 operand *left , *result ;
8397 int size, offset = 0;
8400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8401 /* rotate right with carry */
8403 result=IC_RESULT(ic);
8404 pic16_aopOp (left,ic,FALSE);
8405 pic16_aopOp (result,ic,TRUE);
8407 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8409 same = pic16_sameRegs(AOP(result),AOP(left));
8411 /* move it to the result */
8412 size = AOP_SIZE(result);
8414 /* get the msb and put it into the carry */
8415 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8422 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8424 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8425 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8432 pic16_freeAsmop(left,NULL,ic,TRUE);
8433 pic16_freeAsmop(result,NULL,ic,TRUE);
8437 /* gpasm can get the highest order bit with HIGH/UPPER
8438 * so the following probably is not needed -- VR */
8440 /*-----------------------------------------------------------------*/
8441 /* genGetHbit - generates code get highest order bit */
8442 /*-----------------------------------------------------------------*/
8443 static void genGetHbit (iCode *ic)
8445 operand *left, *result;
8447 result=IC_RESULT(ic);
8448 pic16_aopOp (left,ic,FALSE);
8449 pic16_aopOp (result,ic,FALSE);
8451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8452 /* get the highest order byte into a */
8453 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8454 if(AOP_TYPE(result) == AOP_CRY){
8455 pic16_emitcode("rlc","a");
8456 pic16_outBitC(result);
8459 pic16_emitcode("rl","a");
8460 pic16_emitcode("anl","a,#0x01");
8461 pic16_outAcc(result);
8465 pic16_freeAsmop(left,NULL,ic,TRUE);
8466 pic16_freeAsmop(result,NULL,ic,TRUE);
8470 /*-----------------------------------------------------------------*/
8471 /* AccRol - rotate left accumulator by known count */
8472 /*-----------------------------------------------------------------*/
8473 static void AccRol (int shCount)
8475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8476 shCount &= 0x0007; // shCount : 0..7
8481 pic16_emitcode("rl","a");
8484 pic16_emitcode("rl","a");
8485 pic16_emitcode("rl","a");
8488 pic16_emitcode("swap","a");
8489 pic16_emitcode("rr","a");
8492 pic16_emitcode("swap","a");
8495 pic16_emitcode("swap","a");
8496 pic16_emitcode("rl","a");
8499 pic16_emitcode("rr","a");
8500 pic16_emitcode("rr","a");
8503 pic16_emitcode("rr","a");
8509 /*-----------------------------------------------------------------*/
8510 /* AccLsh - left shift accumulator by known count */
8511 /*-----------------------------------------------------------------*/
8512 static void AccLsh (int shCount, int doMask)
8514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8520 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8534 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8538 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8542 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8546 /* no masking is required in genPackBits */
8547 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8551 /*-----------------------------------------------------------------*/
8552 /* AccRsh - right shift accumulator by known count */
8553 /*-----------------------------------------------------------------*/
8554 static void AccRsh (int shCount, int andmask)
8556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8561 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8569 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8572 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8575 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8576 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8580 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8583 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8588 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8590 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8594 /*-----------------------------------------------------------------*/
8595 /* AccSRsh - signed right shift accumulator by known count */
8596 /*-----------------------------------------------------------------*/
8597 static void AccSRsh (int shCount)
8600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8603 pic16_emitcode("mov","c,acc.7");
8604 pic16_emitcode("rrc","a");
8605 } else if(shCount == 2){
8606 pic16_emitcode("mov","c,acc.7");
8607 pic16_emitcode("rrc","a");
8608 pic16_emitcode("mov","c,acc.7");
8609 pic16_emitcode("rrc","a");
8611 tlbl = newiTempLabel(NULL);
8612 /* rotate right accumulator */
8613 AccRol(8 - shCount);
8614 /* and kill the higher order bits */
8615 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8616 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8617 pic16_emitcode("orl","a,#0x%02x",
8618 (unsigned char)~SRMask[shCount]);
8619 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR1Left2Result - shift right one byte from left to result */
8627 /*-----------------------------------------------------------------*/
8628 static void shiftR1Left2ResultSigned (operand *left, int offl,
8629 operand *result, int offr,
8634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8636 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8640 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8642 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8644 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8645 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8653 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8655 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8659 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8665 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8667 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8672 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8675 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8697 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8698 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8705 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8707 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8709 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8722 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8723 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8724 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8727 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8728 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8736 /*-----------------------------------------------------------------*/
8737 /* shiftR1Left2Result - shift right one byte from left to result */
8738 /*-----------------------------------------------------------------*/
8739 static void shiftR1Left2Result (operand *left, int offl,
8740 operand *result, int offr,
8741 int shCount, int sign)
8745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8747 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8749 /* Copy the msb into the carry if signed. */
8751 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8761 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8784 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8788 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8789 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8795 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8796 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8801 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8802 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8810 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8811 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8812 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8813 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8818 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8819 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8820 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8829 /*-----------------------------------------------------------------*/
8830 /* shiftL1Left2Result - shift left one byte from left to result */
8831 /*-----------------------------------------------------------------*/
8832 static void shiftL1Left2Result (operand *left, int offl,
8833 operand *result, int offr, int shCount)
8838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8840 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8841 DEBUGpic16_emitcode ("; ***","same = %d",same);
8842 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8844 /* shift left accumulator */
8845 //AccLsh(shCount, 1); // don't comment out just yet...
8846 // pic16_aopPut(AOP(result),"a",offr);
8850 /* Shift left 1 bit position */
8851 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8855 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8856 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8861 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8862 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8867 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8868 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8874 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8875 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8879 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8880 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8881 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8885 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8886 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8888 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8893 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8897 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8902 /*-----------------------------------------------------------------*/
8903 /* movLeft2Result - move byte from left to result */
8904 /*-----------------------------------------------------------------*/
8905 static void movLeft2Result (operand *left, int offl,
8906 operand *result, int offr)
8909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8910 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8911 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8913 if (*l == '@' && (IS_AOP_PREG(result))) {
8914 pic16_emitcode("mov","a,%s",l);
8915 pic16_aopPut(AOP(result),"a",offr);
8917 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8918 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8923 /*-----------------------------------------------------------------*/
8924 /* shiftL2Left2Result - shift left two bytes from left to result */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftL2Left2Result (operand *left, int offl,
8927 operand *result, int offr, int shCount)
8929 int same = pic16_sameRegs(AOP(result), AOP(left));
8932 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8934 if (same && (offl != offr)) { // shift bytes
8937 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8938 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8940 } else { // just treat as different later on
8953 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8967 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8968 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8974 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8979 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8980 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8982 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8983 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8984 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8985 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8987 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8991 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8992 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8994 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9005 /* note, use a mov/add for the shift since the mov has a
9006 chance of getting optimized out */
9007 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9015 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9028 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9033 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9041 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9046 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9047 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9050 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9053 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9054 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9055 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9056 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9057 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9062 /*-----------------------------------------------------------------*/
9063 /* shiftR2Left2Result - shift right two bytes from left to result */
9064 /*-----------------------------------------------------------------*/
9065 static void shiftR2Left2Result (operand *left, int offl,
9066 operand *result, int offr,
9067 int shCount, int sign)
9069 int same = pic16_sameRegs(AOP(result), AOP(left));
9071 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9073 if (same && (offl != offr)) { // shift right bytes
9076 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9077 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9079 } else { // just treat as different later on
9091 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9096 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9099 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9100 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9101 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9102 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9111 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9119 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9123 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9124 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9125 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9128 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9129 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9132 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9133 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9134 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9135 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9139 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9140 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9145 pic16_emitpcode(POC_BTFSC,
9146 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9147 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9163 pic16_emitpcode(POC_BTFSC,
9164 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9165 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9167 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9168 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9169 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9170 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9174 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9175 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9177 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9178 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9179 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9181 pic16_emitpcode(POC_BTFSC,
9182 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9183 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9185 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9186 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9193 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9194 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9195 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9196 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9199 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9206 /*-----------------------------------------------------------------*/
9207 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9208 /*-----------------------------------------------------------------*/
9209 static void shiftLLeftOrResult (operand *left, int offl,
9210 operand *result, int offr, int shCount)
9212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9214 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9215 /* shift left accumulator */
9217 /* or with result */
9218 /* back to result */
9219 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9222 /*-----------------------------------------------------------------*/
9223 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9224 /*-----------------------------------------------------------------*/
9225 static void shiftRLeftOrResult (operand *left, int offl,
9226 operand *result, int offr, int shCount)
9228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9230 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9231 /* shift right accumulator */
9233 /* or with result */
9234 /* back to result */
9235 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9238 /*-----------------------------------------------------------------*/
9239 /* genlshOne - left shift a one byte quantity by known count */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshOne (operand *result, operand *left, int shCount)
9243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9244 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9247 /*-----------------------------------------------------------------*/
9248 /* genlshTwo - left shift two bytes by known amount != 0 */
9249 /*-----------------------------------------------------------------*/
9250 static void genlshTwo (operand *result,operand *left, int shCount)
9254 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9255 size = pic16_getDataSize(result);
9257 /* if shCount >= 8 */
9263 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9265 movLeft2Result(left, LSB, result, MSB16);
9267 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9270 /* 1 <= shCount <= 7 */
9273 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9275 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9279 /*-----------------------------------------------------------------*/
9280 /* shiftLLong - shift left one long from left to result */
9281 /* offr = LSB or MSB16 */
9282 /*-----------------------------------------------------------------*/
9283 static void shiftLLong (operand *left, operand *result, int offr )
9285 int size = AOP_SIZE(result);
9286 int same = pic16_sameRegs(AOP(left),AOP(result));
9289 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9291 if (same && (offr == MSB16)) { //shift one byte
9292 for(i=size-1;i>=MSB16;i--) {
9293 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9294 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9297 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9300 if (size > LSB+offr ){
9302 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9304 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9305 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9309 if(size > MSB16+offr){
9311 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9313 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9314 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9318 if(size > MSB24+offr){
9320 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9322 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9323 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9327 if(size > MSB32+offr){
9329 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9331 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9332 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9336 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9340 /*-----------------------------------------------------------------*/
9341 /* genlshFour - shift four byte by a known amount != 0 */
9342 /*-----------------------------------------------------------------*/
9343 static void genlshFour (operand *result, operand *left, int shCount)
9347 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9348 size = AOP_SIZE(result);
9350 /* if shifting more that 3 bytes */
9351 if (shCount >= 24 ) {
9354 /* lowest order of left goes to the highest
9355 order of the destination */
9356 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9358 movLeft2Result(left, LSB, result, MSB32);
9360 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9361 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9362 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9367 /* more than two bytes */
9368 else if ( shCount >= 16 ) {
9369 /* lower order two bytes goes to higher order two bytes */
9371 /* if some more remaining */
9373 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9375 movLeft2Result(left, MSB16, result, MSB32);
9376 movLeft2Result(left, LSB, result, MSB24);
9378 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9379 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9383 /* if more than 1 byte */
9384 else if ( shCount >= 8 ) {
9385 /* lower order three bytes goes to higher order three bytes */
9389 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9391 movLeft2Result(left, LSB, result, MSB16);
9393 else{ /* size = 4 */
9395 movLeft2Result(left, MSB24, result, MSB32);
9396 movLeft2Result(left, MSB16, result, MSB24);
9397 movLeft2Result(left, LSB, result, MSB16);
9398 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9400 else if(shCount == 1)
9401 shiftLLong(left, result, MSB16);
9403 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9404 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9405 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9406 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9411 /* 1 <= shCount <= 7 */
9412 else if(shCount <= 3)
9414 shiftLLong(left, result, LSB);
9415 while(--shCount >= 1)
9416 shiftLLong(result, result, LSB);
9418 /* 3 <= shCount <= 7, optimize */
9420 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9421 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9422 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9426 /*-----------------------------------------------------------------*/
9427 /* genLeftShiftLiteral - left shifting by known count */
9428 /*-----------------------------------------------------------------*/
9429 void pic16_genLeftShiftLiteral (operand *left,
9434 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9438 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9439 pic16_freeAsmop(right,NULL,ic,TRUE);
9441 pic16_aopOp(left,ic,FALSE);
9442 pic16_aopOp(result,ic,TRUE);
9444 size = getSize(operandType(result));
9447 pic16_emitcode("; shift left ","result %d, left %d",size,
9451 /* I suppose that the left size >= result size */
9454 movLeft2Result(left, size, result, size);
9458 else if(shCount >= (size * 8))
9460 pic16_aopPut(AOP(result),zero,size);
9464 genlshOne (result,left,shCount);
9469 genlshTwo (result,left,shCount);
9473 genlshFour (result,left,shCount);
9477 pic16_freeAsmop(left,NULL,ic,TRUE);
9478 pic16_freeAsmop(result,NULL,ic,TRUE);
9481 /*-----------------------------------------------------------------*
9482 * genMultiAsm - repeat assembly instruction for size of register.
9483 * if endian == 1, then the high byte (i.e base address + size of
9484 * register) is used first else the low byte is used first;
9485 *-----------------------------------------------------------------*/
9486 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9504 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9510 #if !(USE_GENERIC_SIGNED_SHIFT)
9511 /*-----------------------------------------------------------------*/
9512 /* genLeftShift - generates code for left shifting */
9513 /*-----------------------------------------------------------------*/
9514 static void genLeftShift (iCode *ic)
9516 operand *left,*right, *result;
9519 symbol *tlbl , *tlbl1;
9522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9524 right = IC_RIGHT(ic);
9526 result = IC_RESULT(ic);
9528 pic16_aopOp(right,ic,FALSE);
9530 /* if the shift count is known then do it
9531 as efficiently as possible */
9532 if (AOP_TYPE(right) == AOP_LIT) {
9533 pic16_genLeftShiftLiteral (left,right,result,ic);
9537 /* shift count is unknown then we have to form
9538 * a loop. Get the loop count in WREG : Note: we take
9539 * only the lower order byte since shifting
9540 * more than 32 bits make no sense anyway, ( the
9541 * largest size of an object can be only 32 bits ) */
9543 pic16_aopOp(left,ic,FALSE);
9544 pic16_aopOp(result,ic,FALSE);
9546 /* now move the left to the result if they are not the
9547 * same, and if size > 1,
9548 * and if right is not same to result (!!!) -- VR */
9549 if (!pic16_sameRegs(AOP(left),AOP(result))
9550 && (AOP_SIZE(result) > 1)) {
9552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9554 size = AOP_SIZE(result);
9559 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9560 if (*l == '@' && (IS_AOP_PREG(result))) {
9562 pic16_emitcode("mov","a,%s",l);
9563 pic16_aopPut(AOP(result),"a",offset);
9567 /* we don't know if left is a literal or a register, take care -- VR */
9568 pic16_mov2f(AOP(result), AOP(left), offset);
9574 size = AOP_SIZE(result);
9576 /* if it is only one byte then */
9578 if(optimized_for_speed) {
9579 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9580 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9581 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9582 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9583 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9584 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9585 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9586 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9587 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9588 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9589 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9590 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9595 tlbl = newiTempLabel(NULL);
9598 /* this is already done, why change it? */
9599 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9600 pic16_mov2f(AOP(result), AOP(left), 0);
9604 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9605 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9606 pic16_emitpLabel(tlbl->key);
9607 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9608 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9610 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9615 if (pic16_sameRegs(AOP(left),AOP(result))) {
9617 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9619 tlbl = newiTempLabel(NULL);
9620 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9621 genMultiAsm(POC_RRCF, result, size,1);
9622 pic16_emitpLabel(tlbl->key);
9623 genMultiAsm(POC_RLCF, result, size,0);
9624 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9626 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9630 //tlbl = newiTempLabel(NULL);
9632 //tlbl1 = newiTempLabel(NULL);
9634 //reAdjustPreg(AOP(result));
9636 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9637 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9638 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9640 //pic16_emitcode("add","a,acc");
9641 //pic16_aopPut(AOP(result),"a",offset++);
9643 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9645 // pic16_emitcode("rlc","a");
9646 // pic16_aopPut(AOP(result),"a",offset++);
9648 //reAdjustPreg(AOP(result));
9650 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9651 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9654 tlbl = newiTempLabel(NULL);
9655 tlbl1= newiTempLabel(NULL);
9657 size = AOP_SIZE(result);
9660 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9662 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9664 /* offset should be 0, 1 or 3 */
9666 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9668 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9670 pic16_emitpcode(POC_MOVWF, pctemp);
9673 pic16_emitpLabel(tlbl->key);
9676 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9678 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9680 pic16_emitpcode(POC_DECFSZ, pctemp);
9681 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9682 pic16_emitpLabel(tlbl1->key);
9684 pic16_popReleaseTempReg(pctemp,1);
9688 pic16_freeAsmop (right,NULL,ic,TRUE);
9689 pic16_freeAsmop(left,NULL,ic,TRUE);
9690 pic16_freeAsmop(result,NULL,ic,TRUE);
9696 #error old code (left here for reference)
9697 /*-----------------------------------------------------------------*/
9698 /* genLeftShift - generates code for left shifting */
9699 /*-----------------------------------------------------------------*/
9700 static void genLeftShift (iCode *ic)
9702 operand *left,*right, *result;
9705 symbol *tlbl , *tlbl1;
9708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9710 right = IC_RIGHT(ic);
9712 result = IC_RESULT(ic);
9714 pic16_aopOp(right,ic,FALSE);
9716 /* if the shift count is known then do it
9717 as efficiently as possible */
9718 if (AOP_TYPE(right) == AOP_LIT) {
9719 pic16_genLeftShiftLiteral (left,right,result,ic);
9723 /* shift count is unknown then we have to form
9724 a loop get the loop count in B : Note: we take
9725 only the lower order byte since shifting
9726 more that 32 bits make no sense anyway, ( the
9727 largest size of an object can be only 32 bits ) */
9730 pic16_aopOp(left,ic,FALSE);
9731 pic16_aopOp(result,ic,FALSE);
9733 /* now move the left to the result if they are not the
9735 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9736 AOP_SIZE(result) > 1) {
9738 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9740 size = AOP_SIZE(result);
9743 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9744 if (*l == '@' && (IS_AOP_PREG(result))) {
9746 pic16_emitcode("mov","a,%s",l);
9747 pic16_aopPut(AOP(result),"a",offset);
9750 /* we don't know if left is a literal or a register, take care -- VR */
9751 pic16_mov2f(AOP(result), AOP(left), offset);
9757 size = AOP_SIZE(result);
9759 /* if it is only one byte then */
9761 if(optimized_for_speed) {
9762 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9763 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9764 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9765 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9766 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9767 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9768 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9769 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9770 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9771 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9772 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9773 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9778 tlbl = newiTempLabel(NULL);
9779 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9780 pic16_mov2f(AOP(result), AOP(left), 0);
9782 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9783 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9786 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9787 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9788 pic16_emitpLabel(tlbl->key);
9789 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9790 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9792 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9797 if (pic16_sameRegs(AOP(left),AOP(result))) {
9799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9801 tlbl = newiTempLabel(NULL);
9802 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9803 genMultiAsm(POC_RRCF, result, size,1);
9804 pic16_emitpLabel(tlbl->key);
9805 genMultiAsm(POC_RLCF, result, size,0);
9806 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9808 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9812 //tlbl = newiTempLabel(NULL);
9814 //tlbl1 = newiTempLabel(NULL);
9816 //reAdjustPreg(AOP(result));
9818 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9819 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9820 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9822 //pic16_emitcode("add","a,acc");
9823 //pic16_aopPut(AOP(result),"a",offset++);
9825 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9827 // pic16_emitcode("rlc","a");
9828 // pic16_aopPut(AOP(result),"a",offset++);
9830 //reAdjustPreg(AOP(result));
9832 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9833 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9836 tlbl = newiTempLabel(NULL);
9837 tlbl1= newiTempLabel(NULL);
9839 size = AOP_SIZE(result);
9842 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9844 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9846 /* offset should be 0, 1 or 3 */
9848 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9850 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9852 pic16_emitpcode(POC_MOVWF, pctemp);
9855 pic16_emitpLabel(tlbl->key);
9858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9860 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9862 pic16_emitpcode(POC_DECFSZ, pctemp);
9863 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9864 pic16_emitpLabel(tlbl1->key);
9866 pic16_popReleaseTempReg(pctemp,1);
9870 pic16_freeAsmop (right,NULL,ic,TRUE);
9871 pic16_freeAsmop(left,NULL,ic,TRUE);
9872 pic16_freeAsmop(result,NULL,ic,TRUE);
9876 /*-----------------------------------------------------------------*/
9877 /* genrshOne - right shift a one byte quantity by known count */
9878 /*-----------------------------------------------------------------*/
9879 static void genrshOne (operand *result, operand *left,
9880 int shCount, int sign)
9882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9883 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9886 /*-----------------------------------------------------------------*/
9887 /* genrshTwo - right shift two bytes by known amount != 0 */
9888 /*-----------------------------------------------------------------*/
9889 static void genrshTwo (operand *result,operand *left,
9890 int shCount, int sign)
9892 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9893 /* if shCount >= 8 */
9897 shiftR1Left2Result(left, MSB16, result, LSB,
9900 movLeft2Result(left, MSB16, result, LSB);
9902 pic16_addSign (result, 1, sign);
9905 /* 1 <= shCount <= 7 */
9907 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9910 /*-----------------------------------------------------------------*/
9911 /* shiftRLong - shift right one long from left to result */
9912 /* offl = LSB or MSB16 */
9913 /*-----------------------------------------------------------------*/
9914 static void shiftRLong (operand *left, int offl,
9915 operand *result, int sign)
9917 int size = AOP_SIZE(result);
9918 int same = pic16_sameRegs(AOP(left),AOP(result));
9920 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9922 if (same && (offl == MSB16)) { //shift one byte right
9923 for(i=MSB16;i<size;i++) {
9924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9930 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9936 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9938 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9943 /* add sign of "a" */
9944 pic16_addSign(result, MSB32, sign);
9948 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9950 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9955 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9962 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9965 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9966 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9971 /*-----------------------------------------------------------------*/
9972 /* genrshFour - shift four byte by a known amount != 0 */
9973 /*-----------------------------------------------------------------*/
9974 static void genrshFour (operand *result, operand *left,
9975 int shCount, int sign)
9977 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9978 /* if shifting more that 3 bytes */
9979 if(shCount >= 24 ) {
9982 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9984 movLeft2Result(left, MSB32, result, LSB);
9986 pic16_addSign(result, MSB16, sign);
9988 else if(shCount >= 16){
9991 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9993 movLeft2Result(left, MSB24, result, LSB);
9994 movLeft2Result(left, MSB32, result, MSB16);
9996 pic16_addSign(result, MSB24, sign);
9998 else if(shCount >= 8){
10001 shiftRLong(left, MSB16, result, sign);
10002 else if(shCount == 0){
10003 movLeft2Result(left, MSB16, result, LSB);
10004 movLeft2Result(left, MSB24, result, MSB16);
10005 movLeft2Result(left, MSB32, result, MSB24);
10006 pic16_addSign(result, MSB32, sign);
10008 else{ //shcount >= 2
10009 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10010 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10011 /* the last shift is signed */
10012 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10013 pic16_addSign(result, MSB32, sign);
10016 else{ /* 1 <= shCount <= 7 */
10018 shiftRLong(left, LSB, result, sign);
10020 shiftRLong(result, LSB, result, sign);
10023 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10024 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10025 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10030 /*-----------------------------------------------------------------*/
10031 /* genRightShiftLiteral - right shifting by known count */
10032 /*-----------------------------------------------------------------*/
10033 static void genRightShiftLiteral (operand *left,
10039 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10040 int lsize,res_size;
10042 pic16_freeAsmop(right,NULL,ic,TRUE);
10044 pic16_aopOp(left,ic,FALSE);
10045 pic16_aopOp(result,ic,TRUE);
10047 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10050 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10054 lsize = pic16_getDataSize(left);
10055 res_size = pic16_getDataSize(result);
10056 /* test the LEFT size !!! */
10058 /* I suppose that the left size >= result size */
10060 assert (res_size <= lsize);
10061 while (res_size--) {
10062 pic16_mov2f (AOP(result), AOP(left), res_size);
10066 else if(shCount >= (lsize * 8)){
10068 if(res_size == 1) {
10069 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10071 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10072 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10077 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10078 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10079 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10081 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10086 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10091 switch (res_size) {
10093 genrshOne (result,left,shCount,sign);
10097 genrshTwo (result,left,shCount,sign);
10101 genrshFour (result,left,shCount,sign);
10109 pic16_freeAsmop(left,NULL,ic,TRUE);
10110 pic16_freeAsmop(result,NULL,ic,TRUE);
10113 #if !(USE_GENERIC_SIGNED_SHIFT)
10114 /*-----------------------------------------------------------------*/
10115 /* genSignedRightShift - right shift of signed number */
10116 /*-----------------------------------------------------------------*/
10117 static void genSignedRightShift (iCode *ic)
10119 operand *right, *left, *result;
10122 symbol *tlbl, *tlbl1 ;
10125 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10127 /* we do it the hard way put the shift count in b
10128 and loop thru preserving the sign */
10129 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10131 right = IC_RIGHT(ic);
10132 left = IC_LEFT(ic);
10133 result = IC_RESULT(ic);
10135 pic16_aopOp(right,ic,FALSE);
10136 pic16_aopOp(left,ic,FALSE);
10137 pic16_aopOp(result,ic,FALSE);
10140 if ( AOP_TYPE(right) == AOP_LIT) {
10141 genRightShiftLiteral (left,right,result,ic,1);
10144 /* shift count is unknown then we have to form
10145 a loop get the loop count in B : Note: we take
10146 only the lower order byte since shifting
10147 more that 32 bits make no sense anyway, ( the
10148 largest size of an object can be only 32 bits ) */
10150 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10151 //pic16_emitcode("inc","b");
10152 //pic16_freeAsmop (right,NULL,ic,TRUE);
10153 //pic16_aopOp(left,ic,FALSE);
10154 //pic16_aopOp(result,ic,FALSE);
10156 /* now move the left to the result if they are not the
10158 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10159 AOP_SIZE(result) > 1) {
10161 size = AOP_SIZE(result);
10165 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10166 if (*l == '@' && IS_AOP_PREG(result)) {
10168 pic16_emitcode("mov","a,%s",l);
10169 pic16_aopPut(AOP(result),"a",offset);
10171 pic16_aopPut(AOP(result),l,offset);
10173 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10174 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10180 /* mov the highest order bit to OVR */
10181 tlbl = newiTempLabel(NULL);
10182 tlbl1= newiTempLabel(NULL);
10184 size = AOP_SIZE(result);
10187 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10189 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10191 /* offset should be 0, 1 or 3 */
10192 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10194 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10196 pic16_emitpcode(POC_MOVWF, pctemp);
10199 pic16_emitpLabel(tlbl->key);
10201 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10202 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10205 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10208 pic16_emitpcode(POC_DECFSZ, pctemp);
10209 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10210 pic16_emitpLabel(tlbl1->key);
10212 pic16_popReleaseTempReg(pctemp,1);
10214 size = AOP_SIZE(result);
10216 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10217 pic16_emitcode("rlc","a");
10218 pic16_emitcode("mov","ov,c");
10219 /* if it is only one byte then */
10221 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10223 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10224 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10225 pic16_emitcode("mov","c,ov");
10226 pic16_emitcode("rrc","a");
10227 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10228 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10229 pic16_aopPut(AOP(result),"a",0);
10233 reAdjustPreg(AOP(result));
10234 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10235 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10236 pic16_emitcode("mov","c,ov");
10238 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10240 pic16_emitcode("rrc","a");
10241 pic16_aopPut(AOP(result),"a",offset--);
10243 reAdjustPreg(AOP(result));
10244 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10245 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10250 pic16_freeAsmop(left,NULL,ic,TRUE);
10251 pic16_freeAsmop(result,NULL,ic,TRUE);
10252 pic16_freeAsmop(right,NULL,ic,TRUE);
10256 #if !(USE_GENERIC_SIGNED_SHIFT)
10257 #warning This implementation of genRightShift() is incomplete!
10258 /*-----------------------------------------------------------------*/
10259 /* genRightShift - generate code for right shifting */
10260 /*-----------------------------------------------------------------*/
10261 static void genRightShift (iCode *ic)
10263 operand *right, *left, *result;
10267 symbol *tlbl, *tlbl1 ;
10269 /* if signed then we do it the hard way preserve the
10270 sign bit moving it inwards */
10271 letype = getSpec(operandType(IC_LEFT(ic)));
10272 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10274 if (!SPEC_USIGN(letype)) {
10275 genSignedRightShift (ic);
10279 /* signed & unsigned types are treated the same : i.e. the
10280 signed is NOT propagated inwards : quoting from the
10281 ANSI - standard : "for E1 >> E2, is equivalent to division
10282 by 2**E2 if unsigned or if it has a non-negative value,
10283 otherwise the result is implementation defined ", MY definition
10284 is that the sign does not get propagated */
10286 right = IC_RIGHT(ic);
10287 left = IC_LEFT(ic);
10288 result = IC_RESULT(ic);
10290 pic16_aopOp(right,ic,FALSE);
10292 /* if the shift count is known then do it
10293 as efficiently as possible */
10294 if (AOP_TYPE(right) == AOP_LIT) {
10295 genRightShiftLiteral (left,right,result,ic, 0);
10299 /* shift count is unknown then we have to form
10300 a loop get the loop count in B : Note: we take
10301 only the lower order byte since shifting
10302 more that 32 bits make no sense anyway, ( the
10303 largest size of an object can be only 32 bits ) */
10305 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10306 pic16_emitcode("inc","b");
10307 pic16_aopOp(left,ic,FALSE);
10308 pic16_aopOp(result,ic,FALSE);
10310 /* now move the left to the result if they are not the
10312 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10313 AOP_SIZE(result) > 1) {
10315 size = AOP_SIZE(result);
10318 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10319 if (*l == '@' && IS_AOP_PREG(result)) {
10321 pic16_emitcode("mov","a,%s",l);
10322 pic16_aopPut(AOP(result),"a",offset);
10324 pic16_aopPut(AOP(result),l,offset);
10329 tlbl = newiTempLabel(NULL);
10330 tlbl1= newiTempLabel(NULL);
10331 size = AOP_SIZE(result);
10334 /* if it is only one byte then */
10337 tlbl = newiTempLabel(NULL);
10338 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10339 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10340 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10343 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10344 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10345 pic16_emitpLabel(tlbl->key);
10346 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10347 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10349 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10354 reAdjustPreg(AOP(result));
10355 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10356 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10359 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10361 pic16_emitcode("rrc","a");
10362 pic16_aopPut(AOP(result),"a",offset--);
10364 reAdjustPreg(AOP(result));
10366 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10367 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10370 pic16_freeAsmop(left,NULL,ic,TRUE);
10371 pic16_freeAsmop (right,NULL,ic,TRUE);
10372 pic16_freeAsmop(result,NULL,ic,TRUE);
10376 #if (USE_GENERIC_SIGNED_SHIFT)
10377 /*-----------------------------------------------------------------*/
10378 /* genGenericShift - generates code for left or right shifting */
10379 /*-----------------------------------------------------------------*/
10380 static void genGenericShift (iCode *ic, int isShiftLeft) {
10381 operand *left,*right, *result;
10383 int sign, signedCount;
10384 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10385 PIC_OPCODE pos_shift, neg_shift;
10389 right = IC_RIGHT(ic);
10390 left = IC_LEFT(ic);
10391 result = IC_RESULT(ic);
10393 pic16_aopOp(right,ic,FALSE);
10394 pic16_aopOp(left,ic,FALSE);
10395 pic16_aopOp(result,ic,TRUE);
10397 sign = !SPEC_USIGN(operandType (left));
10398 signedCount = !SPEC_USIGN(operandType (right));
10400 /* if the shift count is known then do it
10401 as efficiently as possible */
10402 if (AOP_TYPE(right) == AOP_LIT) {
10403 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10404 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10405 // we should modify right->aopu.aop_lit here!
10406 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10407 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10409 pic16_genLeftShiftLiteral (left,right,result,ic);
10411 genRightShiftLiteral (left,right,result,ic, sign);
10414 } // if (right is literal)
10416 /* shift count is unknown then we have to form a loop.
10417 * Note: we take only the lower order byte since shifting
10418 * more than 32 bits make no sense anyway, ( the
10419 * largest size of an object can be only 32 bits )
10420 * Note: we perform arithmetic shifts if the left operand is
10421 * signed and we do an (effective) right shift, i. e. we
10422 * shift in the sign bit from the left. */
10424 label_complete = newiTempLabel ( NULL );
10425 label_loop_pos = newiTempLabel ( NULL );
10426 label_loop_neg = NULL;
10427 label_negative = NULL;
10428 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10429 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10432 // additional labels needed
10433 label_loop_neg = newiTempLabel ( NULL );
10434 label_negative = newiTempLabel ( NULL );
10437 // copy source to result -- this will effectively truncate the left operand to the size of result!
10438 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10439 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10440 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10441 pic16_mov2f (AOP(result),AOP(left), offset);
10444 // if result is longer than left, fill with zeros (or sign)
10445 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10446 if (sign && AOP_SIZE(left) > 0) {
10447 // shift signed operand -- fill with sign
10448 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10449 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10450 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10451 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10452 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10455 // shift unsigned operand -- fill result with zeros
10456 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10457 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10460 } // if (size mismatch)
10462 pic16_mov2w (AOP(right), 0);
10463 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10464 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10467 // perform a shift by one (shift count is positive)
10468 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10469 // 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])
10470 pic16_emitpLabel (label_loop_pos->key);
10472 if (sign && (pos_shift == POC_RRCF)) {
10473 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10476 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10477 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10478 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->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]+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])
10483 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10484 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10486 pic16_emitpLabel (label_loop_pos->key);
10487 if (sign && (pos_shift == POC_RRCF)) {
10488 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10491 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10492 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10493 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10494 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10498 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10500 pic16_emitpLabel (label_negative->key);
10501 // perform a shift by -1 (shift count is negative)
10502 // 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)
10504 pic16_emitpLabel (label_loop_neg->key);
10505 if (sign && (neg_shift == POC_RRCF)) {
10506 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10509 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10510 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10511 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10512 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10513 } // if (signedCount)
10515 pic16_emitpLabel (label_complete->key);
10518 pic16_freeAsmop (right,NULL,ic,TRUE);
10519 pic16_freeAsmop(left,NULL,ic,TRUE);
10520 pic16_freeAsmop(result,NULL,ic,TRUE);
10523 static void genLeftShift (iCode *ic) {
10524 genGenericShift (ic, 1);
10527 static void genRightShift (iCode *ic) {
10528 genGenericShift (ic, 0);
10533 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10534 void pic16_loadFSR0(operand *op, int lit)
10536 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10537 if (AOP_TYPE(op) == AOP_LIT) {
10538 /* handle 12 bit integers correctly */
10539 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10540 if ((val & 0x0fff) != val) {
10541 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10542 val, (val & 0x0fff) );
10545 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10547 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10550 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10551 // set up FSR0 with address of result
10552 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10553 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10557 /*----------------------------------------------------------------*/
10558 /* pic16_derefPtr - move one byte from the location ptr points to */
10559 /* to WREG (doWrite == 0) or one byte from WREG */
10560 /* to the location ptr points to (doWrite != 0) */
10561 /*----------------------------------------------------------------*/
10562 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10564 if (!IS_PTR(operandType(ptr)))
10566 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10567 else pic16_mov2w (AOP(ptr), 0);
10571 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10572 /* We might determine pointer type right here: */
10573 p_type = DCL_TYPE(operandType(ptr));
10578 if (!fsr0_setup || !*fsr0_setup)
10580 pic16_loadFSR0( ptr, 0 );
10581 if (fsr0_setup) *fsr0_setup = 1;
10584 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10586 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10590 if (AOP(ptr)->aopu.aop_reg[2]) {
10591 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10592 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10593 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10594 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10595 pic16_mov2w(AOP(ptr), 2);
10596 pic16_callGenericPointerRW(doWrite, 1);
10598 // data pointer (just 2 byte given)
10599 if (!fsr0_setup || !*fsr0_setup)
10601 pic16_loadFSR0( ptr, 0 );
10602 if (fsr0_setup) *fsr0_setup = 1;
10605 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10607 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10612 assert (0 && "invalid pointer type specified");
10617 /*-----------------------------------------------------------------*/
10618 /* genUnpackBits - generates code for unpacking bits */
10619 /*-----------------------------------------------------------------*/
10620 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10623 sym_link *etype, *letype;
10624 int blen=0, bstr=0;
10629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10630 etype = getSpec(operandType(result));
10631 letype = getSpec(operandType(left));
10633 // if(IS_BITFIELD(etype)) {
10634 blen = SPEC_BLEN(etype);
10635 bstr = SPEC_BSTR(etype);
10638 lbstr = SPEC_BSTR( letype );
10640 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10641 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10644 if((blen == 1) && (bstr < 8)
10645 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10646 /* it is a single bit, so use the appropriate bit instructions */
10647 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10649 same = pic16_sameRegs(AOP(left),AOP(result));
10650 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10651 pic16_emitpcode(POC_CLRF, op);
10653 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10654 /* workaround to reduce the extra lfsr instruction */
10655 pic16_emitpcode(POC_BTFSC,
10656 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10658 assert (PIC_IS_DATA_PTR (operandType(left)));
10659 pic16_loadFSR0 (left, 0);
10660 pic16_emitpcode(POC_BTFSC,
10661 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10664 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10665 /* unsigned bitfields result in either 0 or 1 */
10666 pic16_emitpcode(POC_INCF, op);
10668 /* signed bitfields result in either 0 or -1 */
10669 pic16_emitpcode(POC_DECF, op);
10672 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10675 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10681 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10682 // access symbol directly
10683 pic16_mov2w (AOP(left), 0);
10685 pic16_derefPtr (left, ptype, 0, NULL);
10688 /* if we have bitdisplacement then it fits */
10689 /* into this byte completely or if length is */
10690 /* less than a byte */
10691 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10693 /* shift right acc */
10696 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10697 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10699 /* VR -- normally I would use the following, but since we use the hack,
10700 * to avoid the masking from AccRsh, why not mask it right now? */
10703 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10706 /* extend signed bitfields to 8 bits */
10707 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10709 assert (blen + bstr > 0);
10710 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10711 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10716 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10720 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10721 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10722 exit(EXIT_FAILURE);
10728 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10730 int size, offset = 0, leoffset=0 ;
10732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10733 pic16_aopOp(result, ic, TRUE);
10737 size = AOP_SIZE(result);
10738 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10742 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10743 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10744 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10749 if(AOP(left)->aopu.pcop->type == PO_DIR)
10750 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10752 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10755 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10757 // pic16_DumpOp("(result)",result);
10758 if(is_LitAOp(AOP(result))) {
10759 pic16_mov2w(AOP(left), offset); // patch 8
10760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10762 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10763 pic16_popGet(AOP(left), offset), //patch 8
10764 pic16_popGet(AOP(result), offset)));
10772 pic16_freeAsmop(result,NULL,ic,TRUE);
10777 /*-----------------------------------------------------------------*/
10778 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10779 /*-----------------------------------------------------------------*/
10780 static void genNearPointerGet (operand *left,
10784 // asmop *aop = NULL;
10785 //regs *preg = NULL ;
10786 sym_link *rtype, *retype;
10787 sym_link *ltype, *letype;
10791 rtype = operandType(result);
10792 retype= getSpec(rtype);
10793 ltype = operandType(left);
10794 letype= getSpec(ltype);
10796 pic16_aopOp(left,ic,FALSE);
10798 // pic16_DumpOp("(left)",left);
10799 // pic16_DumpOp("(result)",result);
10801 /* if left is rematerialisable and
10802 * result is not bit variable type and
10803 * the left is pointer to data space i.e
10804 * lower 128 bytes of space */
10806 if (AOP_TYPE(left) == AOP_PCODE
10807 && !IS_BITFIELD(retype)
10808 && DCL_TYPE(ltype) == POINTER) {
10810 genDataPointerGet (left,result,ic);
10811 pic16_freeAsmop(left, NULL, ic, TRUE);
10815 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10816 pic16_aopOp (result,ic,TRUE);
10818 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10821 if(IS_BITFIELD( retype )
10822 && (SPEC_BLEN(operandType(result))==1)
10826 int bitstrt, bytestrt;
10828 /* if this is bitfield of size 1, see if we are checking the value
10829 * of a single bit in an if-statement,
10830 * if yes, then don't generate usual code, but execute the
10831 * genIfx directly -- VR */
10835 /* CHECK: if next iCode is IFX
10836 * and current result operand is nextic's conditional operand
10837 * and current result operand live ranges ends at nextic's key number
10839 if((nextic->op == IFX)
10840 && (result == IC_COND(nextic))
10841 && (OP_LIVETO(result) == nextic->seq)
10842 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10844 /* everything is ok then */
10845 /* find a way to optimize the genIfx iCode */
10847 bytestrt = SPEC_BSTR(operandType(result))/8;
10848 bitstrt = SPEC_BSTR(operandType(result))%8;
10850 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10852 genIfxpCOpJump(nextic, jop);
10854 pic16_freeAsmop(left, NULL, ic, TRUE);
10855 pic16_freeAsmop(result, NULL, ic, TRUE);
10861 /* if bitfield then unpack the bits */
10862 if (IS_BITFIELD(letype))
10863 genUnpackBits (result, left, NULL, POINTER);
10865 /* we have can just get the values */
10866 int size = AOP_SIZE(result);
10869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10871 pic16_loadFSR0( left, 0 );
10875 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876 pic16_popGet(AOP(result), offset++)));
10878 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879 pic16_popGet(AOP(result), offset++)));
10885 /* now some housekeeping stuff */
10887 /* we had to allocate for this iCode */
10888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10889 pic16_freeAsmop(NULL,aop,ic,TRUE);
10891 /* we did not allocate which means left
10892 * already in a pointer register, then
10893 * if size > 0 && this could be used again
10894 * we have to point it back to where it
10896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10897 if (AOP_SIZE(result) > 1
10898 && !OP_SYMBOL(left)->remat
10899 && ( OP_SYMBOL(left)->liveTo > ic->seq
10901 // int size = AOP_SIZE(result) - 1;
10903 // pic16_emitcode("dec","%s",rname);
10909 pic16_freeAsmop(left,NULL,ic,TRUE);
10910 pic16_freeAsmop(result,NULL,ic,TRUE);
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left,
10921 regs *preg = NULL ;
10923 sym_link *rtype, *retype;
10925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10927 rtype = operandType(result);
10928 retype= getSpec(rtype);
10930 pic16_aopOp(left,ic,FALSE);
10932 /* if the value is already in a pointer register
10933 then don't need anything more */
10934 if (!AOP_INPREG(AOP(left))) {
10935 /* otherwise get a free pointer register */
10937 preg = getFreePtr(ic,&aop,FALSE);
10938 pic16_emitcode("mov","%s,%s",
10940 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941 rname = preg->name ;
10943 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10945 pic16_freeAsmop(left,NULL,ic,TRUE);
10946 pic16_aopOp (result,ic,TRUE);
10948 /* if bitfield then unpack the bits */
10949 if (IS_BITFIELD(retype))
10950 genUnpackBits (result,left,rname,PPOINTER);
10952 /* we have can just get the values */
10953 int size = AOP_SIZE(result);
10958 pic16_emitcode("movx","a,@%s",rname);
10959 pic16_aopPut(AOP(result),"a",offset);
10964 pic16_emitcode("inc","%s",rname);
10968 /* now some housekeeping stuff */
10970 /* we had to allocate for this iCode */
10971 pic16_freeAsmop(NULL,aop,ic,TRUE);
10973 /* we did not allocate which means left
10974 already in a pointer register, then
10975 if size > 0 && this could be used again
10976 we have to point it back to where it
10978 if (AOP_SIZE(result) > 1 &&
10979 !OP_SYMBOL(left)->remat &&
10980 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10982 int size = AOP_SIZE(result) - 1;
10984 pic16_emitcode("dec","%s",rname);
10989 pic16_freeAsmop(result,NULL,ic,TRUE);
10995 /* This code is not adjusted to PIC16 and fails utterly.
10996 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10998 /*-----------------------------------------------------------------*/
10999 /* genFarPointerGet - gget value from far space */
11000 /*-----------------------------------------------------------------*/
11001 static void genFarPointerGet (operand *left,
11002 operand *result, iCode *ic)
11005 sym_link *retype = getSpec(operandType(result));
11007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11009 pic16_aopOp(left,ic,FALSE);
11011 /* if the operand is already in dptr
11012 then we do nothing else we move the value to dptr */
11013 if (AOP_TYPE(left) != AOP_STR) {
11014 /* if this is remateriazable */
11015 if (AOP_TYPE(left) == AOP_IMMD)
11016 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11017 else { /* we need to get it byte by byte */
11018 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11019 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11020 if (options.model == MODEL_FLAT24)
11022 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11026 /* so dptr know contains the address */
11027 pic16_freeAsmop(left,NULL,ic,TRUE);
11028 pic16_aopOp(result,ic,TRUE);
11030 /* if bit then unpack */
11031 if (IS_BITFIELD(retype))
11032 genUnpackBits(result,left,"dptr",FPOINTER);
11034 size = AOP_SIZE(result);
11038 pic16_emitcode("movx","a,@dptr");
11039 pic16_aopPut(AOP(result),"a",offset++);
11041 pic16_emitcode("inc","dptr");
11045 pic16_freeAsmop(result,NULL,ic,TRUE);
11050 /*-----------------------------------------------------------------*/
11051 /* genCodePointerGet - get value from code space */
11052 /*-----------------------------------------------------------------*/
11053 static void genCodePointerGet (operand *left,
11054 operand *result, iCode *ic)
11057 sym_link *retype = getSpec(operandType(result));
11059 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11061 pic16_aopOp(left,ic,FALSE);
11063 /* if the operand is already in dptr
11064 then we do nothing else we move the value to dptr */
11065 if (AOP_TYPE(left) != AOP_STR) {
11066 /* if this is remateriazable */
11067 if (AOP_TYPE(left) == AOP_IMMD)
11068 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11069 else { /* we need to get it byte by byte */
11070 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11071 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11072 if (options.model == MODEL_FLAT24)
11074 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11078 /* so dptr know contains the address */
11079 pic16_freeAsmop(left,NULL,ic,TRUE);
11080 pic16_aopOp(result,ic,FALSE);
11082 /* if bit then unpack */
11083 if (IS_BITFIELD(retype))
11084 genUnpackBits(result,left,"dptr",CPOINTER);
11086 size = AOP_SIZE(result);
11090 pic16_emitcode("clr","a");
11091 pic16_emitcode("movc","a,@a+dptr");
11092 pic16_aopPut(AOP(result),"a",offset++);
11094 pic16_emitcode("inc","dptr");
11098 pic16_freeAsmop(result,NULL,ic,TRUE);
11103 /*-----------------------------------------------------------------*/
11104 /* genGenPointerGet - gget value from generic pointer space */
11105 /*-----------------------------------------------------------------*/
11106 static void genGenPointerGet (operand *left,
11107 operand *result, iCode *ic)
11109 int size, offset, lit;
11110 sym_link *retype = getSpec(operandType(result));
11112 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11113 pic16_aopOp(left,ic,FALSE);
11114 pic16_aopOp(result,ic,FALSE);
11115 size = AOP_SIZE(result);
11117 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11119 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11121 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11122 // load FSR0 from immediate
11123 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11125 // pic16_loadFSR0( left );
11130 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11132 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11139 else { /* we need to get it byte by byte */
11140 // set up FSR0 with address from left
11141 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11142 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11148 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11150 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11157 /* if bit then unpack */
11158 if (IS_BITFIELD(retype))
11159 genUnpackBits(result,left,"BAD",GPOINTER);
11162 pic16_freeAsmop(left,NULL,ic,TRUE);
11163 pic16_freeAsmop(result,NULL,ic,TRUE);
11169 /*-----------------------------------------------------------------*/
11170 /* genGenPointerGet - gget value from generic pointer space */
11171 /*-----------------------------------------------------------------*/
11172 static void genGenPointerGet (operand *left,
11173 operand *result, iCode *ic)
11175 int size, offset, lit;
11176 sym_link *letype = getSpec(operandType(left));
11178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11179 pic16_aopOp(left,ic,FALSE);
11180 pic16_aopOp(result,ic,TRUE);
11181 size = AOP_SIZE(result);
11183 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11185 /* if bit then unpack */
11186 if (IS_BITFIELD(letype)) {
11187 genUnpackBits(result,left,"BAD",GPOINTER);
11191 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11193 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11194 // load FSR0 from immediate
11195 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11197 werror(W_POSSBUG2, __FILE__, __LINE__);
11202 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11204 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11211 } else { /* we need to get it byte by byte */
11213 /* set up WREG:PRODL:FSR0L with address from left */
11214 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11215 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11216 pic16_mov2w(AOP(left), 2);
11217 pic16_callGenericPointerRW(0, size);
11219 assignResultValue(result, 1);
11225 pic16_freeAsmop(left,NULL,ic,TRUE);
11226 pic16_freeAsmop(result,NULL,ic,TRUE);
11229 /*-----------------------------------------------------------------*/
11230 /* genConstPointerGet - get value from const generic pointer space */
11231 /*-----------------------------------------------------------------*/
11232 static void genConstPointerGet (operand *left,
11233 operand *result, iCode *ic)
11235 //sym_link *retype = getSpec(operandType(result));
11236 // symbol *albl = newiTempLabel(NULL); // patch 15
11237 // symbol *blbl = newiTempLabel(NULL); //
11238 // PIC_OPCODE poc; // patch 15
11242 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11243 pic16_aopOp(left,ic,FALSE);
11244 pic16_aopOp(result,ic,TRUE);
11245 size = AOP_SIZE(result);
11247 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11249 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11251 // set up table pointer
11252 if( (AOP_TYPE(left) == AOP_PCODE)
11253 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11254 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11256 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11257 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11258 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11260 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11261 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11263 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11264 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11265 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11269 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11270 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11274 pic16_freeAsmop(left,NULL,ic,TRUE);
11275 pic16_freeAsmop(result,NULL,ic,TRUE);
11279 /*-----------------------------------------------------------------*/
11280 /* genPointerGet - generate code for pointer get */
11281 /*-----------------------------------------------------------------*/
11282 static void genPointerGet (iCode *ic)
11284 operand *left, *result ;
11285 sym_link *type, *etype;
11290 left = IC_LEFT(ic);
11291 result = IC_RESULT(ic) ;
11293 /* depending on the type of pointer we need to
11294 move it to the correct pointer register */
11295 type = operandType(left);
11296 etype = getSpec(type);
11299 if (IS_PTR_CONST(type))
11301 if (IS_CODEPTR(type))
11303 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11305 /* if left is of type of pointer then it is simple */
11306 if (IS_PTR(type) && !IS_FUNC(type->next))
11307 p_type = DCL_TYPE(type);
11309 /* we have to go by the storage class */
11310 p_type = PTR_TYPE(SPEC_OCLS(etype));
11312 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11314 if (SPEC_OCLS(etype)->codesp ) {
11315 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11316 //p_type = CPOINTER ;
11318 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11319 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11320 /*p_type = FPOINTER ;*/
11322 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11323 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11324 /* p_type = PPOINTER; */
11326 if (SPEC_OCLS(etype) == idata ) {
11327 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11328 /* p_type = IPOINTER; */
11330 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11331 /* p_type = POINTER ; */
11335 /* now that we have the pointer type we assign
11336 the pointer values */
11341 genNearPointerGet (left,result,ic);
11345 genPagedPointerGet(left,result,ic);
11349 /* PICs do not support FAR pointers... */
11350 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11352 genFarPointerGet (left,result,ic);
11357 genConstPointerGet (left,result,ic);
11358 //pic16_emitcodePointerGet (left,result,ic);
11363 if (IS_PTR_CONST(type))
11364 genConstPointerGet (left,result,ic);
11367 genGenPointerGet (left,result,ic);
11371 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11372 "genPointerGet: illegal pointer type");
11377 /*-----------------------------------------------------------------*/
11378 /* genPackBits - generates code for packed bit storage */
11379 /*-----------------------------------------------------------------*/
11380 static void genPackBits (sym_link *etype , operand *result,
11382 char *rname, int p_type)
11388 int shifted_and_masked = 0;
11389 unsigned long lit = (unsigned long)-1;
11392 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11393 blen = SPEC_BLEN(etype);
11394 bstr = SPEC_BSTR(etype);
11396 retype = getSpec(operandType(right));
11398 if(AOP_TYPE(right) == AOP_LIT) {
11399 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11401 if((blen == 1) && (bstr < 8)) {
11402 /* it is a single bit, so use the appropriate bit instructions */
11404 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11406 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11407 /* workaround to reduce the extra lfsr instruction */
11409 pic16_emitpcode(POC_BSF,
11410 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11412 pic16_emitpcode(POC_BCF,
11413 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11416 if (PIC_IS_DATA_PTR(operandType(result))) {
11417 pic16_loadFSR0(result, 0);
11418 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11419 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11421 /* get old value */
11422 pic16_derefPtr (result, p_type, 0, NULL);
11423 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11424 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11425 /* write back new value */
11426 pic16_derefPtr (result, p_type, 1, NULL);
11432 /* IORLW below is more efficient */
11433 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11434 lit = (lit & ((1UL << blen) - 1)) << bstr;
11435 shifted_and_masked = 1;
11438 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11439 && IS_BITFIELD(retype)
11440 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11444 rblen = SPEC_BLEN( retype );
11445 rbstr = SPEC_BSTR( retype );
11447 if(IS_BITFIELD(etype)) {
11448 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11449 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11451 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11454 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11456 if(IS_BITFIELD(etype)) {
11457 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11459 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11462 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11466 /* move right to W */
11467 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11470 /* if the bit length is less than or */
11471 /* it exactly fits a byte then */
11472 if((shCnt=SPEC_BSTR(etype))
11473 || SPEC_BLEN(etype) <= 8 ) {
11474 int fsr0_setup = 0;
11476 if (blen != 8 || bstr != 0) {
11477 // we need to combine the value with the old value
11478 if(!shifted_and_masked)
11480 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11482 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11483 SPEC_BSTR(etype), SPEC_BLEN(etype));
11485 /* shift left acc, do NOT mask the result again */
11488 /* using PRODH as a temporary register here */
11489 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11492 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11493 || IS_DIRECT(result)) {
11494 /* access symbol directly */
11495 pic16_mov2w (AOP(result), 0);
11497 /* get old value */
11498 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11501 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11502 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11503 (unsigned char)(0xff >> (8-bstr))) ));
11504 if (!shifted_and_masked) {
11505 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11507 /* We have the shifted and masked (literal) right value in `lit' */
11509 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11511 } // if (blen != 8 || bstr != 0)
11513 /* write new value back */
11514 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11515 || IS_DIRECT(result)) {
11516 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11518 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11527 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11528 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11529 exit(EXIT_FAILURE);
11533 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11534 rLen = SPEC_BLEN(etype)-8;
11536 /* now generate for lengths greater than one byte */
11540 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11546 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11552 pic16_emitcode("movx","@dptr,a");
11557 DEBUGpic16_emitcode(";lcall","__gptrput");
11565 pic16_mov2w(AOP(right), offset++);
11568 /* last last was not complete */
11570 /* save the byte & read byte */
11573 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11574 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11579 pic16_emitcode ("mov","b,a");
11580 pic16_emitcode("movx","a,@dptr");
11584 pic16_emitcode ("push","b");
11585 pic16_emitcode ("push","acc");
11586 pic16_emitcode ("lcall","__gptrget");
11587 pic16_emitcode ("pop","b");
11593 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11594 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11595 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11596 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11597 // pic16_emitcode ("orl","a,b");
11600 // if (p_type == GPOINTER)
11601 // pic16_emitcode("pop","b");
11606 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11607 // pic16_emitcode("mov","@%s,a",rname);
11611 pic16_emitcode("movx","@dptr,a");
11615 DEBUGpic16_emitcode(";lcall","__gptrput");
11622 // pic16_freeAsmop(right, NULL, ic, TRUE);
11625 /*-----------------------------------------------------------------*/
11626 /* genDataPointerSet - remat pointer to data space */
11627 /*-----------------------------------------------------------------*/
11628 static void genDataPointerSet(operand *right,
11632 int size, offset = 0, resoffset=0 ;
11634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11635 pic16_aopOp(right,ic,FALSE);
11637 size = AOP_SIZE(right);
11639 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11642 if ( AOP_TYPE(result) == AOP_PCODE) {
11643 fprintf(stderr,"genDataPointerSet %s, %d\n",
11644 AOP(result)->aopu.pcop->name,
11645 (AOP(result)->aopu.pcop->type == PO_DIR)?
11646 PCOR(AOP(result)->aopu.pcop)->instance:
11647 PCOI(AOP(result)->aopu.pcop)->offset);
11651 if(AOP(result)->aopu.pcop->type == PO_DIR)
11652 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11655 if (AOP_TYPE(right) == AOP_LIT) {
11658 if(!IS_FLOAT(operandType( right )))
11659 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11662 unsigned long lit_int;
11666 /* take care if literal is a float */
11667 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11668 lit = info.lit_int;
11670 lit = lit >> (8*offset);
11671 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11673 pic16_mov2w(AOP(right), offset);
11674 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11680 pic16_freeAsmop(right,NULL,ic,TRUE);
11685 /*-----------------------------------------------------------------*/
11686 /* genNearPointerSet - pic16_emitcode for near pointer put */
11687 /*-----------------------------------------------------------------*/
11688 static void genNearPointerSet (operand *right,
11694 sym_link *ptype = operandType(result);
11695 sym_link *resetype;
11697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11698 retype= getSpec(operandType(right));
11699 resetype = getSpec(operandType(result));
11701 pic16_aopOp(result,ic,FALSE);
11703 /* if the result is rematerializable &
11704 * in data space & not a bit variable */
11706 /* and result is not a bit variable */
11707 if (AOP_TYPE(result) == AOP_PCODE
11708 // && AOP_TYPE(result) == AOP_IMMD
11709 && DCL_TYPE(ptype) == POINTER
11710 && !IS_BITFIELD(retype)
11711 && !IS_BITFIELD(resetype)) {
11713 genDataPointerSet (right,result,ic);
11714 pic16_freeAsmop(result,NULL,ic,TRUE);
11718 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11719 pic16_aopOp(right,ic,FALSE);
11720 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11722 /* if bitfield then unpack the bits */
11723 if (IS_BITFIELD(resetype)) {
11724 genPackBits (resetype, result, right, NULL, POINTER);
11726 /* we have can just get the values */
11727 int size = AOP_SIZE(right);
11730 pic16_loadFSR0(result, 0);
11732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11734 if (AOP_TYPE(right) == AOP_LIT) {
11735 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11737 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11739 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11741 } else { // no literal
11743 pic16_emitpcode(POC_MOVFF,
11744 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11745 pic16_popCopyReg(&pic16_pc_postinc0)));
11747 pic16_emitpcode(POC_MOVFF,
11748 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11749 pic16_popCopyReg(&pic16_pc_indf0)));
11757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11758 /* now some housekeeping stuff */
11760 /* we had to allocate for this iCode */
11761 pic16_freeAsmop(NULL,aop,ic,TRUE);
11763 /* we did not allocate which means left
11764 * already in a pointer register, then
11765 * if size > 0 && this could be used again
11766 * we have to point it back to where it
11768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11769 if (AOP_SIZE(right) > 1
11770 && !OP_SYMBOL(result)->remat
11771 && ( OP_SYMBOL(result)->liveTo > ic->seq
11774 int size = AOP_SIZE(right) - 1;
11777 pic16_emitcode("decf","fsr0,f");
11778 //pic16_emitcode("dec","%s",rname);
11782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11785 pic16_freeAsmop(right,NULL,ic,TRUE);
11786 pic16_freeAsmop(result,NULL,ic,TRUE);
11789 /*-----------------------------------------------------------------*/
11790 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11791 /*-----------------------------------------------------------------*/
11792 static void genPagedPointerSet (operand *right,
11797 regs *preg = NULL ;
11801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11803 retype= getSpec(operandType(right));
11805 pic16_aopOp(result,ic,FALSE);
11807 /* if the value is already in a pointer register
11808 then don't need anything more */
11809 if (!AOP_INPREG(AOP(result))) {
11810 /* otherwise get a free pointer register */
11812 preg = getFreePtr(ic,&aop,FALSE);
11813 pic16_emitcode("mov","%s,%s",
11815 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11816 rname = preg->name ;
11818 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11820 pic16_freeAsmop(result,NULL,ic,TRUE);
11821 pic16_aopOp (right,ic,FALSE);
11823 /* if bitfield then unpack the bits */
11824 if (IS_BITFIELD(retype))
11825 genPackBits (retype,result,right,rname,PPOINTER);
11827 /* we have can just get the values */
11828 int size = AOP_SIZE(right);
11832 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11835 pic16_emitcode("movx","@%s,a",rname);
11838 pic16_emitcode("inc","%s",rname);
11844 /* now some housekeeping stuff */
11846 /* we had to allocate for this iCode */
11847 pic16_freeAsmop(NULL,aop,ic,TRUE);
11849 /* we did not allocate which means left
11850 already in a pointer register, then
11851 if size > 0 && this could be used again
11852 we have to point it back to where it
11854 if (AOP_SIZE(right) > 1 &&
11855 !OP_SYMBOL(result)->remat &&
11856 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11858 int size = AOP_SIZE(right) - 1;
11860 pic16_emitcode("dec","%s",rname);
11865 pic16_freeAsmop(right,NULL,ic,TRUE);
11871 /* This code is not adjusted to PIC16 and fails utterly...
11872 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11874 /*-----------------------------------------------------------------*/
11875 /* genFarPointerSet - set value from far space */
11876 /*-----------------------------------------------------------------*/
11877 static void genFarPointerSet (operand *right,
11878 operand *result, iCode *ic)
11881 sym_link *retype = getSpec(operandType(right));
11883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11884 pic16_aopOp(result,ic,FALSE);
11886 /* if the operand is already in dptr
11887 then we do nothing else we move the value to dptr */
11888 if (AOP_TYPE(result) != AOP_STR) {
11889 /* if this is remateriazable */
11890 if (AOP_TYPE(result) == AOP_IMMD)
11891 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11892 else { /* we need to get it byte by byte */
11893 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11894 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11895 if (options.model == MODEL_FLAT24)
11897 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11901 /* so dptr know contains the address */
11902 pic16_freeAsmop(result,NULL,ic,TRUE);
11903 pic16_aopOp(right,ic,FALSE);
11905 /* if bit then unpack */
11906 if (IS_BITFIELD(retype))
11907 genPackBits(retype,result,right,"dptr",FPOINTER);
11909 size = AOP_SIZE(right);
11913 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11915 pic16_emitcode("movx","@dptr,a");
11917 pic16_emitcode("inc","dptr");
11921 pic16_freeAsmop(right,NULL,ic,TRUE);
11925 /*-----------------------------------------------------------------*/
11926 /* genGenPointerSet - set value from generic pointer space */
11927 /*-----------------------------------------------------------------*/
11929 static void genGenPointerSet (operand *right,
11930 operand *result, iCode *ic)
11932 int i, size, offset, lit;
11933 sym_link *retype = getSpec(operandType(right));
11935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11937 pic16_aopOp(result,ic,FALSE);
11938 pic16_aopOp(right,ic,FALSE);
11939 size = AOP_SIZE(right);
11942 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11944 /* if the operand is already in dptr
11945 then we do nothing else we move the value to dptr */
11946 if (AOP_TYPE(result) != AOP_STR) {
11947 /* if this is remateriazable */
11948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11949 // WARNING: anythig until "else" is untested!
11950 if (AOP_TYPE(result) == AOP_IMMD) {
11951 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11952 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11953 // load FSR0 from immediate
11954 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11958 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11960 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11966 else { /* we need to get it byte by byte */
11967 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11968 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11970 // set up FSR0 with address of result
11971 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11972 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11974 /* hack hack! see if this the FSR. If so don't load W */
11975 if(AOP_TYPE(right) != AOP_ACC) {
11977 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11979 if(AOP_TYPE(right) == AOP_LIT)
11982 // note: pic16_popGet handles sign extension
11983 for(i=0;i<size;i++) {
11984 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11986 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11988 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11993 for(i=0;i<size;i++) {
11995 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11996 pic16_popCopyReg(&pic16_pc_postinc0)));
11998 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11999 pic16_popCopyReg(&pic16_pc_indf0)));
12005 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12006 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12008 } // if (AOP_TYPE(result) != AOP_IMMD)
12010 } // if (AOP_TYPE(result) != AOP_STR)
12011 /* so dptr know contains the address */
12014 /* if bit then unpack */
12015 if (IS_BITFIELD(retype))
12016 genPackBits(retype,result,right,"dptr",GPOINTER);
12018 size = AOP_SIZE(right);
12021 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12023 // set up FSR0 with address of result
12024 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12025 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12028 if (AOP_TYPE(right) == AOP_LIT) {
12029 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12031 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12033 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12035 } else { // no literal
12037 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12039 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12047 pic16_freeAsmop(right,NULL,ic,TRUE);
12048 pic16_freeAsmop(result,NULL,ic,TRUE);
12052 static void genGenPointerSet (operand *right,
12053 operand *result, iCode *ic)
12056 sym_link *retype = getSpec(operandType(result));
12058 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12060 pic16_aopOp(result,ic,FALSE);
12061 pic16_aopOp(right,ic,FALSE);
12062 size = AOP_SIZE(right);
12064 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12067 /* if bit then unpack */
12068 if (IS_BITFIELD(retype)) {
12069 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12070 genPackBits(retype,result,right,"dptr",GPOINTER);
12074 size = AOP_SIZE(right);
12076 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12079 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12081 /* value of right+0 is placed on stack, which will be retrieved
12082 * by the support function thus restoring the stack. The important
12083 * thing is that there is no need to manually restore stack pointer
12085 pushaop(AOP(right), 0);
12086 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12087 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12088 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12089 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12091 /* load address to write to in WREG:FSR0H:FSR0L */
12092 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12093 pic16_popCopyReg(&pic16_pc_fsr0l)));
12094 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12095 pic16_popCopyReg(&pic16_pc_prodl)));
12096 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12098 pic16_callGenericPointerRW(1, size);
12101 pic16_freeAsmop(right,NULL,ic,TRUE);
12102 pic16_freeAsmop(result,NULL,ic,TRUE);
12105 /*-----------------------------------------------------------------*/
12106 /* genPointerSet - stores the value into a pointer location */
12107 /*-----------------------------------------------------------------*/
12108 static void genPointerSet (iCode *ic)
12110 operand *right, *result ;
12111 sym_link *type, *etype;
12116 right = IC_RIGHT(ic);
12117 result = IC_RESULT(ic) ;
12119 /* depending on the type of pointer we need to
12120 move it to the correct pointer register */
12121 type = operandType(result);
12122 etype = getSpec(type);
12124 /* if left is of type of pointer then it is simple */
12125 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12126 p_type = DCL_TYPE(type);
12129 /* we have to go by the storage class */
12130 p_type = PTR_TYPE(SPEC_OCLS(etype));
12132 /* if (SPEC_OCLS(etype)->codesp ) { */
12133 /* p_type = CPOINTER ; */
12136 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12137 /* p_type = FPOINTER ; */
12139 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12140 /* p_type = PPOINTER ; */
12142 /* if (SPEC_OCLS(etype) == idata ) */
12143 /* p_type = IPOINTER ; */
12145 /* p_type = POINTER ; */
12148 /* now that we have the pointer type we assign
12149 the pointer values */
12154 genNearPointerSet (right,result,ic);
12158 genPagedPointerSet (right,result,ic);
12162 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12164 genFarPointerSet (right,result,ic);
12169 genGenPointerSet (right,result,ic);
12173 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12174 "genPointerSet: illegal pointer type");
12178 /*-----------------------------------------------------------------*/
12179 /* genIfx - generate code for Ifx statement */
12180 /*-----------------------------------------------------------------*/
12181 static void genIfx (iCode *ic, iCode *popIc)
12183 operand *cond = IC_COND(ic);
12188 pic16_aopOp(cond,ic,FALSE);
12190 /* get the value into acc */
12191 if (AOP_TYPE(cond) != AOP_CRY)
12192 pic16_toBoolean(cond);
12195 /* the result is now in the accumulator */
12196 pic16_freeAsmop(cond,NULL,ic,TRUE);
12198 /* if there was something to be popped then do it */
12202 /* if the condition is a bit variable */
12203 if (isbit && IS_ITEMP(cond) &&
12205 genIfxJump(ic,"c");
12206 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12208 if (isbit && !IS_ITEMP(cond))
12209 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12211 genIfxJump(ic,"a");
12216 /*-----------------------------------------------------------------*/
12217 /* genAddrOf - generates code for address of */
12218 /*-----------------------------------------------------------------*/
12219 static void genAddrOf (iCode *ic)
12221 operand *result, *left;
12223 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12224 pCodeOp *pcop0, *pcop1, *pcop2;
12228 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12230 sym = OP_SYMBOL( IC_LEFT(ic) );
12233 /* get address of symbol on stack */
12234 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12236 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12237 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12240 // operands on stack are accessible via "FSR2 + index" with index
12241 // starting at 2 for arguments and growing from 0 downwards for
12242 // local variables (index == 0 is not assigned so we add one here)
12244 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12247 assert (soffs < 0);
12251 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12252 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12253 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12254 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12255 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12256 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12257 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12263 // if(pic16_debug_verbose) {
12264 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12265 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12268 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12269 size = AOP_SIZE(IC_RESULT(ic));
12271 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12272 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12273 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12276 pic16_emitpcode(POC_MOVLW, pcop0);
12277 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12278 pic16_emitpcode(POC_MOVLW, pcop1);
12279 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12280 pic16_emitpcode(POC_MOVLW, pcop2);
12281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12284 pic16_emitpcode(POC_MOVLW, pcop0);
12285 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12286 pic16_emitpcode(POC_MOVLW, pcop1);
12287 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12289 pic16_emitpcode(POC_MOVLW, pcop0);
12290 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12293 pic16_freeAsmop(left, NULL, ic, FALSE);
12295 pic16_freeAsmop(result,NULL,ic,TRUE);
12300 /*-----------------------------------------------------------------*/
12301 /* genFarFarAssign - assignment when both are in far space */
12302 /*-----------------------------------------------------------------*/
12303 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12305 int size = AOP_SIZE(right);
12308 /* first push the right side on to the stack */
12310 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12312 pic16_emitcode ("push","acc");
12315 pic16_freeAsmop(right,NULL,ic,FALSE);
12316 /* now assign DPTR to result */
12317 pic16_aopOp(result,ic,FALSE);
12318 size = AOP_SIZE(result);
12320 pic16_emitcode ("pop","acc");
12321 pic16_aopPut(AOP(result),"a",--offset);
12323 pic16_freeAsmop(result,NULL,ic,FALSE);
12328 /*-----------------------------------------------------------------*/
12329 /* genAssign - generate code for assignment */
12330 /*-----------------------------------------------------------------*/
12331 static void genAssign (iCode *ic)
12333 operand *result, *right;
12334 sym_link *restype, *rtype;
12335 int size, offset,know_W;
12336 unsigned long lit = 0L;
12338 result = IC_RESULT(ic);
12339 right = IC_RIGHT(ic) ;
12343 /* if they are the same */
12344 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12347 /* reversed order operands are aopOp'ed so that result operand
12348 * is effective in case right is a stack symbol. This maneauver
12349 * allows to use the _G.resDirect flag later */
12350 pic16_aopOp(result,ic,TRUE);
12351 pic16_aopOp(right,ic,FALSE);
12353 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12355 /* if they are the same registers */
12356 if (pic16_sameRegs(AOP(right),AOP(result)))
12359 /* if the result is a bit */
12360 if (AOP_TYPE(result) == AOP_CRY) {
12361 /* if the right size is a literal then
12362 we know what the value is */
12363 if (AOP_TYPE(right) == AOP_LIT) {
12365 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12366 pic16_popGet(AOP(result),0));
12368 if (((int) operandLitValue(right)))
12369 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12370 AOP(result)->aopu.aop_dir,
12371 AOP(result)->aopu.aop_dir);
12373 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12374 AOP(result)->aopu.aop_dir,
12375 AOP(result)->aopu.aop_dir);
12380 /* the right is also a bit variable */
12381 if (AOP_TYPE(right) == AOP_CRY) {
12382 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12383 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12384 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12389 /* we need to or */
12390 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12391 pic16_toBoolean(right);
12393 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12394 //pic16_aopPut(AOP(result),"a",0);
12398 /* bit variables done */
12400 size = AOP_SIZE(result);
12403 /* bit variables done */
12405 size = AOP_SIZE(result);
12406 restype = operandType(result);
12407 rtype = operandType(right);
12410 if(AOP_TYPE(right) == AOP_LIT) {
12411 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12413 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12415 /* patch tag for literals that are cast to pointers */
12416 if (IS_CODEPTR(restype)) {
12417 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12418 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12420 if (IS_GENPTR(restype))
12422 if (IS_CODEPTR(rtype)) {
12423 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12424 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12425 } else if (PIC_IS_DATA_PTR(rtype)) {
12426 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12427 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12428 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12429 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12430 } else if (IS_PTR(rtype)) {
12431 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12432 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12438 unsigned long lit_int;
12443 if(IS_FIXED16X16(operandType(right))) {
12444 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12446 /* take care if literal is a float */
12447 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12448 lit = info.lit_int;
12453 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12454 // sizeof(unsigned long int), sizeof(float));
12457 if (AOP_TYPE(right) == AOP_REG) {
12458 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12460 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12465 /* when do we have to read the program memory?
12466 * - if right itself is a symbol in code space
12467 * (we don't care what it points to if it's a pointer)
12468 * - AND right is not a function (we would want its address)
12470 if(AOP_TYPE(right) != AOP_LIT
12471 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12472 && !IS_FUNC(OP_SYM_TYPE(right))
12473 && !IS_ITEMP(right)) {
12475 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12476 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12478 // set up table pointer
12479 if(is_LitOp(right)) {
12480 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12481 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12482 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12483 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12484 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12485 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12486 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12488 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12489 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12490 pic16_popCopyReg(&pic16_pc_tblptrl)));
12491 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12492 pic16_popCopyReg(&pic16_pc_tblptrh)));
12493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12494 pic16_popCopyReg(&pic16_pc_tblptru)));
12497 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12498 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12500 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12501 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12502 pic16_popGet(AOP(result),offset)));
12506 /* FIXME: for pointers we need to extend differently (according
12507 * to pointer type DATA/CODE/EEPROM/... :*/
12508 size = getSize(OP_SYM_TYPE(right));
12509 if(AOP_SIZE(result) > size) {
12510 size = AOP_SIZE(result) - size;
12512 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12520 /* VR - What is this?! */
12521 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12524 if(aopIdx(AOP(result),0) == 4) {
12525 /* this is a workaround to save value of right into wreg too,
12526 * value of wreg is going to be used later */
12527 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12528 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12529 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12533 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12539 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12540 if(AOP_TYPE(right) == AOP_LIT) {
12542 if(know_W != (lit&0xff))
12543 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12545 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12547 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12551 } else if (AOP_TYPE(right) == AOP_CRY) {
12552 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12554 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12555 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12556 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12558 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12559 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12560 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12564 if(!_G.resDirect) { /* use this aopForSym feature */
12565 if(AOP_TYPE(result) == AOP_ACC) {
12566 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12568 if(AOP_TYPE(right) == AOP_ACC) {
12569 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12571 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12580 pic16_freeAsmop (right,NULL,ic,FALSE);
12581 pic16_freeAsmop (result,NULL,ic,TRUE);
12584 /*-----------------------------------------------------------------*/
12585 /* genJumpTab - generates code for jump table */
12586 /*-----------------------------------------------------------------*/
12587 static void genJumpTab (iCode *ic)
12592 pCodeOp *jt_offs_hi;
12597 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12598 /* get the condition into accumulator */
12599 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12601 /* multiply by three */
12602 pic16_emitcode("add","a,acc");
12603 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12605 jtab = newiTempLabel(NULL);
12606 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12607 pic16_emitcode("jmp","@a+dptr");
12608 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12611 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12612 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12614 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12615 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12616 pic16_emitpLabel(jtab->key);
12620 jt_offs = pic16_popGetTempReg(0);
12621 jt_offs_hi = pic16_popGetTempReg(1);
12622 jt_label = pic16_popGetLabel (jtab->key);
12623 //fprintf (stderr, "Creating jump table...\n");
12625 // calculate offset into jump table (idx * sizeof (GOTO))
12626 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12627 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12628 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12629 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12630 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12631 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12632 pic16_emitpcode(POC_MOVWF , jt_offs);
12634 // prepare PCLATx (set to first entry in jump table)
12635 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12636 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12637 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12638 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12639 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12641 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12642 pic16_emitpcode(POC_ADDWF , jt_offs);
12643 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12644 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12646 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12648 // release temporaries and prepare jump into table (new PCL --> WREG)
12649 pic16_emitpcode(POC_MOVFW , jt_offs);
12650 pic16_popReleaseTempReg (jt_offs_hi, 1);
12651 pic16_popReleaseTempReg (jt_offs, 0);
12653 // jump into the table
12654 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12656 pic16_emitpLabelFORCE(jtab->key);
12659 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12660 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12662 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12663 /* now generate the jump labels */
12664 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12665 jtab = setNextItem(IC_JTLABELS(ic))) {
12666 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12667 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12670 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12674 /*-----------------------------------------------------------------*/
12675 /* genMixedOperation - gen code for operators between mixed types */
12676 /*-----------------------------------------------------------------*/
12678 TSD - Written for the PIC port - but this unfortunately is buggy.
12679 This routine is good in that it is able to efficiently promote
12680 types to different (larger) sizes. Unfortunately, the temporary
12681 variables that are optimized out by this routine are sometimes
12682 used in other places. So until I know how to really parse the
12683 iCode tree, I'm going to not be using this routine :(.
12685 static int genMixedOperation (iCode *ic)
12688 operand *result = IC_RESULT(ic);
12689 sym_link *ctype = operandType(IC_LEFT(ic));
12690 operand *right = IC_RIGHT(ic);
12696 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12698 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12704 nextright = IC_RIGHT(nextic);
12705 nextleft = IC_LEFT(nextic);
12706 nextresult = IC_RESULT(nextic);
12708 pic16_aopOp(right,ic,FALSE);
12709 pic16_aopOp(result,ic,FALSE);
12710 pic16_aopOp(nextright, nextic, FALSE);
12711 pic16_aopOp(nextleft, nextic, FALSE);
12712 pic16_aopOp(nextresult, nextic, FALSE);
12714 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12716 operand *t = right;
12720 pic16_emitcode(";remove right +","");
12722 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12724 operand *t = right;
12728 pic16_emitcode(";remove left +","");
12732 big = AOP_SIZE(nextleft);
12733 small = AOP_SIZE(nextright);
12735 switch(nextic->op) {
12738 pic16_emitcode(";optimize a +","");
12739 /* if unsigned or not an integral type */
12740 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12741 pic16_emitcode(";add a bit to something","");
12744 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12746 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12747 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12748 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12750 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12758 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12759 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12763 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12766 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12767 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12768 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12769 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12772 pic16_emitcode("rlf","known_zero,w");
12779 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12780 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12781 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12783 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12793 pic16_freeAsmop(right,NULL,ic,TRUE);
12794 pic16_freeAsmop(result,NULL,ic,TRUE);
12795 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12796 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12798 nextic->generated = 1;
12805 /*-----------------------------------------------------------------*/
12806 /* genCast - gen code for casting */
12807 /*-----------------------------------------------------------------*/
12808 static void genCast (iCode *ic)
12810 operand *result = IC_RESULT(ic);
12811 sym_link *ctype = operandType(IC_LEFT(ic));
12812 sym_link *rtype = operandType(IC_RIGHT(ic));
12813 sym_link *restype = operandType(IC_RESULT(ic));
12814 operand *right = IC_RIGHT(ic);
12820 /* if they are equivalent then do nothing */
12821 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12824 pic16_aopOp(result,ic,FALSE);
12825 pic16_aopOp(right,ic,FALSE) ;
12827 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12830 /* if the result is a bit */
12831 if (AOP_TYPE(result) == AOP_CRY) {
12833 /* if the right size is a literal then
12834 * we know what the value is */
12835 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12837 if (AOP_TYPE(right) == AOP_LIT) {
12838 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12839 pic16_popGet(AOP(result),0));
12841 if (((int) operandLitValue(right)))
12842 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12843 AOP(result)->aopu.aop_dir,
12844 AOP(result)->aopu.aop_dir);
12846 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12847 AOP(result)->aopu.aop_dir,
12848 AOP(result)->aopu.aop_dir);
12852 /* the right is also a bit variable */
12853 if (AOP_TYPE(right) == AOP_CRY) {
12855 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12857 pic16_emitcode("clrc","");
12858 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12859 AOP(right)->aopu.aop_dir,
12860 AOP(right)->aopu.aop_dir);
12861 pic16_aopPut(AOP(result),"c",0);
12865 /* we need to or */
12866 if (AOP_TYPE(right) == AOP_REG) {
12867 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12868 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12869 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12871 pic16_toBoolean(right);
12872 pic16_aopPut(AOP(result),"a",0);
12876 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12879 size = AOP_SIZE(result);
12881 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12883 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12884 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12885 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12888 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12893 if(IS_BITFIELD(getSpec(restype))
12894 && IS_BITFIELD(getSpec(rtype))) {
12895 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12898 /* port from pic14 to cope with generic pointers */
12899 if (PIC_IS_TAGGED(restype))
12901 operand *result = IC_RESULT(ic);
12902 //operand *left = IC_LEFT(ic);
12903 operand *right = IC_RIGHT(ic);
12906 /* copy common part */
12907 int max, size = AOP_SIZE(result);
12908 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12909 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12914 pic16_mov2w (AOP(right), size);
12915 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12918 /* upcast into generic pointer type? */
12919 if (IS_GENPTR(restype)
12920 && !PIC_IS_TAGGED(rtype)
12921 && (AOP_SIZE(result) > max))
12923 /* determine appropriate tag for right */
12924 if (PIC_IS_DATA_PTR(rtype))
12925 tag = GPTR_TAG_DATA;
12926 else if (IS_CODEPTR(rtype))
12927 tag = GPTR_TAG_CODE;
12928 else if (PIC_IS_DATA_PTR(ctype)) {
12929 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12930 tag = GPTR_TAG_DATA;
12931 } else if (IS_CODEPTR(ctype)) {
12932 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12933 tag = GPTR_TAG_CODE;
12934 } else if (IS_PTR(rtype)) {
12935 PERFORM_ONCE(weirdcast,
12936 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12938 tag = GPTR_TAG_DATA;
12940 PERFORM_ONCE(weirdcast,
12941 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12943 tag = GPTR_TAG_DATA;
12946 assert (AOP_SIZE(result) == 3);
12947 /* zero-extend address... */
12948 for (size = max; size < AOP_SIZE(result)-1; size++)
12949 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12950 /* ...and add tag */
12951 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12952 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12953 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12954 for (size = max; size < AOP_SIZE(result)-1; size++)
12955 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12956 /* add __code tag */
12957 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12958 } else if (AOP_SIZE(result) > max) {
12959 /* extend non-pointers */
12960 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12961 pic16_addSign(result, max, 0);
12966 /* if they are the same size : or less */
12967 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12969 /* if they are in the same place */
12970 if (pic16_sameRegs(AOP(right),AOP(result)))
12973 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12975 if (IS_PTR_CONST(rtype))
12977 if (IS_CODEPTR(rtype))
12979 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12982 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12984 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12986 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12989 if(AOP_TYPE(right) == AOP_IMMD) {
12990 pCodeOp *pcop0, *pcop1, *pcop2;
12991 symbol *sym = OP_SYMBOL( right );
12993 size = AOP_SIZE(result);
12995 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12997 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12999 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13002 pic16_emitpcode(POC_MOVLW, pcop0);
13003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13004 pic16_emitpcode(POC_MOVLW, pcop1);
13005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13006 pic16_emitpcode(POC_MOVLW, pcop2);
13007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13010 pic16_emitpcode(POC_MOVLW, pcop0);
13011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13012 pic16_emitpcode(POC_MOVLW, pcop1);
13013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13015 pic16_emitpcode(POC_MOVLW, pcop0);
13016 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13020 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13021 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13024 if(AOP_SIZE(result) < 2) {
13025 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13027 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13031 /* if they in different places then copy */
13032 size = AOP_SIZE(result);
13035 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13036 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13043 /* if the result is of type pointer */
13044 if (IS_PTR(ctype)) {
13046 sym_link *type = operandType(right);
13047 sym_link *etype = getSpec(type);
13049 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13051 /* pointer to generic pointer */
13052 if (IS_GENPTR(ctype)) {
13056 p_type = DCL_TYPE(type);
13058 /* we have to go by the storage class */
13059 p_type = PTR_TYPE(SPEC_OCLS(etype));
13061 /* if (SPEC_OCLS(etype)->codesp ) */
13062 /* p_type = CPOINTER ; */
13064 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13065 /* p_type = FPOINTER ; */
13067 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13068 /* p_type = PPOINTER; */
13070 /* if (SPEC_OCLS(etype) == idata ) */
13071 /* p_type = IPOINTER ; */
13073 /* p_type = POINTER ; */
13076 /* the first two bytes are known */
13077 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13078 size = GPTRSIZE - 1;
13081 if(offset < AOP_SIZE(right)) {
13082 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13083 pic16_mov2f(AOP(result), AOP(right), offset);
13085 if ((AOP_TYPE(right) == AOP_PCODE) &&
13086 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13087 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13091 pic16_aopPut(AOP(result),
13092 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13097 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13100 /* the last byte depending on type */
13105 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13109 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13113 pic16_emitcode(";BUG!? ","%d",__LINE__);
13118 if (GPTRSIZE > AOP_SIZE(right)) {
13119 // assume __data pointer... THIS MIGHT BE WRONG!
13120 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13122 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13127 /* this should never happen */
13128 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13129 "got unknown pointer type");
13132 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13138 /* just copy the pointers */
13139 size = AOP_SIZE(result);
13142 pic16_aopPut(AOP(result),
13143 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13152 /* so we now know that the size of destination is greater
13153 than the size of the source.
13154 Now, if the next iCode is an operator then we might be
13155 able to optimize the operation without performing a cast.
13157 if(genMixedOperation(ic))
13160 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13162 /* we move to result for the size of source */
13163 size = AOP_SIZE(right);
13168 pic16_mov2f(AOP(result), AOP(right), offset);
13172 /* now depending on the sign of the destination */
13173 size = AOP_SIZE(result) - AOP_SIZE(right);
13174 /* if unsigned or not an integral type */
13175 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13177 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13179 /* we need to extend the sign :( */
13182 /* Save one instruction of casting char to int */
13183 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13184 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13185 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13187 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13190 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13192 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13194 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13197 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13202 pic16_freeAsmop(right,NULL,ic,TRUE);
13203 pic16_freeAsmop(result,NULL,ic,TRUE);
13207 /*-----------------------------------------------------------------*/
13208 /* genDjnz - generate decrement & jump if not zero instrucion */
13209 /*-----------------------------------------------------------------*/
13210 static int genDjnz (iCode *ic, iCode *ifx)
13212 symbol *lbl, *lbl1;
13213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13218 /* if the if condition has a false label
13219 then we cannot save */
13223 /* if the minus is not of the form
13225 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13226 !IS_OP_LITERAL(IC_RIGHT(ic)))
13229 if (operandLitValue(IC_RIGHT(ic)) != 1)
13232 /* if the size of this greater than one then no
13234 if (getSize(operandType(IC_RESULT(ic))) > 1)
13237 /* otherwise we can save BIG */
13238 lbl = newiTempLabel(NULL);
13239 lbl1= newiTempLabel(NULL);
13241 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13243 if (IS_AOP_PREG(IC_RESULT(ic))) {
13244 pic16_emitcode("dec","%s",
13245 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13246 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13247 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13251 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13252 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13254 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13255 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13259 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13260 ifx->generated = 1;
13264 /*-----------------------------------------------------------------*/
13265 /* genReceive - generate code for a receive iCode */
13266 /*-----------------------------------------------------------------*/
13267 static void genReceive (iCode *ic)
13273 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13274 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13276 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13278 if (isOperandInFarSpace(IC_RESULT(ic))
13279 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13280 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13282 int size = getSize(operandType(IC_RESULT(ic)));
13283 int offset = pic16_fReturnSizePic - size;
13287 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13288 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13292 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13294 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13295 size = AOP_SIZE(IC_RESULT(ic));
13298 pic16_emitcode ("pop","acc");
13299 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13302 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13304 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13307 /* set pseudo stack pointer to where it should be - dw*/
13308 GpsuedoStkPtr = ic->parmBytes;
13310 /* setting GpsuedoStkPtr has side effects here: */
13311 assignResultValue(IC_RESULT(ic), 0);
13314 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13317 /*-----------------------------------------------------------------*/
13318 /* genDummyRead - generate code for dummy read of volatiles */
13319 /*-----------------------------------------------------------------*/
13321 genDummyRead (iCode * ic)
13327 if (op && IS_SYMOP(op)) {
13328 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13329 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13332 pic16_aopOp (op, ic, FALSE);
13333 for (i=0; i < AOP_SIZE(op); i++) {
13334 // may need to protect this from the peepholer -- this is not nice but works...
13335 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13336 pic16_mov2w (AOP(op),i);
13337 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13339 pic16_freeAsmop (op, NULL, ic, TRUE);
13341 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13345 /*-----------------------------------------------------------------*/
13346 /* genpic16Code - generate code for pic16 based controllers */
13347 /*-----------------------------------------------------------------*/
13349 * At this point, ralloc.c has gone through the iCode and attempted
13350 * to optimize in a way suitable for a PIC. Now we've got to generate
13351 * PIC instructions that correspond to the iCode.
13353 * Once the instructions are generated, we'll pass through both the
13354 * peep hole optimizer and the pCode optimizer.
13355 *-----------------------------------------------------------------*/
13357 void genpic16Code (iCode *lic)
13362 lineHead = lineCurr = NULL;
13364 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13365 pic16_addpBlock(pb);
13368 /* if debug information required */
13369 if (options.debug && currFunc) {
13371 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13376 for (ic = lic ; ic ; ic = ic->next ) {
13378 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13379 if ( cln != ic->lineno ) {
13380 if ( options.debug ) {
13381 debugFile->writeCLine (ic);
13384 if(!options.noCcodeInAsm) {
13385 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13386 printCLine(ic->filename, ic->lineno)));
13392 if(options.iCodeInAsm) {
13395 /* insert here code to print iCode as comment */
13396 l = Safe_strdup(printILine(ic));
13397 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13400 /* if the result is marked as
13401 * spilt and rematerializable or code for
13402 * this has already been generated then
13404 if (resultRemat(ic) || ic->generated )
13407 /* depending on the operation */
13426 /* IPOP happens only when trying to restore a
13427 * spilt live range, if there is an ifx statement
13428 * following this pop then the if statement might
13429 * be using some of the registers being popped which
13430 * would destroy the contents of the register so
13431 * we need to check for this condition and handle it */
13433 && ic->next->op == IFX
13434 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13435 genIfx (ic->next,ic);
13453 genEndFunction (ic);
13469 pic16_genPlus (ic) ;
13473 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13474 pic16_genMinus (ic);
13490 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13494 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13500 /* note these two are xlated by algebraic equivalence
13501 * during parsing SDCC.y */
13502 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13503 "got '>=' or '<=' shouldn't have come here");
13507 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13519 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13523 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13527 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13551 genRightShift (ic);
13554 case GET_VALUE_AT_ADDRESS:
13559 if (POINTER_SET(ic))
13586 addSet(&_G.sendSet,ic);
13589 case DUMMY_READ_VOLATILE:
13599 /* now we are ready to call the
13600 peep hole optimizer */
13601 if (!options.nopeep)
13602 peepHole (&lineHead);
13604 /* now do the actual printing */
13605 printLine (lineHead, codeOutFile);
13608 DFPRINTF((stderr,"printing pBlock\n\n"));
13609 pic16_printpBlock(stdout,pb);