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"
52 /* Set the following to 1 to enable the slower/bigger
53 * but more robust generic shifting routine (which also
54 * operates correctly with negative shift values). */
55 #define USE_GENERIC_SIGNED_SHIFT 1
57 /* Set the following to 1 to enable the new
58 * stripped down genCmp version.
59 * This version should be easier to understand,
60 * more reliable and (sigh) slighly slower. */
61 #define USE_SIMPLE_GENCMP 1
63 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
64 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
67 #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
69 /* If you change these, you also have to update the library files
70 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
71 #define GPTR_TAG_DATA 0x80
72 #define GPTR_TAG_EEPROM 0x40
73 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
75 /* Wrapper to execute `code' at most once. */
76 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
78 void pic16_genMult8X8_n (operand *, operand *,operand *);
80 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
81 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 void pic16_genMult16X16_16(operand *, operand *, operand *);
83 void pic16_genMult32X32_32(operand *, operand *, operand *);
85 pCode *pic16_AssembleLine(char *line, int peeps);
86 extern void pic16_printpBlock(FILE *of, pBlock *pb);
87 static asmop *newAsmop (short type);
88 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
89 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
90 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
91 static pCodeOp *pic16_popRegFromIdx(int rIdx);
93 //static int aopIdx (asmop *aop, int offset);
95 int pic16_labelOffset=0;
96 extern int pic16_debug_verbose;
97 #if !(USE_GENERIC_SIGNED_SHIFT)
98 static int optimized_for_speed = 0;
107 /* max_key keeps track of the largest label number used in
108 a function. This is then used to adjust the label offset
109 for the next function.
111 static int max_key=0;
112 static int GpsuedoStkPtr=0;
114 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
116 const char *pic16_AopType(short type);
117 static iCode *ifxForOp ( operand *op, iCode *ic );
119 void pic16_pushpCodeOp(pCodeOp *pcop);
120 void pic16_poppCodeOp(pCodeOp *pcop);
122 static bool is_LitOp(operand *op);
123 static bool is_LitAOp(asmop *aop);
126 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
128 /* set the following macro to 1 to enable passing the
129 * first byte of functions parameters via WREG */
130 #define USE_WREG_IN_FUNC_PARAMS 0
133 /* this is the down and dirty file with all kinds of
134 kludgy & hacky stuff. This is what it is all about
135 CODE GENERATION for a specific MCU . some of the
136 routines may be reusable, will have to see */
138 static char *zero = "#0x00";
139 static char *one = "#0x01";
140 //static char *spname = "sp";
144 * Function return value policy (MSB-->LSB):
146 * 16 bits -> PRODL:WREG
147 * 24 bits -> PRODH:PRODL:WREG
148 * 32 bits -> FSR0L:PRODH:PRODL:WREG
149 * >32 bits -> on stack, and FSR0 points to the beginning
154 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
155 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
156 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
157 static char **fReturn = fReturnpic16;
159 static char *accUse[] = {"WREG"};
161 //static short rbank = -1;
175 bitVect *fregsUsed; /* registers used in function */
177 set *sregsAllocSet; /* registers used to store stack variables */
178 int stack_lat; /* stack offset latency */
180 int useWreg; /* flag when WREG is used to pass function parameter */
183 extern int pic16_ptrRegReq ;
184 extern int pic16_nRegs;
185 extern struct dbuf_s *codeOutBuf;
186 //static void saverbank (int, iCode *,bool);
188 static lineNode *lineHead = NULL;
189 static lineNode *lineCurr = NULL;
191 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
192 0xE0, 0xC0, 0x80, 0x00};
193 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
194 0x07, 0x03, 0x01, 0x00};
198 /*-----------------------------------------------------------------*/
199 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
200 /* exponent of 2 is returned, otherwise -1 is */
202 /* note that this is similar to the function `powof2' in SDCCsymt */
206 /*-----------------------------------------------------------------*/
207 int pic16_my_powof2 (unsigned long num)
210 if( (num & (num-1)) == 0) {
223 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
225 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
227 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
228 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
229 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
230 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
231 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
232 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
233 ((result) ? AOP_SIZE(result) : 0));
236 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
239 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
241 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
242 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
243 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
244 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
245 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
246 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
250 void pic16_emitpcomment (char *fmt, ...)
253 char lb[INITIAL_INLINEASM];
254 unsigned char *lbp = (unsigned char *)lb;
259 vsprintf(lb+1,fmt,ap);
261 while (isspace(*lbp)) lbp++;
264 lineCurr = (lineCurr ?
265 connectLine(lineCurr,newLineNode(lb)) :
266 (lineHead = newLineNode(lb)));
267 lineCurr->isInline = _G.inLine;
268 lineCurr->isDebug = _G.debugLine;
269 lineCurr->isComment = 1;
271 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
274 // fprintf(stderr, "%s\n", lb);
277 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
280 char lb[INITIAL_INLINEASM];
281 unsigned char *lbp = (unsigned char *)lb;
283 if(!pic16_debug_verbose)
290 sprintf(lb,"%s\t",inst);
292 sprintf(lb,"%s",inst);
293 vsprintf(lb+(strlen(lb)),fmt,ap);
297 while (isspace(*lbp)) lbp++;
300 lineCurr = (lineCurr ?
301 connectLine(lineCurr,newLineNode(lb)) :
302 (lineHead = newLineNode(lb)));
303 lineCurr->isInline = _G.inLine;
304 lineCurr->isDebug = _G.debugLine;
306 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
309 // fprintf(stderr, "%s\n", lb);
314 void pic16_emitpLabel(int key)
316 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
319 void pic16_emitpLabelFORCE(int key)
321 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
324 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
325 * NEVER call pic16_emitpcode_real directly, please... */
326 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
330 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
332 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
335 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
338 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
340 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
343 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
346 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
352 #define pic16_emitcode DEBUGpic16_emitcode
354 /*-----------------------------------------------------------------*/
355 /* pic16_emitcode - writes the code into a file : for now it is simple */
356 /*-----------------------------------------------------------------*/
357 void pic16_emitcode (char *inst,char *fmt, ...)
360 char lb[INITIAL_INLINEASM];
361 unsigned char *lbp = lb;
367 sprintf(lb,"%s\t",inst);
369 sprintf(lb,"%s",inst);
370 vsprintf(lb+(strlen(lb)),fmt,ap);
374 while (isspace(*lbp)) lbp++;
377 lineCurr = (lineCurr ?
378 connectLine(lineCurr,newLineNode(lb)) :
379 (lineHead = newLineNode(lb)));
380 lineCurr->isInline = _G.inLine;
381 lineCurr->isDebug = _G.debugLine;
382 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
383 lineCurr->isComment = (*lbp == ';');
385 // VR fprintf(stderr, "lb = <%s>\n", lbp);
387 // if(pic16_debug_verbose)
388 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
395 /*-----------------------------------------------------------------*/
396 /* pic16_emitDebuggerSymbol - associate the current code location */
397 /* with a debugger symbol */
398 /*-----------------------------------------------------------------*/
400 pic16_emitDebuggerSymbol (char * debugSym)
403 pic16_emitcode (";", "%s ==.", debugSym);
408 /*-----------------------------------------------------------------*/
409 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
410 /*-----------------------------------------------------------------*/
411 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
413 // bool r0iu = FALSE , r1iu = FALSE;
414 // bool r0ou = FALSE , r1ou = FALSE;
415 bool fsr0iu = FALSE, fsr0ou;
416 bool fsr2iu = FALSE, fsr2ou;
418 //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result);
421 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
422 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
424 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
425 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
427 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
428 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
429 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
432 if(!fsr0iu && !fsr0ou) {
433 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
434 (*aopp)->type = AOP_FSR0;
436 //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
438 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
442 /* no usage of FSR2 */
443 if(!fsr2iu && !fsr2ou) {
444 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
445 (*aopp)->type = AOP_FSR2;
447 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
451 /* now we know they both have usage */
452 /* if fsr0 not used in this instruction */
454 if (!_G.fsr0Pushed) {
455 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
456 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
460 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
461 (*aopp)->type = AOP_FSR0;
463 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
465 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
469 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
474 /* the logic: if r0 & r1 used in the instruction
475 then we are in trouble otherwise */
477 /* first check if r0 & r1 are used by this
478 instruction, in which case we are in trouble */
479 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
480 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
485 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
486 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
488 /* if no usage of r0 then return it */
489 if (!r0iu && !r0ou) {
490 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
491 (*aopp)->type = AOP_R0;
493 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
496 /* if no usage of r1 then return it */
497 if (!r1iu && !r1ou) {
498 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
499 (*aopp)->type = AOP_R1;
501 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
504 /* now we know they both have usage */
505 /* if r0 not used in this instruction */
507 /* push it if not already pushed */
509 //pic16_emitcode ("push","%s",
510 // pic16_regWithIdx(R0_IDX)->dname);
514 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
515 (*aopp)->type = AOP_R0;
517 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
520 /* if r1 not used then */
523 /* push it if not already pushed */
525 //pic16_emitcode ("push","%s",
526 // pic16_regWithIdx(R1_IDX)->dname);
530 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
531 (*aopp)->type = AOP_R1;
532 return pic16_regWithIdx(R1_IDX);
536 /* I said end of world but not quite end of world yet */
537 /* if this is a result then we can push it on the stack*/
539 (*aopp)->type = AOP_STK;
543 /* other wise this is true end of the world */
544 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
545 "getFreePtr should never reach here");
550 /*-----------------------------------------------------------------*/
551 /* newAsmop - creates a new asmOp */
552 /*-----------------------------------------------------------------*/
553 static asmop *newAsmop (short type)
557 aop = Safe_calloc(1,sizeof(asmop));
562 static void genSetDPTR(int n)
566 pic16_emitcode(";", "Select standard DPTR");
567 pic16_emitcode("mov", "dps, #0x00");
571 pic16_emitcode(";", "Select alternate DPTR");
572 pic16_emitcode("mov", "dps, #0x01");
576 /*-----------------------------------------------------------------*/
577 /* resolveIfx - converts an iCode ifx into a form more useful for */
578 /* generating code */
579 /*-----------------------------------------------------------------*/
580 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
584 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
590 resIfx->condition = 1; /* assume that the ifx is true */
591 resIfx->generated = 0; /* indicate that the ifx has not been used */
594 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
597 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
598 __FUNCTION__,__LINE__,resIfx->lbl->key);
603 resIfx->lbl = IC_TRUE(ifx);
605 resIfx->lbl = IC_FALSE(ifx);
606 resIfx->condition = 0;
611 DEBUGpic16_emitcode("; +++","ifx true is non-null");
613 DEBUGpic16_emitcode("; +++","ifx true is null");
615 DEBUGpic16_emitcode("; +++","ifx false is non-null");
617 DEBUGpic16_emitcode("; +++","ifx false is null");
621 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
625 /*-----------------------------------------------------------------*/
626 /* pointerCode - returns the code for a pointer type */
627 /*-----------------------------------------------------------------*/
628 static int pointerCode (sym_link *etype)
631 return PTR_TYPE(SPEC_OCLS(etype));
636 /*-----------------------------------------------------------------*/
637 /* aopForSym - for a true symbol */
638 /*-----------------------------------------------------------------*/
639 static asmop *aopForSym (iCode *ic, operand *op, bool result)
641 symbol *sym=OP_SYMBOL(op);
643 memmap *space= SPEC_OCLS(sym->etype);
647 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
649 // sym = OP_SYMBOL(op);
651 /* if already has one */
653 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
658 /* if symbol was initially placed onStack then we must re-place it
659 * to direct memory, since pic16 does not have a specific stack */
661 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
669 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
671 sym->aop = aop = newAsmop (AOP_PAGED);
672 aop->aopu.aop_dir = sym->rname ;
673 aop->size = getSize(sym->type);
674 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
675 pic16_allocDirReg( IC_LEFT(ic) );
683 /* assign depending on the storage class */
684 /* if it is on the stack or indirectly addressable */
685 /* space we need to assign either r0 or r1 to it */
686 if (sym->onStack) // || sym->iaccess)
691 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
692 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
694 /* acquire a temporary register -- it is saved in function */
696 sym->aop = aop = newAsmop(AOP_STA);
697 aop->aopu.stk.stk = sym->stack;
698 aop->size = getSize(sym->type);
701 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
702 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
703 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
704 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
706 for(i=0;i<aop->size;i++)
707 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
708 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
710 if(1 && ic->op == SEND) {
712 /* if SEND do the send here */
715 // debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
716 for(i=0;i<aop->size;i++) {
717 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
718 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
723 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
726 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
728 // we do not need to load the value if it is to be defined...
729 if (result) return aop;
732 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
735 for(i=0;i<aop->size;i++) {
737 /* initialise for stack access via frame pointer */
738 // operands on stack are accessible via "{FRAME POINTER} + index" with index
739 // starting at 2 for arguments and growing from 0 downwards for
740 // local variables (index == 0 is not assigned so we add one here)
742 int soffs = sym->stack;
748 if(1 && ic->op == SEND) {
749 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
750 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751 pic16_popCopyReg( pic16_frame_plusw ),
752 pic16_popCopyReg(pic16_stack_postdec )));
754 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
755 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
756 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
762 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
769 /* now assign the address of the variable to
770 the pointer register */
771 if (aop->type != AOP_STK) {
775 pic16_emitcode("push","acc");
777 pic16_emitcode("mov","a,_bp");
778 pic16_emitcode("add","a,#0x%02x",
780 ((char)(sym->stack - _G.nRegsSaved )) :
781 ((char)sym->stack)) & 0xff);
782 pic16_emitcode("mov","%s,a",
783 aop->aopu.aop_ptr->name);
786 pic16_emitcode("pop","acc");
788 pic16_emitcode("mov","%s,#%s",
789 aop->aopu.aop_ptr->name,
791 aop->paged = space->paged;
793 aop->aopu.aop_stk = sym->stack;
801 if (sym->onStack && options.stack10bit)
803 /* It's on the 10 bit stack, which is located in
807 //DEBUGpic16_emitcode(";","%d",__LINE__);
810 pic16_emitcode("push","acc");
812 pic16_emitcode("mov","a,_bp");
813 pic16_emitcode("add","a,#0x%02x",
815 ((char)(sym->stack - _G.nRegsSaved )) :
816 ((char)sym->stack)) & 0xff);
819 pic16_emitcode ("mov","dpx1,#0x40");
820 pic16_emitcode ("mov","dph1,#0x00");
821 pic16_emitcode ("mov","dpl1, a");
825 pic16_emitcode("pop","acc");
827 sym->aop = aop = newAsmop(AOP_DPTR2);
828 aop->size = getSize(sym->type);
834 /* special case for a function */
835 if (IS_FUNC(sym->type)) {
836 sym->aop = aop = newAsmop(AOP_PCODE);
837 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
838 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
839 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
840 PCOI(aop->aopu.pcop)->index = 0;
841 aop->size = FPTRSIZE;
842 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
849 //DEBUGpic16_emitcode(";","%d",__LINE__);
850 /* if in bit space */
851 if (IN_BITSPACE(space)) {
852 sym->aop = aop = newAsmop (AOP_CRY);
853 aop->aopu.aop_dir = sym->rname ;
854 aop->size = getSize(sym->type);
855 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
858 /* if it is in direct space */
859 if (IN_DIRSPACE(space)) {
860 if(!strcmp(sym->rname, "_WREG")) {
861 sym->aop = aop = newAsmop (AOP_ACC);
862 aop->size = getSize(sym->type); /* should always be 1 */
863 assert(aop->size == 1);
864 DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
867 sym->aop = aop = newAsmop (AOP_DIR);
868 aop->aopu.aop_dir = sym->rname ;
869 aop->size = getSize(sym->type);
870 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
871 pic16_allocDirReg( IC_LEFT(ic) );
876 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
877 sym->aop = aop = newAsmop (AOP_DIR);
878 aop->aopu.aop_dir = sym->rname ;
879 aop->size = getSize(sym->type);
880 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
881 pic16_allocDirReg( IC_LEFT(ic) );
886 /* only remaining is far space */
887 sym->aop = aop = newAsmop(AOP_PCODE);
889 /* change the next if to 1 to revert to good old immediate code */
890 if(IN_CODESPACE(space)) {
891 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
892 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
893 PCOI(aop->aopu.pcop)->index = 0;
895 /* try to allocate via direct register */
896 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
897 // aop->size = getSize( sym->type );
900 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
901 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
904 if(!pic16_allocDirReg (IC_LEFT(ic)))
908 if(IN_DIRSPACE( space ))
910 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
911 aop->size = FPTRSIZE;
912 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
913 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
914 else if(sym->onStack) {
917 if(SPEC_SCLS(sym->etype) == S_PDATA) {
918 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
919 aop->size = FPTRSIZE;
924 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
926 /* if it is in code space */
927 if (IN_CODESPACE(space))
933 /*-----------------------------------------------------------------*/
934 /* aopForRemat - rematerialzes an object */
935 /*-----------------------------------------------------------------*/
936 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
938 symbol *sym = OP_SYMBOL(op);
940 iCode *ic = NULL, *oldic;
941 asmop *aop = newAsmop(AOP_PCODE);
948 ic = sym->rematiCode;
950 if(IS_OP_POINTER(op)) {
951 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
954 // if(!result) /* fixme-vr */
958 // chat *iLine = printILine(ic);
959 // pic16_emitpcomment("ic: %s\n", iLine);
963 val += (int) operandLitValue(IC_RIGHT(ic));
964 } else if (ic->op == '-') {
965 val -= (int) operandLitValue(IC_RIGHT(ic));
969 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
972 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
975 if(!op->isaddr)viaimmd++; else viaimmd=0;
977 /* set the following if to 1 to revert to good old immediate code */
978 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
981 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
983 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
986 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
988 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
991 PCOI(aop->aopu.pcop)->index = val;
993 aop->size = getSize( sym->type );
995 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
997 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
998 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
1000 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
1004 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1005 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1007 val, IS_PTR_CONST(operandType(op)));
1009 val, IS_CODEPTR(operandType(op)));
1012 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1014 pic16_allocDirReg (IC_LEFT(ic));
1016 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1023 static int aopIdx (asmop *aop, int offset)
1028 if(aop->type != AOP_REG)
1031 return aop->aopu.aop_reg[offset]->rIdx;
1036 /*-----------------------------------------------------------------*/
1037 /* regsInCommon - two operands have some registers in common */
1038 /*-----------------------------------------------------------------*/
1039 static bool regsInCommon (operand *op1, operand *op2)
1041 symbol *sym1, *sym2;
1044 /* if they have registers in common */
1045 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1048 sym1 = OP_SYMBOL(op1);
1049 sym2 = OP_SYMBOL(op2);
1051 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1054 for (i = 0 ; i < sym1->nRegs ; i++) {
1059 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1063 if (sym2->regs[j] == sym1->regs[i])
1071 /*-----------------------------------------------------------------*/
1072 /* operandsEqu - equivalent */
1073 /*-----------------------------------------------------------------*/
1074 static bool operandsEqu ( operand *op1, operand *op2)
1076 symbol *sym1, *sym2;
1078 /* if they not symbols */
1079 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1082 sym1 = OP_SYMBOL(op1);
1083 sym2 = OP_SYMBOL(op2);
1085 /* if both are itemps & one is spilt
1086 and the other is not then false */
1087 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1088 sym1->isspilt != sym2->isspilt )
1091 /* if they are the same */
1095 if (sym1->rname[0] && sym2->rname[0]
1096 && strcmp (sym1->rname, sym2->rname) == 0)
1100 /* if left is a tmp & right is not */
1101 if (IS_ITEMP(op1) &&
1104 (sym1->usl.spillLoc == sym2))
1107 if (IS_ITEMP(op2) &&
1111 (sym2->usl.spillLoc == sym1))
1117 /*-----------------------------------------------------------------*/
1118 /* pic16_sameRegs - two asmops have the same registers */
1119 /*-----------------------------------------------------------------*/
1120 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1127 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1128 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1130 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1132 if (aop1->type != AOP_REG ||
1133 aop2->type != AOP_REG )
1136 /* This is a bit too restrictive if one is a subset of the other...
1137 if (aop1->size != aop2->size )
1141 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1142 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1144 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1145 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1152 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1154 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1155 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1157 if(aop1 == aop2)return TRUE;
1158 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1160 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1166 /*-----------------------------------------------------------------*/
1167 /* pic16_aopOp - allocates an asmop for an operand : */
1168 /*-----------------------------------------------------------------*/
1169 void pic16_aopOp (operand *op, iCode *ic, bool result)
1178 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1180 /* if this a literal */
1181 if (IS_OP_LITERAL(op)) {
1182 op->aop = aop = newAsmop(AOP_LIT);
1183 aop->aopu.aop_lit = op->operand.valOperand;
1184 aop->size = getSize(operandType(op));
1189 sym_link *type = operandType(op);
1191 if(IS_PTR_CONST(type))
1193 if(IS_CODEPTR(type))
1195 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1198 /* if already has a asmop then continue */
1202 /* if the underlying symbol has a aop */
1203 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1204 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1205 op->aop = OP_SYMBOL(op)->aop;
1209 /* if this is a true symbol */
1210 if (IS_TRUE_SYMOP(op)) {
1211 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1212 op->aop = aopForSym(ic, op, result);
1216 /* this is a temporary : this has
1222 e) can be a return use only */
1224 sym = OP_SYMBOL(op);
1226 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1227 /* if the type is a conditional */
1228 if (sym->regType == REG_CND) {
1229 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1234 /* if it is spilt then two situations
1236 b) has a spill location */
1237 if (sym->isspilt || sym->nRegs == 0) {
1239 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1240 DEBUGpic16_emitcode(";","%d",__LINE__);
1241 /* rematerialize it NOW */
1244 sym->aop = op->aop = aop = aopForRemat (op, result);
1245 // aop->size = getSize(sym->type);
1246 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1253 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1254 aop->size = getSize(sym->type);
1255 for ( i = 0 ; i < 1 ; i++ ) {
1256 aop->aopu.aop_str[i] = accUse[i];
1257 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1259 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1260 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1268 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1269 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1270 //pic16_allocDirReg (IC_LEFT(ic));
1271 aop->size = getSize(sym->type);
1276 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1277 aop->size = getSize(sym->type);
1278 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1279 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1281 DEBUGpic16_emitcode(";","%d",__LINE__);
1285 /* else spill location */
1286 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1287 /* force a new aop if sizes differ */
1288 sym->usl.spillLoc->aop = NULL;
1292 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1293 __FUNCTION__,__LINE__,
1294 sym->usl.spillLoc->rname,
1295 sym->rname, sym->usl.spillLoc->offset);
1298 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1299 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1300 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1301 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1303 sym->usl.spillLoc->offset, op);
1304 } else if (getSize(sym->type) <= 1) {
1305 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1306 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1307 assert (getSize(sym->type) <= 1);
1308 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1309 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1311 /* We need some kind of dummy area for getSize(sym->type) byte,
1312 * use WREG for all storage locations.
1313 * XXX: This only works if we are implementing a `dummy read',
1314 * the stored value will not be retrievable...
1315 * See #1503234 for a case requiring this. */
1316 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1317 aop->size = getSize(sym->type);
1318 for ( i = 0 ; i < aop->size ;i++)
1319 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1321 aop->size = getSize(sym->type);
1327 sym_link *type = operandType(op);
1329 if(IS_PTR_CONST(type))
1331 if(IS_CODEPTR(type))
1333 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1336 /* must be in a register */
1337 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1338 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1339 aop->size = sym->nRegs;
1340 for ( i = 0 ; i < sym->nRegs ;i++)
1341 aop->aopu.aop_reg[i] = sym->regs[i];
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_freeAsmop - free up the asmop given to an operand */
1346 /*----------------------------------------------------------------*/
1347 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1364 /* depending on the asmop type only three cases need work AOP_RO
1365 , AOP_R1 && AOP_STK */
1367 switch (aop->type) {
1369 if (_G.fsr0Pushed ) {
1371 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1372 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1373 // pic16_emitcode ("pop","ar0");
1377 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1381 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1387 pic16_emitcode ("pop","ar0");
1391 bitVectUnSetBit(ic->rUsed,R0_IDX);
1397 pic16_emitcode ("pop","ar1");
1401 bitVectUnSetBit(ic->rUsed,R1_IDX);
1408 /* we must store the result on stack */
1409 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1410 // operands on stack are accessible via "FSR2 + index" with index
1411 // starting at 2 for arguments and growing from 0 downwards for
1412 // local variables (index == 0 is not assigned so we add one here)
1413 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1418 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1419 for(i=0;i<aop->size;i++) {
1420 /* initialise for stack access via frame pointer */
1421 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1422 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1423 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1426 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1430 for(i=0;i<aop->size;i++) {
1431 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1433 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1434 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1435 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1442 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1443 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1444 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1445 deleteSetItem( &_G.sregsAllocSet, sr );
1456 int stk = aop->aopu.aop_stk + aop->size;
1457 bitVectUnSetBit(ic->rUsed,R0_IDX);
1458 bitVectUnSetBit(ic->rUsed,R1_IDX);
1460 getFreePtr(ic,&aop,FALSE);
1462 if (options.stack10bit)
1464 /* I'm not sure what to do here yet... */
1467 "*** Warning: probably generating bad code for "
1468 "10 bit stack mode.\n");
1472 pic16_emitcode ("mov","a,_bp");
1473 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1474 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1476 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1480 pic16_emitcode("pop","acc");
1481 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1483 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1486 pic16_freeAsmop(op,NULL,ic,TRUE);
1488 pic16_emitcode("pop","ar0");
1493 pic16_emitcode("pop","ar1");
1503 /* all other cases just dealloc */
1507 OP_SYMBOL(op)->aop = NULL;
1508 /* if the symbol has a spill */
1510 SPIL_LOC(op)->aop = NULL;
1515 /*-----------------------------------------------------------------*/
1516 /* pic16_aopGet - for fetching value of the aop */
1517 /*-----------------------------------------------------------------*/
1518 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1523 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1525 /* offset is greater than size then zero */
1526 if (offset > (aop->size - 1) &&
1527 aop->type != AOP_LIT)
1530 /* depending on type */
1531 switch (aop->type) {
1535 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1536 rs = Safe_calloc(1, strlen(s)+1);
1541 /* if we need to increment it */
1542 while (offset > aop->coff)
1544 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1548 while (offset < aop->coff)
1550 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1556 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1557 return (dname ? "acc" : "a");
1559 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1560 rs = Safe_calloc (1, strlen (s) + 1);
1568 sprintf (s,"%s",aop->aopu.aop_immd);
1571 sprintf(s,"(%s >> %d)",
1576 aop->aopu.aop_immd);
1577 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1578 rs = Safe_calloc(1,strlen(s)+1);
1584 sprintf(s,"(%s + %d)",
1587 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1589 sprintf(s,"%s",aop->aopu.aop_dir);
1590 rs = Safe_calloc(1,strlen(s)+1);
1595 return aop->aopu.aop_reg[offset]->name;
1598 return aop->aopu.aop_dir;
1601 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1602 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1604 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1605 rs = Safe_strdup("WREG");
1609 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1610 rs = Safe_calloc(1,strlen(s)+1);
1615 aop->coff = offset ;
1617 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1620 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1621 aop->type = AOP_ACC;
1622 return Safe_strdup("_WREG");
1624 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1626 return aop->aopu.aop_str[offset];
1630 pCodeOp *pcop = aop->aopu.pcop;
1631 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1633 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1634 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1636 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1638 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1641 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1644 rs = Safe_calloc(1,strlen(s)+1);
1650 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1652 sprintf(s,"(%s + %d)",
1656 sprintf(s,"%s",aop->aopu.aop_dir);
1657 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1658 rs = Safe_calloc(1,strlen(s)+1);
1664 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1668 // pCodeOp *pcop = aop->aop
1673 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1674 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1675 "aopget got unsupported aop->type");
1681 /* lock has the following meaning: When allocating temporary registers
1682 * for stack variables storage, the value of the temporary register is
1683 * saved on stack. Its value is restored at the end. This procedure is
1684 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1685 * a possibility that before a call to pic16_aopOp, a temporary register
1686 * is allocated for a while and it is freed after some time, this will
1687 * mess the stack and values will not be restored properly. So use lock=1
1688 * to allocate temporary registers used internally by the programmer, and
1689 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1690 * to inform the compiler developer about a possible bug. This is an internal
1691 * feature for developing the compiler -- VR */
1693 int _TempReg_lock = 0;
1694 /*-----------------------------------------------------------------*/
1695 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1696 /*-----------------------------------------------------------------*/
1697 pCodeOp *pic16_popGetTempReg(int lock)
1702 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1704 // werror(W_POSSBUG2, __FILE__, __LINE__);
1707 _TempReg_lock += lock;
1717 /* this code might seem better but it does the *same* job with
1718 * the old code, it all depends on ralloc.c to get a free/unused
1722 while(i < pic16_nRegs) {
1723 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1724 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1725 if((!rr || (rr && rr->isFree))
1726 && !bitVectBitValue(cfunc->regsUsed, i)) {
1727 pcop = pic16_newpCodeOpReg( i );
1728 PCOR(pcop)->r->wasUsed = 1;
1729 PCOR(pcop)->r->isFree = 0;
1736 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1740 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1741 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1742 PCOR(pcop)->r->wasUsed=1;
1743 PCOR(pcop)->r->isFree=0;
1745 /* push value on stack */
1746 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1755 /*-----------------------------------------------------------------*/
1756 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1757 /* is not part of f, but don't save if */
1759 /*-----------------------------------------------------------------*/
1760 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1766 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1769 // werror(W_POSSBUG2, __FILE__, __LINE__);
1772 _TempReg_lock += lock;
1777 i = bitVectFirstBit(f);
1780 /* bypass registers that are used by function */
1781 if(!bitVectBitValue(f, i)) {
1783 /* bypass registers that are already allocated for stack access */
1784 if(!bitVectBitValue(v, i)) {
1786 // debugf("getting register rIdx = %d\n", i);
1787 /* ok, get the operand */
1788 pcop = pic16_newpCodeOpReg( i );
1790 /* should never by NULL */
1791 assert( pcop != NULL );
1795 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1798 PCOR(pcop)->r->wasUsed=1;
1799 PCOR(pcop)->r->isFree=0;
1805 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1807 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1808 /* already used in previous steps, break */
1815 /* caller takes care of the following */
1816 // bitVectSetBit(v, i);
1819 /* push value on stack */
1820 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1821 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1839 /*-----------------------------------------------------------------*/
1840 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1844 _TempReg_lock -= lock;
1846 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1847 PCOR(pcop)->r->isFree = 1;
1849 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popGetLabel(int key)
1858 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1863 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1866 /*-----------------------------------------------------------------*/
1867 /* pic16_popCopyReg - copy a pcode operator */
1868 /*-----------------------------------------------------------------*/
1869 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1873 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1874 memcpy (pcor, pc, sizeof (pCodeOpReg));
1875 pcor->r->wasUsed = 1;
1877 //pcor->pcop.type = pc->pcop.type;
1879 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1880 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1882 pcor->pcop.name = NULL;
1885 //pcor->rIdx = pc->rIdx;
1886 //pcor->r->wasUsed=1;
1887 //pcor->instance = pc->instance;
1889 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit - asm operator to pcode operator conversion */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit(int lit)
1899 return pic16_newpCodeOpLit(lit);
1902 /* Allow for 12 bit literals (LFSR x, <here!>). */
1903 pCodeOp *pic16_popGetLit12(int lit)
1905 return pic16_newpCodeOpLit12(lit);
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1910 /*-----------------------------------------------------------------*/
1911 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1913 return pic16_newpCodeOpLit2(lit, arg2);
1917 /*-----------------------------------------------------------------*/
1918 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1919 /*-----------------------------------------------------------------*/
1920 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1922 return pic16_newpCodeOpImmd(name, offset,index, 0);
1926 /*-----------------------------------------------------------------*/
1927 /* pic16_popGet - asm operator to pcode operator conversion */
1928 /*-----------------------------------------------------------------*/
1929 pCodeOp *pic16_popGetWithString(char *str)
1935 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1939 pcop = pic16_newpCodeOp(str,PO_STR);
1944 /*-----------------------------------------------------------------*/
1945 /* pic16_popRegFromString - */
1946 /*-----------------------------------------------------------------*/
1947 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1950 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1951 pcop->type = PO_DIR;
1953 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1954 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1959 pcop->name = Safe_calloc(1,strlen(str)+1);
1960 strcpy(pcop->name,str);
1962 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1964 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1965 // PCOR(pcop)->r->wasUsed = 1;
1967 /* make sure that register doesn't exist,
1968 * and operand isn't NULL
1969 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1970 if((PCOR(pcop)->r == NULL)
1972 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1973 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1974 // __FUNCTION__, __LINE__, str, size, offset);
1976 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1977 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1980 PCOR(pcop)->instance = offset;
1985 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1989 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1990 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1992 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1993 PCOR(pcop)->rIdx = rIdx;
1994 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1996 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1998 PCOR(pcop)->r->isFree = 0;
1999 PCOR(pcop)->r->wasUsed = 1;
2001 pcop->type = PCOR(pcop)->r->pc_type;
2006 /*---------------------------------------------------------------------------------*/
2007 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2009 /*---------------------------------------------------------------------------------*/
2010 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2012 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2013 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2019 /*--------------------------------------------------------------------------------.-*/
2020 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2021 /* VR 030601 , adapted by Hans Dorn */
2022 /*--------------------------------------------------------------------------------.-*/
2023 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2026 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2030 /*---------------------------------------------------------------------------------*/
2031 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2032 /* movff instruction */
2033 /*---------------------------------------------------------------------------------*/
2034 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2036 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2037 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2043 /*-----------------------------------------------------------------*/
2044 /* pic16_popGet - asm operator to pcode operator conversion */
2045 /*-----------------------------------------------------------------*/
2046 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2048 // char *s = buffer ;
2054 /* offset is greater than size then zero */
2056 // if (offset > (aop->size - 1) &&
2057 // aop->type != AOP_LIT)
2058 // return NULL; //zero;
2060 /* depending on type */
2061 switch (aop->type) {
2066 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2067 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2073 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2074 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2075 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2076 PCOR(pcop)->r->wasUsed = 1;
2077 PCOR(pcop)->r->isFree = 0;
2079 PCOR(pcop)->instance = offset;
2080 pcop->type = PCOR(pcop)->r->pc_type;
2084 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2085 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2088 /* pCodeOp is already allocated from aopForSym */
2089 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2090 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2095 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2097 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2099 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2101 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2102 PCOR(pcop)->rIdx = rIdx;
2103 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2104 PCOR(pcop)->r->wasUsed=1;
2105 PCOR(pcop)->r->isFree=0;
2107 PCOR(pcop)->instance = offset;
2108 pcop->type = PCOR(pcop)->r->pc_type;
2109 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2113 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2114 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2120 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2121 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2125 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2126 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2133 // debugf2("aop = %p\toffset = %d\n", aop, offset);
2134 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
2135 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2137 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2139 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2140 // pcop->type = PO_GPR_REGISTER;
2141 PCOR(pcop)->rIdx = rIdx;
2142 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2143 PCOR(pcop)->r->wasUsed=1;
2144 PCOR(pcop)->r->isFree=0;
2146 PCOR(pcop)->instance = offset;
2147 pcop->type = PCOR(pcop)->r->pc_type;
2149 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2150 // rs = aop->aopu.aop_reg[offset]->name;
2151 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2156 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2158 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2159 PCOR(pcop)->instance = offset;
2160 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2161 //if(PCOR(pcop)->r == NULL)
2162 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2166 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2167 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2170 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2171 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2174 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2175 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2176 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2177 pcop->type = PCOR(pcop)->r->pc_type;
2178 pcop->name = PCOR(pcop)->r->name;
2184 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2186 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2187 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2188 switch( aop->aopu.pcop->type ) {
2189 case PO_DIR: PCOR(pcop)->instance += offset; break;
2190 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2195 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2196 assert( 0 ); /* should never reach here */;
2201 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2202 "pic16_popGet got unsupported aop->type");
2205 /*-----------------------------------------------------------------*/
2206 /* pic16_aopPut - puts a string for a aop */
2207 /*-----------------------------------------------------------------*/
2208 void pic16_aopPut (asmop *aop, char *s, int offset)
2215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2217 if (aop->size && offset > ( aop->size - 1)) {
2218 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2219 "pic16_aopPut got offset > aop->size");
2223 /* will assign value to value */
2224 /* depending on where it is ofcourse */
2225 switch (aop->type) {
2228 sprintf(d,"(%s + %d)",
2229 aop->aopu.aop_dir,offset);
2230 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2233 sprintf(d,"%s",aop->aopu.aop_dir);
2236 DEBUGpic16_emitcode(";","%d",__LINE__);
2238 pic16_emitcode("movf","%s,w",s);
2239 pic16_emitcode("movwf","%s",d);
2242 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2243 if(offset >= aop->size) {
2244 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2247 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2250 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2257 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2258 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2261 strcmp(s,"r0") == 0 ||
2262 strcmp(s,"r1") == 0 ||
2263 strcmp(s,"r2") == 0 ||
2264 strcmp(s,"r3") == 0 ||
2265 strcmp(s,"r4") == 0 ||
2266 strcmp(s,"r5") == 0 ||
2267 strcmp(s,"r6") == 0 ||
2268 strcmp(s,"r7") == 0 )
2269 pic16_emitcode("mov","%s,%s ; %d",
2270 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2274 if(strcmp(s,"W")==0 )
2275 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2277 pic16_emitcode("movwf","%s",
2278 aop->aopu.aop_reg[offset]->name);
2280 if(strcmp(s,zero)==0) {
2281 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2283 } else if(strcmp(s,"W")==0) {
2284 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2285 pcop->type = PO_GPR_REGISTER;
2287 PCOR(pcop)->rIdx = -1;
2288 PCOR(pcop)->r = NULL;
2290 DEBUGpic16_emitcode(";","%d",__LINE__);
2291 pcop->name = Safe_strdup(s);
2292 pic16_emitpcode(POC_MOVFW,pcop);
2293 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2294 } else if(strcmp(s,one)==0) {
2295 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2296 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2298 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2306 if (aop->type == AOP_DPTR2)
2312 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2313 "pic16_aopPut writting to code space");
2317 while (offset > aop->coff) {
2319 pic16_emitcode ("inc","dptr");
2322 while (offset < aop->coff) {
2324 pic16_emitcode("lcall","__decdptr");
2329 /* if not in accumulater */
2332 pic16_emitcode ("movx","@dptr,a");
2334 if (aop->type == AOP_DPTR2)
2342 while (offset > aop->coff) {
2344 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2346 while (offset < aop->coff) {
2348 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2354 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2359 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2361 if (strcmp(s,"r0") == 0 ||
2362 strcmp(s,"r1") == 0 ||
2363 strcmp(s,"r2") == 0 ||
2364 strcmp(s,"r3") == 0 ||
2365 strcmp(s,"r4") == 0 ||
2366 strcmp(s,"r5") == 0 ||
2367 strcmp(s,"r6") == 0 ||
2368 strcmp(s,"r7") == 0 ) {
2370 sprintf(buffer,"a%s",s);
2371 pic16_emitcode("mov","@%s,%s",
2372 aop->aopu.aop_ptr->name,buffer);
2374 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2379 if (strcmp(s,"a") == 0)
2380 pic16_emitcode("push","acc");
2382 pic16_emitcode("push","%s",s);
2387 /* if bit variable */
2388 if (!aop->aopu.aop_dir) {
2389 pic16_emitcode("clr","a");
2390 pic16_emitcode("rlc","a");
2393 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2396 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2399 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2401 lbl = newiTempLabel(NULL);
2403 if (strcmp(s,"a")) {
2406 pic16_emitcode("clr","c");
2407 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2408 pic16_emitcode("cpl","c");
2409 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2410 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2417 if (strcmp(aop->aopu.aop_str[offset],s))
2418 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2423 if (!offset && (strcmp(s,"acc") == 0))
2426 if (strcmp(aop->aopu.aop_str[offset],s))
2427 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2431 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2432 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2433 // "pic16_aopPut got unsupported aop->type");
2439 /*-----------------------------------------------------------------*/
2440 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2441 /*-----------------------------------------------------------------*/
2442 void pic16_mov2w (asmop *aop, int offset)
2444 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2447 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2449 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2452 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2454 if(is_LitAOp(src)) {
2455 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2456 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2458 if(pic16_sameRegsOfs(src, dst, offset))return;
2459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2460 pic16_popGet(dst, offset)));
2464 static void pic16_movLit2f(pCodeOp *pc, int lit)
2466 if (0 == (lit & 0x00ff))
2468 pic16_emitpcode (POC_CLRF, pc);
2469 } else if (0xff == (lit & 0x00ff))
2471 pic16_emitpcode (POC_SETF, pc);
2473 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2474 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2478 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2480 if(is_LitAOp(src)) {
2481 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2482 pic16_emitpcode(POC_MOVWF, dst);
2484 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2488 void pic16_testStackOverflow(void)
2490 #define GSTACK_TEST_NAME "_gstack_test"
2492 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2497 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2498 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2499 // strcpy(sym->rname, GSTACK_TEST_NAME);
2500 checkAddSym(&externs, sym);
2505 /* push pcop into stack */
2506 void pic16_pushpCodeOp(pCodeOp *pcop)
2508 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2509 if (pcop->type == PO_LITERAL) {
2510 pic16_emitpcode(POC_MOVLW, pcop);
2511 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2513 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2515 if(pic16_options.gstack)
2516 pic16_testStackOverflow();
2520 /* pop pcop from stack */
2521 void pic16_poppCodeOp(pCodeOp *pcop)
2523 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2524 if(pic16_options.gstack)
2525 pic16_testStackOverflow();
2529 /*-----------------------------------------------------------------*/
2530 /* pushw - pushes wreg to stack */
2531 /*-----------------------------------------------------------------*/
2534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2536 if(pic16_options.gstack)
2537 pic16_testStackOverflow();
2541 /*-----------------------------------------------------------------*/
2542 /* pushaop - pushes aop to stack */
2543 /*-----------------------------------------------------------------*/
2544 void pushaop(asmop *aop, int offset)
2546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2548 if(_G.resDirect)return;
2550 if(is_LitAOp(aop)) {
2551 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2552 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2554 pic16_emitpcode(POC_MOVFF,
2555 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2558 if(pic16_options.gstack)
2559 pic16_testStackOverflow();
2562 /*-----------------------------------------------------------------*/
2563 /* popaop - pops aop from stack */
2564 /*-----------------------------------------------------------------*/
2565 void popaop(asmop *aop, int offset)
2567 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2568 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2569 if(pic16_options.gstack)
2570 pic16_testStackOverflow();
2573 void popaopidx(asmop *aop, int offset, int index)
2577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2579 if(STACK_MODEL_LARGE)ofs++;
2581 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2582 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2583 if(pic16_options.gstack)
2584 pic16_testStackOverflow();
2587 #if !(USE_GENERIC_SIGNED_SHIFT)
2588 /*-----------------------------------------------------------------*/
2589 /* reAdjustPreg - points a register back to where it should */
2590 /*-----------------------------------------------------------------*/
2591 static void reAdjustPreg (asmop *aop)
2595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2597 if ((size = aop->size) <= 1)
2600 switch (aop->type) {
2604 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2608 if (aop->type == AOP_DPTR2)
2614 pic16_emitcode("lcall","__decdptr");
2617 if (aop->type == AOP_DPTR2)
2629 /*-----------------------------------------------------------------*/
2630 /* opIsGptr: returns non-zero if the passed operand is */
2631 /* a generic pointer type. */
2632 /*-----------------------------------------------------------------*/
2633 static int opIsGptr(operand *op)
2635 sym_link *type = operandType(op);
2637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2638 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2646 /*-----------------------------------------------------------------*/
2647 /* pic16_getDataSize - get the operand data size */
2648 /*-----------------------------------------------------------------*/
2649 int pic16_getDataSize(operand *op)
2651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2654 return AOP_SIZE(op);
2656 // tsd- in the pic port, the genptr size is 1, so this code here
2657 // fails. ( in the 8051 port, the size was 4).
2660 size = AOP_SIZE(op);
2661 if (size == GPTRSIZE)
2663 sym_link *type = operandType(op);
2664 if (IS_GENPTR(type))
2666 /* generic pointer; arithmetic operations
2667 * should ignore the high byte (pointer type).
2670 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2677 /*-----------------------------------------------------------------*/
2678 /* pic16_outAcc - output Acc */
2679 /*-----------------------------------------------------------------*/
2680 void pic16_outAcc(operand *result)
2683 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2684 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2687 size = pic16_getDataSize(result);
2689 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2692 /* unsigned or positive */
2694 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2699 /*-----------------------------------------------------------------*/
2700 /* pic16_outBitC - output a bit C */
2701 /* Move to result the value of Carry flag -- VR */
2702 /*-----------------------------------------------------------------*/
2703 void pic16_outBitC(operand *result)
2707 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2709 /* if the result is bit */
2710 if (AOP_TYPE(result) == AOP_CRY) {
2711 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2712 pic16_aopPut(AOP(result),"c",0);
2715 i = AOP_SIZE(result);
2717 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2719 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2723 /*-----------------------------------------------------------------*/
2724 /* pic16_outBitOp - output a bit from Op */
2725 /* Move to result the value of set/clr op -- VR */
2726 /*-----------------------------------------------------------------*/
2727 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2733 /* if the result is bit */
2734 if (AOP_TYPE(result) == AOP_CRY) {
2735 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2736 pic16_aopPut(AOP(result),"c",0);
2739 i = AOP_SIZE(result);
2741 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2743 pic16_emitpcode(POC_RRCF, pcop);
2744 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2748 /*-----------------------------------------------------------------*/
2749 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2750 /*-----------------------------------------------------------------*/
2751 void pic16_toBoolean(operand *oper)
2753 int size = AOP_SIZE(oper) - 1;
2756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2758 if ( AOP_TYPE(oper) != AOP_ACC) {
2759 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2762 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2766 /*-----------------------------------------------------------------*/
2767 /* genUminusFloat - unary minus for floating points */
2768 /*-----------------------------------------------------------------*/
2769 static void genUminusFloat(operand *op,operand *result)
2771 int size ,offset =0 ;
2774 /* for this we just need to flip the
2775 first it then copy the rest in place */
2776 size = AOP_SIZE(op);
2777 assert( size == AOP_SIZE(result) );
2780 pic16_mov2f(AOP(result), AOP(op), offset);
2784 /* toggle the MSB's highest bit */
2785 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2788 /*-----------------------------------------------------------------*/
2789 /* genUminus - unary minus code generation */
2790 /*-----------------------------------------------------------------*/
2791 static void genUminus (iCode *ic)
2794 sym_link *optype, *rtype;
2801 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2802 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2804 /* if both in bit space then special case */
2805 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2806 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2808 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2809 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2810 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2814 optype = operandType(IC_LEFT(ic));
2815 rtype = operandType(IC_RESULT(ic));
2818 /* if float then do float stuff */
2819 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2820 if(IS_FIXED(optype))
2821 debugf("implement fixed16x16 type\n", 0);
2823 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2827 /* otherwise subtract from zero by taking the 2's complement */
2828 size = AOP_SIZE(IC_LEFT(ic));
2829 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2830 label = newiTempLabel ( NULL );
2832 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2833 for (i=size-1; i > 0; i--) {
2834 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2836 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2837 for (i=1; i < size; i++) {
2838 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2839 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2842 for (i=size-1; i >= 0; i--) {
2843 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2844 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2847 for (i=0; i < size-2; i++) {
2848 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2849 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2851 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2853 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2856 pic16_emitpLabel (label->key);
2859 /* release the aops */
2860 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2861 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2865 /*-----------------------------------------------------------------*/
2866 /* saveRegisters - will look for a call and save the registers */
2867 /*-----------------------------------------------------------------*/
2868 static void saveRegisters(iCode *lic)
2875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2877 for (ic = lic ; ic ; ic = ic->next)
2878 if (ic->op == CALL || ic->op == PCALL)
2882 fprintf(stderr,"found parameter push with no function call\n");
2886 /* if the registers have been saved already then
2888 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2891 /* find the registers in use at this time
2892 and push them away to safety */
2893 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2897 if (options.useXstack) {
2898 if (bitVectBitValue(rsave,R0_IDX))
2899 pic16_emitcode("mov","b,r0");
2900 pic16_emitcode("mov","r0,%s",spname);
2901 for (i = 0 ; i < pic16_nRegs ; i++) {
2902 if (bitVectBitValue(rsave,i)) {
2904 pic16_emitcode("mov","a,b");
2906 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2907 pic16_emitcode("movx","@r0,a");
2908 pic16_emitcode("inc","r0");
2911 pic16_emitcode("mov","%s,r0",spname);
2912 if (bitVectBitValue(rsave,R0_IDX))
2913 pic16_emitcode("mov","r0,b");
2915 //for (i = 0 ; i < pic16_nRegs ; i++) {
2916 // if (bitVectBitValue(rsave,i))
2917 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2920 dtype = operandType(IC_LEFT(ic));
2921 if (currFunc && dtype &&
2922 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2923 IFFUNC_ISISR(currFunc->type) &&
2926 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2929 /*-----------------------------------------------------------------*/
2930 /* unsaveRegisters - pop the pushed registers */
2931 /*-----------------------------------------------------------------*/
2932 static void unsaveRegisters (iCode *ic)
2937 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2938 /* find the registers in use at this time
2939 and push them away to safety */
2940 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2943 if (options.useXstack) {
2944 pic16_emitcode("mov","r0,%s",spname);
2945 for (i = pic16_nRegs ; i >= 0 ; i--) {
2946 if (bitVectBitValue(rsave,i)) {
2947 pic16_emitcode("dec","r0");
2948 pic16_emitcode("movx","a,@r0");
2950 pic16_emitcode("mov","b,a");
2952 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2956 pic16_emitcode("mov","%s,r0",spname);
2957 if (bitVectBitValue(rsave,R0_IDX))
2958 pic16_emitcode("mov","r0,b");
2960 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2961 // if (bitVectBitValue(rsave,i))
2962 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2969 /*-----------------------------------------------------------------*/
2971 /*-----------------------------------------------------------------*/
2972 static void pushSide(operand * oper, int size)
2975 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2977 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2978 if (AOP_TYPE(oper) != AOP_REG &&
2979 AOP_TYPE(oper) != AOP_DIR &&
2981 pic16_emitcode("mov","a,%s",l);
2982 pic16_emitcode("push","acc");
2984 pic16_emitcode("push","%s",l);
2989 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2991 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2992 pic16_emitpcode(POC_MOVFW, src);
2993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2995 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2996 src, pic16_popGet(AOP(op), offset)));
3001 /*-----------------------------------------------------------------*/
3002 /* assignResultValue - assign results to oper, rescall==1 is */
3003 /* called from genCall() or genPcall() */
3004 /*-----------------------------------------------------------------*/
3005 static void assignResultValue(operand * oper, int res_size, int rescall)
3007 int size = AOP_SIZE(oper);
3011 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3012 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3015 /* assign result from a call/pcall function() */
3017 /* function results are stored in a special order,
3018 * see top of file with Function return policy, or manual */
3021 /* 8-bits, result in WREG */
3022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3024 if(size > 1 && res_size > 1) {
3025 /* 16-bits, result in PRODL:WREG */
3026 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3029 if(size > 2 && res_size > 2) {
3030 /* 24-bits, result in PRODH:PRODL:WREG */
3031 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3034 if(size > 3 && res_size > 3) {
3035 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3036 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3039 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3042 /* >32-bits, result on stack, and FSR0 points to beginning.
3043 * Fix stack when done */
3045 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3047 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3048 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3050 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3055 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3056 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3057 if(STACK_MODEL_LARGE) {
3059 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3063 int areg = 0; /* matching argument register */
3065 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3066 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3069 /* its called from genReceive (probably) -- VR */
3070 /* I hope this code will not be called from somewhere else in the future!
3071 * We manually set the pseudo stack pointer in genReceive. - dw
3073 if(!GpsuedoStkPtr && _G.useWreg) {
3074 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3076 /* The last byte in the assignment is in W */
3077 if(areg <= GpsuedoStkPtr) {
3079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3081 // debugf("receive from WREG\n", 0);
3083 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3086 _G.stack_lat = AOP_SIZE(oper)-1;
3091 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3092 // debugf("receive from STACK\n", 0);
3099 /*-----------------------------------------------------------------*/
3100 /* genIpush - generate code for pushing this gets a little complex */
3101 /*-----------------------------------------------------------------*/
3102 static void genIpush (iCode *ic)
3104 // int size, offset=0;
3107 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3110 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3112 /* send to stack as normal */
3113 addSet(&_G.sendSet,ic);
3114 // addSetHead(&_G.sendSet,ic);
3115 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3120 int size, offset = 0 ;
3124 /* if this is not a parm push : ie. it is spill push
3125 and spill push is always done on the local stack */
3126 if (!ic->parmPush) {
3128 /* and the item is spilt then do nothing */
3129 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3132 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3133 size = AOP_SIZE(IC_LEFT(ic));
3134 /* push it on the stack */
3136 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3141 pic16_emitcode("push","%s",l);
3146 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3150 /*-----------------------------------------------------------------*/
3151 /* genIpop - recover the registers: can happen only for spilling */
3152 /*-----------------------------------------------------------------*/
3153 static void genIpop (iCode *ic)
3156 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3161 /* if the temp was not pushed then */
3162 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3165 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3166 size = AOP_SIZE(IC_LEFT(ic));
3169 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3172 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3177 /*-----------------------------------------------------------------*/
3178 /* unsaverbank - restores the resgister bank from stack */
3179 /*-----------------------------------------------------------------*/
3180 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3182 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3190 if (options.useXstack) {
3192 r = getFreePtr(ic,&aop,FALSE);
3195 pic16_emitcode("mov","%s,_spx",r->name);
3196 pic16_emitcode("movx","a,@%s",r->name);
3197 pic16_emitcode("mov","psw,a");
3198 pic16_emitcode("dec","%s",r->name);
3201 pic16_emitcode ("pop","psw");
3204 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3205 if (options.useXstack) {
3206 pic16_emitcode("movx","a,@%s",r->name);
3207 //pic16_emitcode("mov","(%s+%d),a",
3208 // regspic16[i].base,8*bank+regspic16[i].offset);
3209 pic16_emitcode("dec","%s",r->name);
3212 pic16_emitcode("pop",""); //"(%s+%d)",
3213 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3216 if (options.useXstack) {
3218 pic16_emitcode("mov","_spx,%s",r->name);
3219 pic16_freeAsmop(NULL,aop,ic,TRUE);
3225 /*-----------------------------------------------------------------*/
3226 /* saverbank - saves an entire register bank on the stack */
3227 /*-----------------------------------------------------------------*/
3228 static void saverbank (int bank, iCode *ic, bool pushPsw)
3230 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3236 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3237 if (options.useXstack) {
3240 r = getFreePtr(ic,&aop,FALSE);
3241 pic16_emitcode("mov","%s,_spx",r->name);
3245 for (i = 0 ; i < pic16_nRegs ;i++) {
3246 if (options.useXstack) {
3247 pic16_emitcode("inc","%s",r->name);
3248 //pic16_emitcode("mov","a,(%s+%d)",
3249 // regspic16[i].base,8*bank+regspic16[i].offset);
3250 pic16_emitcode("movx","@%s,a",r->name);
3252 pic16_emitcode("push","");// "(%s+%d)",
3253 //regspic16[i].base,8*bank+regspic16[i].offset);
3257 if (options.useXstack) {
3258 pic16_emitcode("mov","a,psw");
3259 pic16_emitcode("movx","@%s,a",r->name);
3260 pic16_emitcode("inc","%s",r->name);
3261 pic16_emitcode("mov","_spx,%s",r->name);
3262 pic16_freeAsmop (NULL,aop,ic,TRUE);
3265 pic16_emitcode("push","psw");
3267 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3275 static int wparamCmp(void *p1, void *p2)
3277 return (!strcmp((char *)p1, (char *)p2));
3280 int inWparamList(char *s)
3282 return isinSetWith(wparamList, s, wparamCmp);
3286 /*-----------------------------------------------------------------*/
3287 /* genCall - generates a call statement */
3288 /*-----------------------------------------------------------------*/
3289 static void genCall (iCode *ic)
3299 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3300 /* if caller saves & we have not saved then */
3301 // if (!ic->regsSaved)
3302 // saveRegisters(ic);
3304 /* initialise stackParms for IPUSH pushes */
3305 // stackParms = psuedoStkPtr;
3306 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3307 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3308 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3311 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3314 /* if send set is not empty the assign */
3317 int psuedoStkPtr=-1;
3318 int firstTimeThruLoop = 1;
3321 /* reverse sendSet if function is not reentrant */
3322 if(!IFFUNC_ISREENT(ftype))
3323 _G.sendSet = reverseSet(_G.sendSet);
3325 /* First figure how many parameters are getting passed */
3329 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3333 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3334 size = AOP_SIZE(IC_LEFT(sic));
3338 /* pass the last byte through WREG */
3342 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3343 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3344 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3346 if(!firstTimeThruLoop) {
3347 /* If this is not the first time we've been through the loop
3348 * then we need to save the parameter in a temporary
3349 * register. The last byte of the last parameter is
3353 // --psuedoStkPtr; // sanity check
3357 firstTimeThruLoop=0;
3359 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3364 /* all arguments are passed via stack */
3368 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3369 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3370 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3372 // pushaop(AOP(IC_LEFT(sic)), size);
3373 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3380 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3384 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3385 pushw(); /* save last parameter to stack if functions has varargs */
3389 } else use_wreg = 0;
3391 _G.stackRegSet = _G.sendSet;
3396 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3400 /* if we need to assign a result value */
3401 if ((IS_ITEMP(IC_RESULT(ic))
3402 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3403 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3404 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3407 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3410 /* Must not assign an 8-bit result to a 16-bit variable;
3411 * this would use (used...) the uninitialized PRODL! */
3412 /* FIXME: Need a proper way to obtain size of function result type,
3413 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3414 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3416 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3417 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3419 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3422 if(!stackParms && ic->parmBytes) {
3423 stackParms = ic->parmBytes;
3426 stackParms -= use_wreg;
3429 if(stackParms == 1) {
3430 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3432 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3433 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3435 if(STACK_MODEL_LARGE) {
3437 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3442 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3445 /* adjust the stack for parameters if required */
3446 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3449 /* if register bank was saved then pop them */
3451 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3453 /* if we hade saved some registers then unsave them */
3454 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3455 unsaveRegisters (ic);
3461 /*-----------------------------------------------------------------*/
3462 /* genPcall - generates a call by pointer statement */
3463 /* new version, created from genCall - HJD */
3464 /*-----------------------------------------------------------------*/
3465 static void genPcall (iCode *ic)
3469 symbol *retlbl = newiTempLabel(NULL);
3470 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3474 fntype = operandType( IC_LEFT(ic) )->next;
3476 /* if send set is not empty the assign */
3479 int psuedoStkPtr=-1;
3481 /* reverse sendSet if function is not reentrant */
3482 if(!IFFUNC_ISREENT(fntype))
3483 _G.sendSet = reverseSet(_G.sendSet);
3487 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3490 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3491 size = AOP_SIZE(IC_LEFT(sic));
3494 /* all parameters are passed via stack, since WREG is clobbered
3495 * by the calling sequence */
3497 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3499 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3501 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3505 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3508 _G.stackRegSet = _G.sendSet;
3512 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3514 // push return address
3515 // push $ on return stack, then replace with retlbl
3517 /* Thanks to Thorsten Klose for pointing out that the following
3518 * snippet should be interrupt safe */
3519 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3520 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3522 pic16_emitpcodeNULLop(POC_PUSH);
3524 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3525 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3526 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3527 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3528 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3529 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3532 /* restore interrupt control register */
3533 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3534 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3536 /* make the call by writing the pointer into pc */
3537 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3538 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3540 // note: MOVFF to PCL not allowed
3541 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3542 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3545 /* return address is here: (X) */
3546 pic16_emitpLabelFORCE(retlbl->key);
3548 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3551 /* if we need assign a result value */
3552 if ((IS_ITEMP(IC_RESULT(ic))
3553 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3554 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3555 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3558 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3561 /* FIXME: Need proper way to obtain the function result's type.
3562 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3563 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3565 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3566 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3568 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3571 // stackParms -= use_wreg;
3574 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3575 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3576 if(STACK_MODEL_LARGE) {
3578 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3583 /*-----------------------------------------------------------------*/
3584 /* resultRemat - result is rematerializable */
3585 /*-----------------------------------------------------------------*/
3586 static int resultRemat (iCode *ic)
3588 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3589 if (SKIP_IC(ic) || ic->op == IFX)
3592 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3593 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3594 if (sym->remat && !POINTER_SET(ic))
3601 #if defined(__BORLANDC__) || defined(_MSC_VER)
3602 #define STRCASECMP stricmp
3604 #define STRCASECMP strcasecmp
3608 /*-----------------------------------------------------------------*/
3609 /* inExcludeList - return 1 if the string is in exclude Reg list */
3610 /*-----------------------------------------------------------------*/
3611 static bool inExcludeList(char *s)
3613 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3617 if (options.excludeRegs[i] &&
3618 STRCASECMP(options.excludeRegs[i],"none") == 0)
3621 for ( i = 0 ; options.excludeRegs[i]; i++) {
3622 if (options.excludeRegs[i] &&
3623 STRCASECMP(s,options.excludeRegs[i]) == 0)
3630 /*-----------------------------------------------------------------*/
3631 /* genFunction - generated code for function entry */
3632 /*-----------------------------------------------------------------*/
3633 static void genFunction (iCode *ic)
3639 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3641 pic16_labelOffset += (max_key+4);
3646 ftype = operandType(IC_LEFT(ic));
3647 sym = OP_SYMBOL(IC_LEFT(ic));
3649 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3650 /* create an absolute section at the interrupt vector:
3651 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3656 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3658 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3659 sprintf(asymname, "ivec_%s", sym->name);
3661 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3663 /* when an interrupt is declared as naked, do not emit the special
3664 * wrapper segment at vector address. The user should take care for
3665 * this instead. -- VR */
3667 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3668 asym = newSymbol(asymname, 0);
3669 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3670 pic16_addpBlock( apb );
3672 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3673 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3674 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3675 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3676 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3678 /* mark the end of this tiny function */
3679 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3681 sprintf(asymname, "%s", sym->rname);
3687 abSym = Safe_calloc(1, sizeof(absSym));
3688 strcpy(abSym->name, asymname);
3690 switch( FUNC_INTNO(sym->type) ) {
3691 case 0: abSym->address = 0x000000; break;
3692 case 1: abSym->address = 0x000008; break;
3693 case 2: abSym->address = 0x000018; break;
3696 // fprintf(stderr, "no interrupt number is given\n");
3697 abSym->address = -1; break;
3700 /* relocate interrupt vectors if needed */
3701 if(abSym->address != -1)
3702 abSym->address += pic16_options.ivt_loc;
3704 addSet(&absSymSet, abSym);
3708 /* create the function header */
3709 pic16_emitcode(";","-----------------------------------------");
3710 pic16_emitcode(";"," function %s",sym->name);
3711 pic16_emitcode(";","-----------------------------------------");
3713 /* prevent this symbol from being emitted as 'extern' */
3714 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3716 pic16_emitcode("","%s:",sym->rname);
3717 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3722 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3723 if(!strcmp(ab->name, sym->rname)) {
3724 pic16_pBlockConvert2Absolute(pb);
3730 if(IFFUNC_ISNAKED(ftype)) {
3731 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3735 /* if critical function then turn interrupts off */
3736 if (IFFUNC_ISCRITICAL(ftype)) {
3737 //pic16_emitcode("clr","ea");
3740 currFunc = sym; /* update the currFunc symbol */
3741 _G.fregsUsed = sym->regsUsed;
3742 _G.sregsAlloc = newBitVect(128);
3745 /* if this is an interrupt service routine then
3746 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3747 if (IFFUNC_ISISR(sym->type)) {
3748 _G.usefastretfie = 1; /* use shadow registers by default */
3750 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3751 if(!FUNC_ISSHADOWREGS(sym->type)) {
3752 /* do not save WREG,STATUS,BSR for high priority interrupts
3753 * because they are stored in the hardware shadow registers already */
3754 _G.usefastretfie = 0;
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3760 /* these should really be optimized somehow, because not all
3761 * interrupt handlers modify them */
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3764 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3765 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3766 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3767 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3769 // pic16_pBlockConvert2ISR(pb);
3772 /* emit code to setup stack frame if user enabled,
3773 * and function is not main() */
3775 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3776 if(strcmp(sym->name, "main")) {
3778 || !options.ommitFramePtr
3780 || IFFUNC_ARGS(sym->type)
3781 || FUNC_HASSTACKPARM(sym->etype)
3783 /* setup the stack frame */
3784 if(STACK_MODEL_LARGE)
3785 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3786 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3788 if(STACK_MODEL_LARGE)
3789 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3790 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3794 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3797 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3799 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3800 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3802 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3805 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3806 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3813 /* if callee-save to be used for this function
3814 * then save the registers being used in this function */
3815 // if (IFFUNC_CALLEESAVES(sym->type))
3816 if(strcmp(sym->name, "main")) {
3819 /* if any registers used */
3820 if (sym->regsUsed) {
3821 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3824 /* save the registers used */
3825 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3826 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3827 if (bitVectBitValue(sym->regsUsed,i)) {
3829 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3831 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3834 if(!pic16_regWithIdx(i)->wasUsed) {
3835 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3836 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3837 pic16_regWithIdx(i)->wasUsed = 1;
3844 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3845 for(i=0;i<sym->regsUsed->size;i++) {
3846 if(bitVectBitValue(sym->regsUsed, i)) {
3851 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3854 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3859 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3860 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3863 /*-----------------------------------------------------------------*/
3864 /* genEndFunction - generates epilogue for functions */
3865 /*-----------------------------------------------------------------*/
3866 static void genEndFunction (iCode *ic)
3868 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3872 if(IFFUNC_ISNAKED(sym->type)) {
3873 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3879 /* add code for ISCRITICAL */
3880 if(IFFUNC_ISCRITICAL(sym->type)) {
3881 /* if critical function, turn on interrupts */
3883 /* TODO: add code here -- VR */
3886 // sym->regsUsed = _G.fregsUsed;
3888 /* now we need to restore the registers */
3889 /* if any registers used */
3891 /* first restore registers that might be used for stack access */
3892 if(_G.sregsAllocSet) {
3895 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3896 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3897 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3901 if (strcmp(sym->name, "main") && sym->regsUsed) {
3904 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3905 /* restore registers used */
3906 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3907 for ( i = sym->regsUsed->size; i >= 0; i--) {
3908 if (bitVectBitValue(sym->regsUsed,i)) {
3909 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3913 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3918 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3920 if (sym->stack == 1) {
3921 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3922 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3924 // we have to add more than one...
3925 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3926 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3927 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3929 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3930 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3931 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3935 if(strcmp(sym->name, "main")) {
3937 || !options.ommitFramePtr
3939 || IFFUNC_ARGS(sym->type)
3940 || FUNC_HASSTACKPARM(sym->etype)
3942 /* restore stack frame */
3943 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3944 if(STACK_MODEL_LARGE)
3945 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3951 if (IFFUNC_ISISR(sym->type)) {
3952 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3953 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3954 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3955 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3956 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3957 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3959 if(!FUNC_ISSHADOWREGS(sym->type)) {
3960 /* do not restore interrupt vector for WREG,STATUS,BSR
3961 * for high priority interrupt, see genFunction */
3962 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3963 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3964 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3966 // _G.interruptvector = 0; /* sanity check */
3969 /* if debug then send end of function */
3970 /* if (options.debug && currFunc) */
3972 debugFile->writeEndFunction (currFunc, ic, 1);
3975 if(_G.usefastretfie)
3976 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3978 pic16_emitpcodeNULLop(POC_RETFIE);
3980 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3982 _G.usefastretfie = 0;
3986 if (IFFUNC_ISCRITICAL(sym->type)) {
3987 pic16_emitcode("setb","ea");
3990 /* if debug then send end of function */
3992 debugFile->writeEndFunction (currFunc, ic, 1);
3995 /* insert code to restore stack frame, if user enabled it
3996 * and function is not main() */
3999 pic16_emitpcodeNULLop(POC_RETURN);
4001 /* Mark the end of a function */
4002 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4006 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4008 unsigned long lit=1;
4013 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4014 if(AOP_TYPE(op) == AOP_LIT) {
4015 if(!IS_FLOAT(operandType( op ))) {
4016 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4019 unsigned long lit_int;
4023 /* take care if literal is a float */
4024 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4029 if (AOP_TYPE(op) == AOP_LIT) {
4030 /* FIXME: broken for
4031 * char __at(0x456) foo;
4033 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4034 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4035 } else if (AOP_TYPE(op) == AOP_PCODE
4036 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4037 /* char *s= "aaa"; return s; */
4038 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4039 * that the generic pointer is interpreted correctly
4040 * as referring to __code space, but this is fragile! */
4041 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4042 /* XXX: should check that dest != WREG */
4043 pic16_emitpcode(POC_MOVWF, dest);
4045 if(dest->type == PO_WREG && (offset == 0)) {
4046 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4049 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4053 /*-----------------------------------------------------------------*/
4054 /* genRet - generate code for return statement */
4055 /*-----------------------------------------------------------------*/
4056 static void genRet (iCode *ic)
4062 /* if we have no return value then
4063 * just generate the "ret" */
4068 /* we have something to return then
4069 * move the return value into place */
4070 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4071 size = AOP_SIZE(IC_LEFT(ic));
4075 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4078 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4081 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4083 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4086 /* >32-bits, setup stack and FSR0 */
4088 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4089 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4091 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4093 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4098 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4099 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4101 if(STACK_MODEL_LARGE) {
4102 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4103 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4105 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4110 /* old code, left here for reference -- VR */
4114 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4116 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4117 pic16_emitpcomment("push %s",l);
4120 DEBUGpic16_emitcode(";", "%d", __LINE__);
4121 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4122 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4124 if (strcmp(fReturn[offset],l)) {
4125 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4126 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4127 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4129 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4133 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4143 if (strcmp(fReturn[pushed],"a"))
4144 pic16_emitcode("pop",fReturn[pushed]);
4146 pic16_emitcode("pop","acc");
4152 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4155 /* generate a jump to the return label
4156 * if the next is not the return statement */
4157 if (!(ic->next && ic->next->op == LABEL
4158 && IC_LABEL(ic->next) == returnLabel)) {
4160 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4161 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4165 /*-----------------------------------------------------------------*/
4166 /* genLabel - generates a label */
4167 /*-----------------------------------------------------------------*/
4168 static void genLabel (iCode *ic)
4172 /* special case never generate */
4173 if (IC_LABEL(ic) == entryLabel)
4176 pic16_emitpLabel(IC_LABEL(ic)->key);
4177 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4180 /*-----------------------------------------------------------------*/
4181 /* genGoto - generates a goto */
4182 /*-----------------------------------------------------------------*/
4184 static void genGoto (iCode *ic)
4187 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4188 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4192 /*-----------------------------------------------------------------*/
4193 /* genMultbits :- multiplication of bits */
4194 /*-----------------------------------------------------------------*/
4195 static void genMultbits (operand *left,
4201 if(!pic16_sameRegs(AOP(result),AOP(right)))
4202 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4204 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4205 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4206 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4211 /*-----------------------------------------------------------------*/
4212 /* genMultOneByte : 8 bit multiplication & division */
4213 /*-----------------------------------------------------------------*/
4214 static void genMultOneByte (operand *left,
4220 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4221 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4223 /* (if two literals, the value is computed before) */
4224 /* if one literal, literal on the right */
4225 if (AOP_TYPE(left) == AOP_LIT){
4231 /* size is already checked in genMult == 1 */
4232 // size = AOP_SIZE(result);
4234 if (AOP_TYPE(right) == AOP_LIT){
4235 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4236 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4237 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4238 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4240 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4241 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4242 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4243 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4246 pic16_genMult8X8_n (left, right,result);
4250 /*-----------------------------------------------------------------*/
4251 /* genMultOneWord : 16 bit multiplication */
4252 /*-----------------------------------------------------------------*/
4253 static void genMultOneWord (operand *left,
4258 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4259 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4261 /* (if two literals, the value is computed before)
4262 * if one literal, literal on the right */
4263 if (AOP_TYPE(left) == AOP_LIT){
4269 /* size is checked already == 2 */
4270 // size = AOP_SIZE(result);
4272 if (AOP_TYPE(right) == AOP_LIT) {
4273 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4274 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4275 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4276 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4278 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4279 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4280 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4281 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4284 pic16_genMult16X16_16(left, right,result);
4289 /*-----------------------------------------------------------------*/
4290 /* genMultOneLong : 32 bit multiplication */
4291 /*-----------------------------------------------------------------*/
4292 static void genMultOneLong (operand *left,
4297 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4298 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4300 /* (if two literals, the value is computed before)
4301 * if one literal, literal on the right */
4302 if (AOP_TYPE(left) == AOP_LIT){
4308 /* size is checked already == 4 */
4309 // size = AOP_SIZE(result);
4311 if (AOP_TYPE(right) == AOP_LIT) {
4312 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4313 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4314 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4315 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4317 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4318 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4319 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4320 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4323 pic16_genMult32X32_32(left, right,result);
4329 /*-----------------------------------------------------------------*/
4330 /* genMult - generates code for multiplication */
4331 /*-----------------------------------------------------------------*/
4332 static void genMult (iCode *ic)
4334 operand *left = IC_LEFT(ic);
4335 operand *right = IC_RIGHT(ic);
4336 operand *result= IC_RESULT(ic);
4339 /* assign the amsops */
4340 pic16_aopOp (left,ic,FALSE);
4341 pic16_aopOp (right,ic,FALSE);
4342 pic16_aopOp (result,ic,TRUE);
4344 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4346 /* special cases first *
4348 if (AOP_TYPE(left) == AOP_CRY
4349 && AOP_TYPE(right)== AOP_CRY) {
4350 genMultbits(left,right,result);
4354 /* if both are of size == 1 */
4355 if(AOP_SIZE(left) == 1
4356 && AOP_SIZE(right) == 1) {
4357 genMultOneByte(left,right,result);
4362 /* if both are of size == 2 */
4363 if(AOP_SIZE(left) == 2
4364 && AOP_SIZE(right) == 2) {
4365 genMultOneWord(left, right, result);
4369 /* if both are of size == 4 */
4370 if(AOP_SIZE(left) == 4
4371 && AOP_SIZE(right) == 4) {
4372 genMultOneLong(left, right, result);
4377 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4378 assert( !"Multiplication should have been transformed into function call!" );
4380 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4383 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4384 /* should have been converted to function call */
4388 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4389 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4390 pic16_freeAsmop(result,NULL,ic,TRUE);
4394 /*-----------------------------------------------------------------*/
4395 /* genDivbits :- division of bits */
4396 /*-----------------------------------------------------------------*/
4397 static void genDivbits (operand *left,
4404 /* the result must be bit */
4405 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4406 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4410 pic16_emitcode("div","ab");
4411 pic16_emitcode("rrc","a");
4412 pic16_aopPut(AOP(result),"c",0);
4415 /*-----------------------------------------------------------------*/
4416 /* genDivOneByte : 8 bit division */
4417 /*-----------------------------------------------------------------*/
4418 static void genDivOneByte (operand *left,
4422 sym_link *opetype = operandType(result);
4427 /* result = divident / divisor
4428 * - divident may be a register or a literal,
4429 * - divisor may be a register or a literal,
4430 * so there are 3 cases (literal / literal is optimized
4431 * by the front-end) to handle.
4432 * In addition we must handle signed and unsigned, which
4433 * result in 6 final different cases -- VR */
4437 size = AOP_SIZE(result) - 1;
4439 /* signed or unsigned */
4440 if (SPEC_USIGN(opetype)) {
4441 pCodeOp *pct1, /* count */
4444 symbol *label1, *label2, *label3;;
4447 /* unsigned is easy */
4449 pct1 = pic16_popGetTempReg(1);
4450 pct2 = pic16_popGetTempReg(1);
4451 pct3 = pic16_popGetTempReg(1);
4453 label1 = newiTempLabel(NULL);
4454 label2 = newiTempLabel(NULL);
4455 label3 = newiTempLabel(NULL);
4457 /* the following algorithm is extracted from divuint.c */
4459 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4460 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4462 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4464 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4466 pic16_emitpLabel(label1->key);
4469 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4473 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4477 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4479 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4480 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4482 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4483 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4484 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4486 pic16_emitpLabel( label3->key );
4487 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4488 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4492 pic16_emitpLabel(label2->key);
4493 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4494 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4495 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4497 /* result is in wreg */
4498 if(AOP_TYPE(result) != AOP_ACC)
4499 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4501 pic16_popReleaseTempReg( pct3, 1);
4502 pic16_popReleaseTempReg( pct2, 1);
4503 pic16_popReleaseTempReg( pct1, 1);
4508 /* signed is a little bit more difficult */
4510 /* save the signs of the operands */
4511 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4513 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4514 pic16_emitcode("push","acc"); /* save it on the stack */
4516 /* now sign adjust for both left & right */
4517 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4519 lbl = newiTempLabel(NULL);
4520 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4521 pic16_emitcode("cpl","a");
4522 pic16_emitcode("inc","a");
4523 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4524 pic16_emitcode("mov","b,a");
4526 /* sign adjust left side */
4527 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4530 lbl = newiTempLabel(NULL);
4531 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4532 pic16_emitcode("cpl","a");
4533 pic16_emitcode("inc","a");
4534 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4536 /* now the division */
4537 pic16_emitcode("div","ab");
4538 /* we are interested in the lower order
4540 pic16_emitcode("mov","b,a");
4541 lbl = newiTempLabel(NULL);
4542 pic16_emitcode("pop","acc");
4543 /* if there was an over flow we don't
4544 adjust the sign of the result */
4545 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4546 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4548 pic16_emitcode("clr","a");
4549 pic16_emitcode("subb","a,b");
4550 pic16_emitcode("mov","b,a");
4551 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4553 /* now we are done */
4554 pic16_aopPut(AOP(result),"b",0);
4556 pic16_emitcode("mov","c,b.7");
4557 pic16_emitcode("subb","a,acc");
4560 pic16_aopPut(AOP(result),"a",offset++);
4565 /*-----------------------------------------------------------------*/
4566 /* genDiv - generates code for division */
4567 /*-----------------------------------------------------------------*/
4568 static void genDiv (iCode *ic)
4570 operand *left = IC_LEFT(ic);
4571 operand *right = IC_RIGHT(ic);
4572 operand *result= IC_RESULT(ic);
4574 int leftVal = 0, rightVal = 0;
4576 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4579 /* Division is a very lengthy algorithm, so it is better
4580 * to call support routines than inlining algorithm.
4581 * Division functions written here just in case someone
4582 * wants to inline and not use the support libraries -- VR */
4586 /* assign the amsops */
4587 pic16_aopOp (left,ic,FALSE);
4588 pic16_aopOp (right,ic,FALSE);
4589 pic16_aopOp (result,ic,TRUE);
4593 else if (ic->op == '%')
4596 assert( !"invalid operation requested in genDivMod" );
4598 /* get literal values */
4599 if (IS_VALOP(left)) {
4600 leftVal = (int)floatFromVal( OP_VALUE(left) );
4601 assert( leftVal >= -128 && leftVal < 256 );
4602 if (leftVal < 0) { signedLits++; }
4604 if (IS_VALOP(right)) {
4605 rightVal = (int)floatFromVal( OP_VALUE(right) );
4606 assert( rightVal >= -128 && rightVal < 256 );
4607 if (rightVal < 0) { signedLits++; }
4610 /* We should only come here to convert all
4611 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4612 * with exactly one operand being s8_t into
4613 * u8_t x u8_t -> u8_t. All other cases should have been
4614 * turned into calls to support routines beforehand... */
4615 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4616 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4618 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4619 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4621 /* Both operands are signed or negative, use _divschar
4622 * instead of _divuchar */
4623 pushaop(AOP(right), 0);
4624 pushaop(AOP(left), 0);
4626 /* call _divschar */
4627 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4631 sym = newSymbol( functions[op][0], 0 );
4633 strcpy(sym->rname, functions[op][0]);
4634 checkAddSym(&externs, sym);
4638 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4639 if (AOP_SIZE(result) > 1)
4641 pic16_emitpcode(POC_MOVFF,
4642 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4643 pic16_popGet(AOP(result), 1)));
4645 pic16_addSign(result, 2, 1);
4648 /* clean up stack */
4649 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4650 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4655 /* push right operand */
4656 if (IS_VALOP(right)) {
4658 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4661 pushaop(AOP(right), 0);
4663 } else if (!IS_UNSIGNED(operandType(right))) {
4664 pic16_mov2w(AOP(right), 0);
4665 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4666 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4667 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4670 pushaop(AOP(right), 0);
4673 /* push left operand */
4674 if (IS_VALOP(left)) {
4676 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4679 pushaop(AOP(left), 0);
4681 } else if (!IS_UNSIGNED(operandType(left))) {
4682 pic16_mov2w(AOP(left),0);
4683 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4684 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4685 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4688 pushaop(AOP(left), 0);
4691 /* call _divuchar */
4692 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4696 sym = newSymbol( functions[op][1], 0 );
4698 strcpy(sym->rname, functions[op][1]);
4699 checkAddSym(&externs, sym);
4702 /* Revert negation(s) from above.
4703 * This is inefficient: if both operands are negative, this
4704 * should not touch WREG. However, determining that exactly
4705 * one operand was negated costs at least 3 instructions,
4706 * so there is nothing to be gained here, is there?
4708 * I negate WREG because either operand might share registers with
4709 * result, so assigning first might destroy an operand. */
4711 /* For the modulus operator, (a/b)*b == a shall hold.
4712 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4713 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4714 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4715 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4716 * Only invert the result if the left operand is negative (sigh).
4718 if (AOP_SIZE(result) <= 1 || !negated)
4722 if (IS_VALOP(right)) {
4724 /* we negated this operand above */
4725 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4727 } else if (!IS_UNSIGNED(operandType(right))) {
4728 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4729 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4733 if (IS_VALOP(left)) {
4735 /* we negated this operand above */
4736 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4738 } else if (!IS_UNSIGNED(operandType(left))) {
4739 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4740 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4743 /* Move result to destination. */
4744 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4746 /* Zero-extend: no operand was signed (or result is just a byte). */
4747 pic16_addSign(result, 1, 0);
4749 assert( AOP_SIZE(result) > 1 );
4750 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4753 if (IS_VALOP(right)) {
4755 /* we negated this operand above */
4756 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4758 } else if (!IS_UNSIGNED(operandType(right))) {
4759 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4760 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4764 if (IS_VALOP(left)) {
4766 /* we negated this operand above */
4767 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4769 } else if (!IS_UNSIGNED(operandType(left))) {
4770 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4771 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4774 /* Move result to destination. */
4775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4777 /* Negate result if required. */
4778 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4779 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4782 pic16_addSign(result, 2, 1);
4785 /* clean up stack */
4786 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4787 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4792 /* special cases first */
4794 if (AOP_TYPE(left) == AOP_CRY &&
4795 AOP_TYPE(right)== AOP_CRY) {
4796 genDivbits(left,right,result);
4800 /* if both are of size == 1 */
4801 if (AOP_SIZE(left) == 1 &&
4802 AOP_SIZE(right) == 1 ) {
4803 genDivOneByte(left,right,result);
4808 /* should have been converted to function call */
4811 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4812 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4813 pic16_freeAsmop(result,NULL,ic,TRUE);
4817 /*-----------------------------------------------------------------*/
4818 /* genModbits :- modulus of bits */
4819 /*-----------------------------------------------------------------*/
4820 static void genModbits (operand *left,
4828 werror(W_POSSBUG2, __FILE__, __LINE__);
4829 /* the result must be bit */
4830 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4831 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4835 pic16_emitcode("div","ab");
4836 pic16_emitcode("mov","a,b");
4837 pic16_emitcode("rrc","a");
4838 pic16_aopPut(AOP(result),"c",0);
4841 /*-----------------------------------------------------------------*/
4842 /* genModOneByte : 8 bit modulus */
4843 /*-----------------------------------------------------------------*/
4844 static void genModOneByte (operand *left,
4848 sym_link *opetype = operandType(result);
4853 werror(W_POSSBUG2, __FILE__, __LINE__);
4855 /* signed or unsigned */
4856 if (SPEC_USIGN(opetype)) {
4857 /* unsigned is easy */
4858 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4859 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4861 pic16_emitcode("div","ab");
4862 pic16_aopPut(AOP(result),"b",0);
4866 /* signed is a little bit more difficult */
4868 /* save the signs of the operands */
4869 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4872 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4873 pic16_emitcode("push","acc"); /* save it on the stack */
4875 /* now sign adjust for both left & right */
4876 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4879 lbl = newiTempLabel(NULL);
4880 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4881 pic16_emitcode("cpl","a");
4882 pic16_emitcode("inc","a");
4883 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4884 pic16_emitcode("mov","b,a");
4886 /* sign adjust left side */
4887 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4890 lbl = newiTempLabel(NULL);
4891 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4892 pic16_emitcode("cpl","a");
4893 pic16_emitcode("inc","a");
4894 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4896 /* now the multiplication */
4897 pic16_emitcode("div","ab");
4898 /* we are interested in the lower order
4900 lbl = newiTempLabel(NULL);
4901 pic16_emitcode("pop","acc");
4902 /* if there was an over flow we don't
4903 adjust the sign of the result */
4904 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4905 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4907 pic16_emitcode("clr","a");
4908 pic16_emitcode("subb","a,b");
4909 pic16_emitcode("mov","b,a");
4910 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4912 /* now we are done */
4913 pic16_aopPut(AOP(result),"b",0);
4918 /*-----------------------------------------------------------------*/
4919 /* genMod - generates code for division */
4920 /*-----------------------------------------------------------------*/
4921 static void genMod (iCode *ic)
4923 /* Task deferred to genDiv */
4926 operand *left = IC_LEFT(ic);
4927 operand *right = IC_RIGHT(ic);
4928 operand *result= IC_RESULT(ic);
4932 /* assign the amsops */
4933 pic16_aopOp (left,ic,FALSE);
4934 pic16_aopOp (right,ic,FALSE);
4935 pic16_aopOp (result,ic,TRUE);
4937 /* special cases first */
4939 if (AOP_TYPE(left) == AOP_CRY &&
4940 AOP_TYPE(right)== AOP_CRY) {
4941 genModbits(left,right,result);
4945 /* if both are of size == 1 */
4946 if (AOP_SIZE(left) == 1 &&
4947 AOP_SIZE(right) == 1 ) {
4948 genModOneByte(left,right,result);
4952 /* should have been converted to function call */
4956 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4957 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4958 pic16_freeAsmop(result,NULL,ic,TRUE);
4962 /*-----------------------------------------------------------------*/
4963 /* genIfxJump :- will create a jump depending on the ifx */
4964 /*-----------------------------------------------------------------*/
4966 note: May need to add parameter to indicate when a variable is in bit space.
4968 static void genIfxJump (iCode *ic, char *jval)
4972 /* if true label then we jump if condition
4974 if ( IC_TRUE(ic) ) {
4976 if(strcmp(jval,"a") == 0)
4978 else if (strcmp(jval,"c") == 0)
4981 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4982 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4985 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4986 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4990 /* false label is present */
4991 if(strcmp(jval,"a") == 0)
4993 else if (strcmp(jval,"c") == 0)
4996 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4997 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
5000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5001 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5006 /* mark the icode as generated */
5010 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5014 /* if true label then we jump if condition
5016 if ( IC_TRUE(ic) ) {
5017 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5018 pic16_emitpcode(POC_BTFSC, jop);
5020 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5021 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5024 /* false label is present */
5025 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5026 pic16_emitpcode(POC_BTFSS, jop);
5028 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5029 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5033 /* mark the icode as generated */
5040 /*-----------------------------------------------------------------*/
5042 /*-----------------------------------------------------------------*/
5043 static void genSkip(iCode *ifx,int status_bit)
5045 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5049 if ( IC_TRUE(ifx) ) {
5050 switch(status_bit) {
5065 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5066 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5070 switch(status_bit) {
5084 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5085 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5092 /*-----------------------------------------------------------------*/
5094 /*-----------------------------------------------------------------*/
5095 static void genSkipc(resolvedIfx *rifx)
5097 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5107 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5108 rifx->generated = 1;
5111 #if !(USE_SIMPLE_GENCMP)
5112 /*-----------------------------------------------------------------*/
5114 /*-----------------------------------------------------------------*/
5115 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5117 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5122 if( (rifx->condition ^ invert_condition) & 1)
5127 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5128 rifx->generated = 1;
5133 /*-----------------------------------------------------------------*/
5135 /*-----------------------------------------------------------------*/
5136 static void genSkipz(iCode *ifx, int condition)
5147 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5149 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5152 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5154 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5159 #if !(USE_SIMPLE_GENCMP)
5160 /*-----------------------------------------------------------------*/
5162 /*-----------------------------------------------------------------*/
5163 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5169 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5171 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5174 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5175 rifx->generated = 1;
5180 /*-----------------------------------------------------------------*/
5181 /* genChkZeroes :- greater or less than comparison */
5182 /* For each byte in a literal that is zero, inclusive or the */
5183 /* the corresponding byte in the operand with W */
5184 /* returns true if any of the bytes are zero */
5185 /*-----------------------------------------------------------------*/
5186 static int genChkZeroes(operand *op, int lit, int size)
5193 i = (lit >> (size*8)) & 0xff;
5197 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5199 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5209 /*-----------------------------------------------------------------*/
5210 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5211 /* aop (if it's NOT a literal) or from lit (if */
5212 /* aop is a literal) */
5213 /*-----------------------------------------------------------------*/
5214 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5215 if (aop->type == AOP_LIT) {
5216 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5218 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5222 /*-----------------------------------------------------------------*/
5223 /* genCmp :- greater or less than comparison */
5224 /*-----------------------------------------------------------------*/
5226 #if USE_SIMPLE_GENCMP /* { */
5228 /* genCmp performs a left < right comparison, stores
5229 * the outcome in result (if != NULL) and generates
5230 * control flow code for the ifx (if != NULL).
5232 * This version leaves in sequences like
5233 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5234 * which should be optmized by the peephole
5235 * optimizer - RN 2005-01-01 */
5236 static void genCmp (operand *left,operand *right,
5237 operand *result, iCode *ifx, int sign)
5250 assert (left && right);
5251 assert (AOP_SIZE(left) == AOP_SIZE(right));
5253 size = AOP_SIZE(right) - 1;
5254 mask = (0x100UL << (size*8)) - 1;
5255 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5260 resolveIfx (&rIfx, ifx);
5262 /* handle for special cases */
5263 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5266 /**********************************************************************
5267 * handle bits - bit compares are promoted to int compares seemingly! *
5268 **********************************************************************/
5270 // THIS IS COMPLETELY UNTESTED!
5271 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5272 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5273 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5274 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5277 // 1 < {0,1} is false --> clear C by skipping the next instruction
5278 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5279 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5280 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5281 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5282 emitCLRC; // only skipped for left=0 && right=1
5284 goto correct_result_in_carry;
5288 /*************************************************
5289 * make sure that left is register (or the like) *
5290 *************************************************/
5291 if (!isAOP_REGlike(left)) {
5292 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5293 assert (isAOP_LIT(left));
5294 assert (isAOP_REGlike(right));
5295 // swap left and right
5296 // left < right <==> right > left <==> (right >= left + 1)
5297 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5299 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5300 // MAXVALUE < right? always false
5301 if (performedLt) emitCLRC; else emitSETC;
5302 goto correct_result_in_carry;
5305 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5306 // that's why we handled it above.
5313 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5314 } else if (isAOP_LIT(right)) {
5315 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5318 assert (isAOP_REGlike(left)); // left must be register or the like
5319 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5321 /*************************************************
5322 * special cases go here *
5323 *************************************************/
5325 if (isAOP_LIT(right)) {
5327 // unsigned comparison to a literal
5328 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5330 // unsigned left < 0? always false
5331 if (performedLt) emitCLRC; else emitSETC;
5332 goto correct_result_in_carry;
5335 // signed comparison to a literal
5336 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5337 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5338 // signed left < 0x80000000? always false
5339 if (performedLt) emitCLRC; else emitSETC;
5340 goto correct_result_in_carry;
5341 } else if (lit == 0) {
5342 // compare left < 0; set CARRY if SIGNBIT(left) is set
5343 if (performedLt) emitSETC; else emitCLRC;
5344 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5345 if (performedLt) emitCLRC; else emitSETC;
5346 goto correct_result_in_carry;
5349 } // right is literal
5351 /*************************************************
5352 * perform a general case comparison *
5353 * make sure we get CARRY==1 <==> left >= right *
5354 *************************************************/
5355 // compare most significant bytes
5356 //DEBUGpc ("comparing bytes at offset %d", size);
5358 // unsigned comparison
5359 mov2w_regOrLit (AOP(right), lit, size);
5360 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5362 // signed comparison
5363 // (add 2^n to both operands then perform an unsigned comparison)
5364 if (isAOP_LIT(right)) {
5365 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5366 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5368 if (litbyte == 0x80) {
5369 // left >= 0x80 -- always true, but more bytes to come
5370 pic16_mov2w (AOP(left), size);
5371 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5374 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5375 pic16_mov2w (AOP(left), size);
5376 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5377 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5380 /* using PRODL as a temporary register here */
5381 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5382 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5383 pic16_mov2w (AOP(left), size);
5384 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5385 pic16_emitpcode (POC_MOVWF, pctemp);
5386 pic16_mov2w (AOP(right), size);
5387 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5388 pic16_emitpcode (POC_SUBFW, pctemp);
5389 //pic16_popReleaseTempReg(pctemp, 1);
5393 // compare remaining bytes (treat as unsigned case from above)
5394 templbl = newiTempLabel ( NULL );
5397 //DEBUGpc ("comparing bytes at offset %d", offs);
5398 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5399 mov2w_regOrLit (AOP(right), lit, offs);
5400 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5402 pic16_emitpLabel (templbl->key);
5403 goto result_in_carry;
5407 /****************************************************
5408 * now CARRY contains the result of the comparison: *
5409 * SUBWF sets CARRY iff *
5410 * F-W >= 0 <==> F >= W <==> !(F < W) *
5411 * (F=left, W=right) *
5412 ****************************************************/
5415 if (result && AOP_TYPE(result) != AOP_CRY) {
5416 // value will be stored
5419 // value wil only be used in the following genSkipc()
5420 rIfx.condition ^= 1;
5424 correct_result_in_carry:
5426 // assign result to variable (if neccessary)
5427 if (result && AOP_TYPE(result) != AOP_CRY) {
5428 //DEBUGpc ("assign result");
5429 size = AOP_SIZE(result);
5431 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5433 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5436 // perform conditional jump
5438 //DEBUGpc ("generate control flow");
5447 static void genCmp (operand *left,operand *right,
5448 operand *result, iCode *ifx, int sign)
5450 int size; //, offset = 0 ;
5451 unsigned long lit = 0L,i = 0;
5452 resolvedIfx rFalseIfx;
5453 // resolvedIfx rTrueIfx;
5455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5458 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5459 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5465 resolveIfx(&rFalseIfx,ifx);
5466 truelbl = newiTempLabel(NULL);
5467 size = max(AOP_SIZE(left),AOP_SIZE(right));
5469 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5473 /* if literal is on the right then swap with left */
5474 if ((AOP_TYPE(right) == AOP_LIT)) {
5475 operand *tmp = right ;
5476 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5477 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5480 lit = (lit - 1) & mask;
5483 rFalseIfx.condition ^= 1;
5486 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5487 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5491 //if(IC_TRUE(ifx) == NULL)
5492 /* if left & right are bit variables */
5493 if (AOP_TYPE(left) == AOP_CRY &&
5494 AOP_TYPE(right) == AOP_CRY ) {
5495 assert (0 && "bit variables used in genCmp");
5496 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5497 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5499 /* subtract right from left if at the
5500 end the carry flag is set then we know that
5501 left is greater than right */
5503 symbol *lbl = newiTempLabel(NULL);
5506 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5507 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5511 if(AOP_TYPE(right) == AOP_LIT) {
5513 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5515 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5522 genSkipCond(&rFalseIfx,left,size-1,7);
5524 /* no need to compare to 0...*/
5525 /* NOTE: this is a de-generate compare that most certainly
5526 * creates some dead code. */
5527 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5529 if(ifx) ifx->generated = 1;
5536 //i = (lit >> (size*8)) & 0xff;
5537 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5539 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5541 i = ((0-lit) & 0xff);
5544 /* lit is 0x7f, all signed chars are less than
5545 * this except for 0x7f itself */
5546 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5547 genSkipz2(&rFalseIfx,0);
5549 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5550 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5551 genSkipc(&rFalseIfx);
5556 genSkipz2(&rFalseIfx,1);
5558 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5559 genSkipc(&rFalseIfx);
5563 if(ifx) ifx->generated = 1;
5567 /* chars are out of the way. now do ints and longs */
5570 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5577 genSkipCond(&rFalseIfx,left,size,7);
5578 if(ifx) ifx->generated = 1;
5583 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5585 //rFalseIfx.condition ^= 1;
5586 //genSkipCond(&rFalseIfx,left,size,7);
5587 //rFalseIfx.condition ^= 1;
5589 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5590 if(rFalseIfx.condition)
5591 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5593 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5595 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5596 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5597 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5600 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5602 if(rFalseIfx.condition) {
5604 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5610 genSkipc(&rFalseIfx);
5611 pic16_emitpLabel(truelbl->key);
5612 if(ifx) ifx->generated = 1;
5619 if( (lit & 0xff) == 0) {
5620 /* lower byte is zero */
5621 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5622 i = ((lit >> 8) & 0xff) ^0x80;
5623 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5624 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5625 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5626 genSkipc(&rFalseIfx);
5629 if(ifx) ifx->generated = 1;
5634 /* Special cases for signed longs */
5635 if( (lit & 0xffffff) == 0) {
5636 /* lower byte is zero */
5637 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5638 i = ((lit >> 8*3) & 0xff) ^0x80;
5639 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5640 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5641 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5642 genSkipc(&rFalseIfx);
5645 if(ifx) ifx->generated = 1;
5653 if(lit & (0x80 << (size*8))) {
5654 /* lit is negative */
5655 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5657 //genSkipCond(&rFalseIfx,left,size,7);
5659 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5661 if(rFalseIfx.condition)
5662 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5664 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5668 /* lit is positive */
5669 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5670 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5671 if(rFalseIfx.condition)
5672 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5674 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5679 This works, but is only good for ints.
5680 It also requires a "known zero" register.
5681 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5682 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5683 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5684 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5685 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5686 genSkipc(&rFalseIfx);
5688 pic16_emitpLabel(truelbl->key);
5689 if(ifx) ifx->generated = 1;
5693 /* There are no more special cases, so perform a general compare */
5695 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5696 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5700 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5702 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5704 //rFalseIfx.condition ^= 1;
5705 genSkipc(&rFalseIfx);
5707 pic16_emitpLabel(truelbl->key);
5709 if(ifx) ifx->generated = 1;
5716 /* sign is out of the way. So now do an unsigned compare */
5717 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5720 /* General case - compare to an unsigned literal on the right.*/
5722 i = (lit >> (size*8)) & 0xff;
5723 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5724 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5726 i = (lit >> (size*8)) & 0xff;
5729 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5731 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5733 /* this byte of the lit is zero,
5734 *if it's not the last then OR in the variable */
5736 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5741 pic16_emitpLabel(lbl->key);
5742 // pic16_emitpLabel(truelbl->key);
5743 //if(emitFinalCheck)
5744 genSkipc(&rFalseIfx);
5746 pic16_emitpLabel(truelbl->key);
5748 if(ifx) ifx->generated = 1;
5755 if(AOP_TYPE(left) == AOP_LIT) {
5756 //symbol *lbl = newiTempLabel(NULL);
5758 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5761 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5764 if((lit == 0) && (sign == 0)){
5767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5769 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5771 genSkipz2(&rFalseIfx,0);
5772 if(ifx) ifx->generated = 1;
5779 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5780 /* degenerate compare can never be true */
5781 if(rFalseIfx.condition == 0)
5782 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5784 if(ifx) ifx->generated = 1;
5789 /* signed comparisons to a literal byte */
5791 int lp1 = (lit+1) & 0xff;
5793 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5796 rFalseIfx.condition ^= 1;
5797 genSkipCond(&rFalseIfx,right,0,7);
5800 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5801 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5802 genSkipz2(&rFalseIfx,1);
5805 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5806 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5807 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5808 rFalseIfx.condition ^= 1;
5809 genSkipc(&rFalseIfx);
5813 /* unsigned comparisons to a literal byte */
5815 switch(lit & 0xff ) {
5817 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5818 genSkipz2(&rFalseIfx,0);
5821 rFalseIfx.condition ^= 1;
5822 genSkipCond(&rFalseIfx,right,0,7);
5826 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5827 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5829 rFalseIfx.condition ^= 1;
5830 if (AOP_TYPE(result) == AOP_CRY)
5831 genSkipc(&rFalseIfx);
5833 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5834 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5840 if(ifx) ifx->generated = 1;
5841 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5847 /* Size is greater than 1 */
5855 /* this means lit = 0xffffffff, or -1 */
5858 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5859 rFalseIfx.condition ^= 1;
5860 genSkipCond(&rFalseIfx,right,size,7);
5861 if(ifx) ifx->generated = 1;
5863 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5872 if(rFalseIfx.condition) {
5873 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5874 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5877 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5879 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5883 if(rFalseIfx.condition) {
5884 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5885 pic16_emitpLabel(truelbl->key);
5887 rFalseIfx.condition ^= 1;
5888 genSkipCond(&rFalseIfx,right,s,7);
5891 if(ifx) ifx->generated = 1;
5893 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5899 if((size == 1) && (0 == (lp1&0xff))) {
5900 /* lower byte of signed word is zero */
5901 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5902 i = ((lp1 >> 8) & 0xff) ^0x80;
5903 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5904 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5905 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5907 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5909 if(ifx) ifx->generated = 1;
5912 rFalseIfx.condition ^= 1;
5913 genSkipc(&rFalseIfx);
5914 if(ifx) ifx->generated = 1;
5920 if(lit & (0x80 << (size*8))) {
5921 /* Lit is less than zero */
5922 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5923 //rFalseIfx.condition ^= 1;
5924 //genSkipCond(&rFalseIfx,left,size,7);
5925 //rFalseIfx.condition ^= 1;
5926 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5927 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5929 if(rFalseIfx.condition)
5930 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5932 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5936 /* Lit is greater than or equal to zero */
5937 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5938 //rFalseIfx.condition ^= 1;
5939 //genSkipCond(&rFalseIfx,right,size,7);
5940 //rFalseIfx.condition ^= 1;
5942 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5943 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5945 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5946 if(rFalseIfx.condition)
5947 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5949 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5954 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5958 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5960 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5962 rFalseIfx.condition ^= 1;
5963 //rFalseIfx.condition = 1;
5964 genSkipc(&rFalseIfx);
5966 pic16_emitpLabel(truelbl->key);
5968 if(ifx) ifx->generated = 1;
5971 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5978 /* compare word or long to an unsigned literal on the right.*/
5983 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5986 break; /* handled above */
5989 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5991 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5992 genSkipz2(&rFalseIfx,0);
5996 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5998 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6001 if(rFalseIfx.condition)
6002 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6004 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6007 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6008 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6010 rFalseIfx.condition ^= 1;
6011 genSkipc(&rFalseIfx);
6014 pic16_emitpLabel(truelbl->key);
6016 if(ifx) ifx->generated = 1;
6018 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6026 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6027 i = (lit >> (size*8)) & 0xff;
6029 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6030 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6033 i = (lit >> (size*8)) & 0xff;
6036 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6038 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6040 /* this byte of the lit is zero,
6041 * if it's not the last then OR in the variable */
6043 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6048 pic16_emitpLabel(lbl->key);
6050 rFalseIfx.condition ^= 1;
6052 genSkipc(&rFalseIfx);
6056 pic16_emitpLabel(truelbl->key);
6057 if(ifx) ifx->generated = 1;
6059 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6065 /* Compare two variables */
6067 DEBUGpic16_emitcode(";sign","%d",sign);
6071 /* Sigh. thus sucks... */
6075 pctemp = pic16_popGetTempReg(1);
6076 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6077 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6078 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6079 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6080 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6081 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6082 pic16_popReleaseTempReg(pctemp, 1);
6084 /* Signed char comparison */
6085 /* Special thanks to Nikolai Golovchenko for this snippet */
6086 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6087 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6088 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6089 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6090 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6091 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6093 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6094 genSkipc(&rFalseIfx);
6096 if(ifx) ifx->generated = 1;
6098 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6106 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6107 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6111 /* The rest of the bytes of a multi-byte compare */
6115 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6118 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6119 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6124 pic16_emitpLabel(lbl->key);
6126 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6127 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6128 (AOP_TYPE(result) == AOP_REG)) {
6129 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6130 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6132 genSkipc(&rFalseIfx);
6134 //genSkipc(&rFalseIfx);
6135 if(ifx) ifx->generated = 1;
6138 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6146 if ((AOP_TYPE(result) != AOP_CRY)
6147 && AOP_SIZE(result)) {
6148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6150 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6152 pic16_outBitC(result);
6154 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6155 /* if the result is used in the next
6156 ifx conditional branch then generate
6157 code a little differently */
6159 genIfxJump (ifx,"c");
6161 pic16_outBitC(result);
6162 /* leave the result in acc */
6167 #elif 0 /* VR version of genCmp() */ /* } else { */
6169 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6170 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6171 operand *result, int offset, int invert_op)
6175 /* check condition, > or < ?? */
6176 if(rIfx->condition != 0)invert_op ^= 1;
6178 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6180 if(!ifx)invert_op ^= 1;
6182 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6183 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6186 if(!invert_op)return POC_CPFSGT;
6187 else return POC_CPFSLT;
6190 static int compareAopfirstpass=1;
6192 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6193 operand *oper, int offset, operand *result,
6194 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6200 /* invert if there is a result to be loaded, in order to fit,
6201 * SETC/CLRC sequence */
6202 if(AOP_SIZE(result))invert_op ^= 1;
6204 // if(sign && !offset)invert_op ^= 1;
6206 // if(sign)invert_op ^= 1;
6208 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6210 if(AOP_SIZE(result) && compareAopfirstpass) {
6213 pic16_emitpcode(POC_SETF, pcop2);
6218 pic16_emitpcode(POC_CLRF, pcop2);
6224 compareAopfirstpass = 0;
6226 /* there is a bug when comparing operands with size > 1,
6227 * because higher bytes can be equal and test should be performed
6228 * to the next lower byte, current algorithm, considers operands
6229 * inequal in these cases! -- VR 20041107 */
6233 pic16_emitpcode(op, pcop);
6235 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6238 if((!sign || !offset) && AOP_SIZE(result)) {
6241 pic16_emitpcode(POC_CLRF, pcop2);
6246 pic16_emitpcode(POC_SETF, pcop2);
6251 /* don't emit final branch (offset == 0) */
6255 pic16_emitpcode(POC_RRCF, pcop2);
6257 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6260 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6261 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6262 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6264 truelbl = newiTempLabel( NULL );
6265 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6266 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6267 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6269 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6270 pic16_emitpLabel(truelbl->key);
6272 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6277 static void genCmp (operand *left, operand *right,
6278 operand *result, iCode *ifx, int sign)
6282 resolvedIfx rFalseIfx;
6283 symbol *falselbl, *tlbl;
6287 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6289 resolveIfx(&rFalseIfx, ifx);
6290 size = max(AOP_SIZE(left), AOP_SIZE(right));
6292 /* if left & right are bit variables */
6293 if(AOP_TYPE(left) == AOP_CRY
6294 && AOP_TYPE(right) == AOP_CRY ) {
6296 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6297 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6299 werror(W_POSSBUG2, __FILE__, __LINE__);
6303 /* if literal is on the right then swap with left */
6304 if((AOP_TYPE(right) == AOP_LIT)) {
6305 operand *tmp = right ;
6306 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6308 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6310 // lit = (lit - 1) & mask;
6313 rFalseIfx.condition ^= 1; /* reverse compare */
6315 if ((AOP_TYPE(left) == AOP_LIT)) {
6316 /* float compares are handled by support functions */
6317 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6320 /* actual comparing algorithm */
6321 // size = AOP_SIZE( right );
6323 falselbl = newiTempLabel( NULL );
6324 if(AOP_TYPE(left) == AOP_LIT) {
6325 /* compare to literal */
6326 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6329 pCodeOp *pct, *pct2;
6332 /* signed compare */
6333 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6335 /* using PRODL:PRODH as a temporary register here */
6336 pct = pic16_popCopyReg(&pic16_pc_prodl);
6337 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6338 tlbl = newiTempLabel( NULL );
6340 /* first compare signs:
6341 * a. if both are positive, compare just like unsigned
6342 * b. if both are negative, invert cmpop, compare just like unsigned
6343 * c. if different signs, determine the result directly */
6349 tlbl1 = newiTempLabel( NULL );
6350 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6354 /* literal is zero or positive:
6355 * a. if carry is zero, too, continue compare,
6356 * b. if carry is set, then continue depending on cmpop ^ condition:
6357 * 1. '<' return false (literal < variable),
6358 * 2. '>' return true (literal > variable) */
6359 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6360 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6363 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6364 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6368 /* literal is negative:
6369 * a. if carry is set, too, continue compare,
6370 * b. if carry is zero, then continue depending on cmpop ^ condition:
6371 * 1. '<' return true (literal < variable),
6372 * 2. '>' return false (literal > variable) */
6373 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6374 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6376 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6377 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6382 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6384 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6385 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6390 pic16_emitpLabel( tlbl1->key );
6393 compareAopfirstpass=1;
6394 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6395 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6396 // pic16_emitpcode(POC_MOVWF, pct);
6398 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6399 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6400 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6401 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6405 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6406 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6407 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6408 // pic16_emitpcode(POC_MOVWF, pct);
6410 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6411 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6412 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6413 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6414 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6417 if(ifx)ifx->generated = 1;
6419 if(AOP_SIZE(result)) {
6420 pic16_emitpLabel(tlbl->key);
6421 pic16_emitpLabel(falselbl->key);
6422 pic16_outBitOp( result, pct2 );
6424 pic16_emitpLabel(tlbl->key);
6428 /* unsigned compare */
6429 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6431 compareAopfirstpass=1;
6434 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6435 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6438 if(ifx)ifx->generated = 1;
6440 if(AOP_SIZE(result)) {
6441 pic16_emitpLabel(falselbl->key);
6442 pic16_outBitC( result );
6447 /* compare registers */
6448 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6452 pCodeOp *pct, *pct2;
6454 /* signed compare */
6455 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6457 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6458 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6459 tlbl = newiTempLabel( NULL );
6461 compareAopfirstpass=1;
6464 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6465 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6467 pic16_emitpcode(POC_MOVWF, pct);
6469 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6470 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6471 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6473 /* WREG already holds left + 0x80 */
6474 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6478 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6479 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6480 pic16_emitpcode(POC_MOVWF, pct);
6482 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6483 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6484 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6486 /* WREG already holds left + 0x80 */
6487 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6488 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6491 if(ifx)ifx->generated = 1;
6493 if(AOP_SIZE(result)) {
6494 pic16_emitpLabel(tlbl->key);
6495 pic16_emitpLabel(falselbl->key);
6496 pic16_outBitOp( result, pct2 );
6498 pic16_emitpLabel(tlbl->key);
6502 /* unsigned compare */
6503 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6505 compareAopfirstpass=1;
6508 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6509 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6513 if(ifx)ifx->generated = 1;
6514 if(AOP_SIZE(result)) {
6516 pic16_emitpLabel(falselbl->key);
6517 pic16_outBitC( result );
6528 /*-----------------------------------------------------------------*/
6529 /* genCmpGt :- greater than comparison */
6530 /*-----------------------------------------------------------------*/
6531 static void genCmpGt (iCode *ic, iCode *ifx)
6533 operand *left, *right, *result;
6534 sym_link *letype , *retype;
6540 right= IC_RIGHT(ic);
6541 result = IC_RESULT(ic);
6543 letype = getSpec(operandType(left));
6544 retype =getSpec(operandType(right));
6545 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6546 /* assign the amsops */
6547 pic16_aopOp (left,ic,FALSE);
6548 pic16_aopOp (right,ic,FALSE);
6549 pic16_aopOp (result,ic,TRUE);
6551 genCmp(right, left, result, ifx, sign);
6553 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6554 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6555 pic16_freeAsmop(result,NULL,ic,TRUE);
6558 /*-----------------------------------------------------------------*/
6559 /* genCmpLt - less than comparisons */
6560 /*-----------------------------------------------------------------*/
6561 static void genCmpLt (iCode *ic, iCode *ifx)
6563 operand *left, *right, *result;
6564 sym_link *letype , *retype;
6570 right= IC_RIGHT(ic);
6571 result = IC_RESULT(ic);
6573 letype = getSpec(operandType(left));
6574 retype =getSpec(operandType(right));
6575 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6577 /* assign the amsops */
6578 pic16_aopOp (left,ic,FALSE);
6579 pic16_aopOp (right,ic,FALSE);
6580 pic16_aopOp (result,ic,TRUE);
6582 genCmp(left, right, result, ifx, sign);
6584 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6585 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6586 pic16_freeAsmop(result,NULL,ic,TRUE);
6591 // FIXME reenable literal optimisation when the pic16 port is stable
6593 /*-----------------------------------------------------------------*/
6594 /* genc16bit2lit - compare a 16 bit value to a literal */
6595 /*-----------------------------------------------------------------*/
6596 static void genc16bit2lit(operand *op, int lit, int offset)
6600 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6601 if( (lit&0xff) == 0)
6606 switch( BYTEofLONG(lit,i)) {
6608 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6611 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6614 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6617 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6618 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6623 switch( BYTEofLONG(lit,i)) {
6625 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6629 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6633 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6636 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6638 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6647 /*-----------------------------------------------------------------*/
6648 /* gencjneshort - compare and jump if not equal */
6649 /*-----------------------------------------------------------------*/
6650 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6652 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6654 int res_offset = 0; /* the result may be a different size then left or right */
6655 int res_size = AOP_SIZE(result);
6657 symbol *lbl, *lbl_done;
6659 unsigned long lit = 0L;
6660 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6662 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6663 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6665 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6666 resolveIfx(&rIfx,ifx);
6667 lbl = newiTempLabel(NULL);
6668 lbl_done = newiTempLabel(NULL);
6671 /* if the left side is a literal or
6672 if the right is in a pointer register and left
6674 if ((AOP_TYPE(left) == AOP_LIT) ||
6675 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6680 if(AOP_TYPE(right) == AOP_LIT)
6681 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6683 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6684 preserve_result = 1;
6686 if(result && !preserve_result)
6689 for(i = 0; i < AOP_SIZE(result); i++)
6690 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6694 /* if the right side is a literal then anything goes */
6695 if (AOP_TYPE(right) == AOP_LIT &&
6696 AOP_TYPE(left) != AOP_DIR ) {
6699 genc16bit2lit(left, lit, 0);
6701 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6707 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6708 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6710 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6714 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6716 if(res_offset < res_size-1)
6724 /* if the right side is in a register or in direct space or
6725 if the left is a pointer register & right is not */
6726 else if (AOP_TYPE(right) == AOP_REG ||
6727 AOP_TYPE(right) == AOP_DIR ||
6728 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6729 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6730 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6731 int lbl_key = lbl->key;
6734 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6735 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6737 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6738 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6739 __FUNCTION__,__LINE__);
6743 /* switch(size) { */
6745 /* genc16bit2lit(left, lit, 0); */
6747 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6752 if((AOP_TYPE(left) == AOP_DIR) &&
6753 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6755 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6756 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6758 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6760 switch (lit & 0xff) {
6762 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6765 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6766 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6767 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6771 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6772 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6773 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6774 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6778 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6779 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6784 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6787 if(AOP_TYPE(result) == AOP_CRY) {
6788 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6793 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6795 /* fix me. probably need to check result size too */
6796 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6801 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6802 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6809 if(res_offset < res_size-1)
6814 } else if(AOP_TYPE(right) == AOP_REG &&
6815 AOP_TYPE(left) != AOP_DIR){
6818 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6819 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6820 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6827 if(res_offset < res_size-1)
6832 /* right is a pointer reg need both a & b */
6834 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6836 pic16_emitcode("mov","b,%s",l);
6837 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6838 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6843 if(result && preserve_result)
6846 for(i = 0; i < AOP_SIZE(result); i++)
6847 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6850 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6852 if(result && preserve_result)
6853 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6856 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6858 pic16_emitpLabel(lbl->key);
6860 if(result && preserve_result)
6863 for(i = 0; i < AOP_SIZE(result); i++)
6864 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6866 pic16_emitpLabel(lbl_done->key);
6869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6877 /*-----------------------------------------------------------------*/
6878 /* gencjne - compare and jump if not equal */
6879 /*-----------------------------------------------------------------*/
6880 static void gencjne(operand *left, operand *right, iCode *ifx)
6882 symbol *tlbl = newiTempLabel(NULL);
6884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6885 gencjneshort(left, right, lbl);
6887 pic16_emitcode("mov","a,%s",one);
6888 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6889 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6890 pic16_emitcode("clr","a");
6891 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6893 pic16_emitpLabel(lbl->key);
6894 pic16_emitpLabel(tlbl->key);
6900 /*-----------------------------------------------------------------*/
6901 /* is_LitOp - check if operand has to be treated as literal */
6902 /*-----------------------------------------------------------------*/
6903 static bool is_LitOp(operand *op)
6905 return ((AOP_TYPE(op) == AOP_LIT)
6906 || ( (AOP_TYPE(op) == AOP_PCODE)
6907 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6908 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6911 /*-----------------------------------------------------------------*/
6912 /* is_LitAOp - check if operand has to be treated as literal */
6913 /*-----------------------------------------------------------------*/
6914 static bool is_LitAOp(asmop *aop)
6916 return ((aop->type == AOP_LIT)
6917 || ( (aop->type == AOP_PCODE)
6918 && ( (aop->aopu.pcop->type == PO_LITERAL)
6919 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6924 /*-----------------------------------------------------------------*/
6925 /* genCmpEq - generates code for equal to */
6926 /*-----------------------------------------------------------------*/
6927 static void genCmpEq (iCode *ic, iCode *ifx)
6929 operand *left, *right, *result;
6930 symbol *falselbl = newiTempLabel(NULL);
6931 symbol *donelbl = newiTempLabel(NULL);
6933 int preserve_result = 0;
6934 int generate_result = 0;
6936 unsigned long lit = -1;
6940 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6941 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6942 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6944 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6946 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6948 werror(W_POSSBUG2, __FILE__, __LINE__);
6949 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6950 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6954 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6956 operand *tmp = right ;
6961 if (AOP_TYPE(right) == AOP_LIT) {
6962 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6965 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6966 preserve_result = 1;
6968 if(result && AOP_SIZE(result))
6969 generate_result = 1;
6971 if(generate_result && !preserve_result)
6973 for(i = 0; i < AOP_SIZE(result); i++)
6974 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6977 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6978 for(i=0; i < AOP_SIZE(left); i++)
6980 if(AOP_TYPE(left) != AOP_ACC)
6983 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6985 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6987 if(is_LitOp(right)) {
6988 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6989 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6992 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6994 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6999 if(generate_result && preserve_result)
7001 for(i = 0; i < AOP_SIZE(result); i++)
7002 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7006 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7008 if(generate_result && preserve_result)
7009 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7011 if(ifx && IC_TRUE(ifx))
7012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7014 if(ifx && IC_FALSE(ifx))
7015 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7017 pic16_emitpLabel(falselbl->key);
7021 if(ifx && IC_FALSE(ifx))
7022 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7024 if(generate_result && preserve_result)
7026 for(i = 0; i < AOP_SIZE(result); i++)
7027 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7030 pic16_emitpLabel(donelbl->key);
7036 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7037 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7038 pic16_freeAsmop(result,NULL,ic,TRUE);
7044 // old version kept for reference
7046 /*-----------------------------------------------------------------*/
7047 /* genCmpEq - generates code for equal to */
7048 /*-----------------------------------------------------------------*/
7049 static void genCmpEq (iCode *ic, iCode *ifx)
7051 operand *left, *right, *result;
7052 unsigned long lit = 0L;
7054 symbol *falselbl = newiTempLabel(NULL);
7057 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7060 DEBUGpic16_emitcode ("; ifx is non-null","");
7062 DEBUGpic16_emitcode ("; ifx is null","");
7064 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7065 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7066 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7068 size = max(AOP_SIZE(left),AOP_SIZE(right));
7070 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7072 /* if literal, literal on the right or
7073 if the right is in a pointer register and left
7075 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7076 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7077 operand *tmp = right ;
7083 if(ifx && !AOP_SIZE(result)){
7085 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7086 /* if they are both bit variables */
7087 if (AOP_TYPE(left) == AOP_CRY &&
7088 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7089 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7090 if(AOP_TYPE(right) == AOP_LIT){
7091 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7093 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7094 pic16_emitcode("cpl","c");
7095 } else if(lit == 1L) {
7096 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7098 pic16_emitcode("clr","c");
7100 /* AOP_TYPE(right) == AOP_CRY */
7102 symbol *lbl = newiTempLabel(NULL);
7103 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7104 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7105 pic16_emitcode("cpl","c");
7106 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7108 /* if true label then we jump if condition
7110 tlbl = newiTempLabel(NULL);
7111 if ( IC_TRUE(ifx) ) {
7112 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7113 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7115 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7116 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7118 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7121 /* left and right are both bit variables, result is carry */
7124 resolveIfx(&rIfx,ifx);
7126 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7127 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7128 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7129 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7134 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7136 /* They're not both bit variables. Is the right a literal? */
7137 if(AOP_TYPE(right) == AOP_LIT) {
7138 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7143 switch(lit & 0xff) {
7145 if ( IC_TRUE(ifx) ) {
7146 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7148 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7150 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7151 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7155 if ( IC_TRUE(ifx) ) {
7156 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7158 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7160 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7161 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7165 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7167 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7172 /* end of size == 1 */
7176 genc16bit2lit(left,lit,offset);
7179 /* end of size == 2 */
7184 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7185 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7186 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7187 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7190 /* search for patterns that can be optimized */
7192 genc16bit2lit(left,lit,0);
7196 emitSKPZ; // if hi word unequal
7198 emitSKPNZ; // if hi word equal
7200 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7201 genc16bit2lit(left,lit,2);
7204 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7205 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7209 pic16_emitpLabel(falselbl->key);
7218 } else if(AOP_TYPE(right) == AOP_CRY ) {
7219 /* we know the left is not a bit, but that the right is */
7220 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7221 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7222 pic16_popGet(AOP(right),offset));
7223 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7225 /* if the two are equal, then W will be 0 and the Z bit is set
7226 * we could test Z now, or go ahead and check the high order bytes if
7227 * the variable we're comparing is larger than a byte. */
7230 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7232 if ( IC_TRUE(ifx) ) {
7234 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7235 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7238 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7239 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7243 /* They're both variables that are larger than bits */
7246 tlbl = newiTempLabel(NULL);
7249 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7250 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7252 if ( IC_TRUE(ifx) ) {
7256 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7258 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7259 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7263 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7266 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7267 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7272 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7274 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7275 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7279 if(s>1 && IC_TRUE(ifx)) {
7280 pic16_emitpLabel(tlbl->key);
7281 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7285 /* mark the icode as generated */
7290 /* if they are both bit variables */
7291 if (AOP_TYPE(left) == AOP_CRY &&
7292 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7293 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7294 if(AOP_TYPE(right) == AOP_LIT){
7295 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7297 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7298 pic16_emitcode("cpl","c");
7299 } else if(lit == 1L) {
7300 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7302 pic16_emitcode("clr","c");
7304 /* AOP_TYPE(right) == AOP_CRY */
7306 symbol *lbl = newiTempLabel(NULL);
7307 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7308 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7309 pic16_emitcode("cpl","c");
7310 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7313 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7314 pic16_outBitC(result);
7318 genIfxJump (ifx,"c");
7321 /* if the result is used in an arithmetic operation
7322 then put the result in place */
7323 pic16_outBitC(result);
7326 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7327 gencjne(left,right,result,ifx);
7330 gencjne(left,right,newiTempLabel(NULL));
7332 if(IC_TRUE(ifx)->key)
7333 gencjne(left,right,IC_TRUE(ifx)->key);
7335 gencjne(left,right,IC_FALSE(ifx)->key);
7339 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7340 pic16_aopPut(AOP(result),"a",0);
7345 genIfxJump (ifx,"a");
7349 /* if the result is used in an arithmetic operation
7350 then put the result in place */
7352 if (AOP_TYPE(result) != AOP_CRY)
7353 pic16_outAcc(result);
7355 /* leave the result in acc */
7359 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7360 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7361 pic16_freeAsmop(result,NULL,ic,TRUE);
7365 /*-----------------------------------------------------------------*/
7366 /* ifxForOp - returns the icode containing the ifx for operand */
7367 /*-----------------------------------------------------------------*/
7368 static iCode *ifxForOp ( operand *op, iCode *ic )
7372 /* if true symbol then needs to be assigned */
7373 if (IS_TRUE_SYMOP(op))
7376 /* if this has register type condition and
7377 the next instruction is ifx with the same operand
7378 and live to of the operand is upto the ifx only then */
7380 && ic->next->op == IFX
7381 && IC_COND(ic->next)->key == op->key
7382 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7384 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7390 ic->next->op == IFX &&
7391 IC_COND(ic->next)->key == op->key) {
7392 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7397 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7399 ic->next->op == IFX)
7400 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7403 ic->next->op == IFX &&
7404 IC_COND(ic->next)->key == op->key) {
7405 DEBUGpic16_emitcode ("; "," key is okay");
7406 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7407 OP_SYMBOL(op)->liveTo,
7412 /* the code below is completely untested
7413 * it just allows ulong2fs.c compile -- VR */
7416 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7417 __FILE__, __FUNCTION__, __LINE__);
7419 /* if this has register type condition and
7420 the next instruction is ifx with the same operand
7421 and live to of the operand is upto the ifx only then */
7423 ic->next->op == IFX &&
7424 IC_COND(ic->next)->key == op->key &&
7425 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7429 ic->next->op == IFX &&
7430 IC_COND(ic->next)->key == op->key) {
7431 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7435 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7436 __FILE__, __FUNCTION__, __LINE__);
7438 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7443 /*-----------------------------------------------------------------*/
7444 /* genAndOp - for && operation */
7445 /*-----------------------------------------------------------------*/
7446 static void genAndOp (iCode *ic)
7448 operand *left,*right, *result;
7453 /* note here that && operations that are in an
7454 if statement are taken away by backPatchLabels
7455 only those used in arthmetic operations remain */
7456 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7457 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7458 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7460 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7462 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7463 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7464 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7466 /* if both are bit variables */
7467 /* if (AOP_TYPE(left) == AOP_CRY && */
7468 /* AOP_TYPE(right) == AOP_CRY ) { */
7469 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7470 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7471 /* pic16_outBitC(result); */
7473 /* tlbl = newiTempLabel(NULL); */
7474 /* pic16_toBoolean(left); */
7475 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7476 /* pic16_toBoolean(right); */
7477 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7478 /* pic16_outBitAcc(result); */
7481 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7482 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7483 pic16_freeAsmop(result,NULL,ic,TRUE);
7487 /*-----------------------------------------------------------------*/
7488 /* genOrOp - for || operation */
7489 /*-----------------------------------------------------------------*/
7492 modified this code, but it doesn't appear to ever get called
7495 static void genOrOp (iCode *ic)
7497 operand *left,*right, *result;
7502 /* note here that || operations that are in an
7503 if statement are taken away by backPatchLabels
7504 only those used in arthmetic operations remain */
7505 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7506 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7507 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7509 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7511 /* if both are bit variables */
7512 if (AOP_TYPE(left) == AOP_CRY &&
7513 AOP_TYPE(right) == AOP_CRY ) {
7514 pic16_emitcode("clrc","");
7515 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7516 AOP(left)->aopu.aop_dir,
7517 AOP(left)->aopu.aop_dir);
7518 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7519 AOP(right)->aopu.aop_dir,
7520 AOP(right)->aopu.aop_dir);
7521 pic16_emitcode("setc","");
7524 tlbl = newiTempLabel(NULL);
7525 pic16_toBoolean(left);
7527 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7528 pic16_toBoolean(right);
7529 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7531 pic16_outBitAcc(result);
7534 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7535 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7536 pic16_freeAsmop(result,NULL,ic,TRUE);
7539 /*-----------------------------------------------------------------*/
7540 /* isLiteralBit - test if lit == 2^n */
7541 /*-----------------------------------------------------------------*/
7542 static int isLiteralBit(unsigned long lit)
7544 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7545 0x100L,0x200L,0x400L,0x800L,
7546 0x1000L,0x2000L,0x4000L,0x8000L,
7547 0x10000L,0x20000L,0x40000L,0x80000L,
7548 0x100000L,0x200000L,0x400000L,0x800000L,
7549 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7550 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7554 for(idx = 0; idx < 32; idx++)
7560 /*-----------------------------------------------------------------*/
7561 /* continueIfTrue - */
7562 /*-----------------------------------------------------------------*/
7563 static void continueIfTrue (iCode *ic)
7567 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7571 /*-----------------------------------------------------------------*/
7573 /*-----------------------------------------------------------------*/
7574 static void jumpIfTrue (iCode *ic)
7578 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7582 /*-----------------------------------------------------------------*/
7583 /* jmpTrueOrFalse - */
7584 /*-----------------------------------------------------------------*/
7585 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7587 // ugly but optimized by peephole
7590 symbol *nlbl = newiTempLabel(NULL);
7591 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7592 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7593 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7594 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7596 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7597 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7602 /*-----------------------------------------------------------------*/
7603 /* genAnd - code for and */
7604 /*-----------------------------------------------------------------*/
7605 static void genAnd (iCode *ic, iCode *ifx)
7607 operand *left, *right, *result;
7609 unsigned long lit = 0L;
7615 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7616 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7617 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7619 resolveIfx(&rIfx,ifx);
7621 /* if left is a literal & right is not then exchange them */
7622 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7623 AOP_NEEDSACC(left)) {
7624 operand *tmp = right ;
7629 /* if result = right then exchange them */
7630 if(pic16_sameRegs(AOP(result),AOP(right))){
7631 operand *tmp = right ;
7636 /* if right is bit then exchange them */
7637 if (AOP_TYPE(right) == AOP_CRY &&
7638 AOP_TYPE(left) != AOP_CRY){
7639 operand *tmp = right ;
7643 if(AOP_TYPE(right) == AOP_LIT)
7644 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7646 size = AOP_SIZE(result);
7648 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7651 // result = bit & yy;
7652 if (AOP_TYPE(left) == AOP_CRY){
7653 // c = bit & literal;
7654 if(AOP_TYPE(right) == AOP_LIT){
7656 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7659 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7662 if(size && (AOP_TYPE(result) == AOP_CRY)){
7663 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7666 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7670 pic16_emitcode("clr","c");
7673 if (AOP_TYPE(right) == AOP_CRY){
7675 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7676 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7679 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7681 pic16_emitcode("rrc","a");
7682 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7688 pic16_outBitC(result);
7690 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7691 genIfxJump(ifx, "c");
7695 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7696 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7697 if((AOP_TYPE(right) == AOP_LIT) &&
7698 (AOP_TYPE(result) == AOP_CRY) &&
7699 (AOP_TYPE(left) != AOP_CRY)){
7700 int posbit = isLiteralBit(lit);
7704 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7707 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7713 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7714 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7716 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7717 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7720 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7721 size = AOP_SIZE(left);
7724 int bp = posbit, ofs=0;
7731 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7732 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7736 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7737 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7739 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7746 symbol *tlbl = newiTempLabel(NULL);
7747 int sizel = AOP_SIZE(left);
7753 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7755 /* patch provided by Aaron Colwell */
7756 if((posbit = isLiteralBit(bytelit)) != 0) {
7757 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7758 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7759 (posbit-1),0, PO_GPR_REGISTER));
7761 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7762 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7764 if (bytelit == 0xff) {
7765 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7766 * a peephole could optimize it out -- VR */
7767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7769 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7770 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7773 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7774 pic16_popGetLabel(tlbl->key));
7778 /* old code, left here for reference -- VR 09/2004 */
7779 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7781 if((posbit = isLiteralBit(bytelit)) != 0)
7782 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7784 if(bytelit != 0x0FFL)
7785 pic16_emitcode("anl","a,%s",
7786 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7787 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7793 // bit = left & literal
7796 pic16_emitpLabel(tlbl->key);
7798 // if(left & literal)
7801 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7804 pic16_emitpLabel(tlbl->key);
7809 pic16_outBitC(result);
7813 /* if left is same as result */
7814 if(pic16_sameRegs(AOP(result),AOP(left))){
7816 for(;size--; offset++,lit>>=8) {
7817 if(AOP_TYPE(right) == AOP_LIT){
7818 switch(lit & 0xff) {
7820 /* and'ing with 0 has clears the result */
7821 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7822 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7825 /* and'ing with 0xff is a nop when the result and left are the same */
7830 int p = pic16_my_powof2( (~lit) & 0xff );
7832 /* only one bit is set in the literal, so use a bcf instruction */
7833 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7834 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7837 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7838 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7839 if(know_W != (lit&0xff))
7840 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7842 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7847 if (AOP_TYPE(left) == AOP_ACC) {
7848 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7850 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7851 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7858 // left & result in different registers
7859 if(AOP_TYPE(result) == AOP_CRY){
7861 // if(size), result in bit
7862 // if(!size && ifx), conditional oper: if(left & right)
7863 symbol *tlbl = newiTempLabel(NULL);
7864 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7866 pic16_emitcode("setb","c");
7868 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7869 pic16_emitcode("anl","a,%s",
7870 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7871 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7876 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7877 pic16_outBitC(result);
7879 jmpTrueOrFalse(ifx, tlbl);
7881 for(;(size--);offset++) {
7883 // result = left & right
7884 if(AOP_TYPE(right) == AOP_LIT){
7885 int t = (lit >> (offset*8)) & 0x0FFL;
7888 pic16_emitcode("clrf","%s",
7889 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7890 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7893 pic16_emitcode("movf","%s,w",
7894 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7895 pic16_emitcode("movwf","%s",
7896 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7897 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7898 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7901 pic16_emitcode("movlw","0x%x",t);
7902 pic16_emitcode("andwf","%s,w",
7903 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7904 pic16_emitcode("movwf","%s",
7905 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7907 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7908 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7909 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7914 if (AOP_TYPE(left) == AOP_ACC) {
7915 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7916 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7918 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919 pic16_emitcode("andwf","%s,w",
7920 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7922 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7924 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7931 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7932 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7933 pic16_freeAsmop(result,NULL,ic,TRUE);
7936 /*-----------------------------------------------------------------*/
7937 /* genOr - code for or */
7938 /*-----------------------------------------------------------------*/
7939 static void genOr (iCode *ic, iCode *ifx)
7941 operand *left, *right, *result;
7943 unsigned long lit = 0L;
7945 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7948 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7949 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7950 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7952 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7954 /* if left is a literal & right is not then exchange them */
7955 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7956 AOP_NEEDSACC(left)) {
7957 operand *tmp = right ;
7962 /* if result = right then exchange them */
7963 if(pic16_sameRegs(AOP(result),AOP(right))){
7964 operand *tmp = right ;
7969 /* if right is bit then exchange them */
7970 if (AOP_TYPE(right) == AOP_CRY &&
7971 AOP_TYPE(left) != AOP_CRY){
7972 operand *tmp = right ;
7977 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7979 if(AOP_TYPE(right) == AOP_LIT)
7980 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7982 size = AOP_SIZE(result);
7986 if (AOP_TYPE(left) == AOP_CRY){
7987 if(AOP_TYPE(right) == AOP_LIT){
7988 // c = bit & literal;
7990 // lit != 0 => result = 1
7991 if(AOP_TYPE(result) == AOP_CRY){
7993 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7994 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7995 // AOP(result)->aopu.aop_dir,
7996 // AOP(result)->aopu.aop_dir);
7998 continueIfTrue(ifx);
8002 // lit == 0 => result = left
8003 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8005 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8008 if (AOP_TYPE(right) == AOP_CRY){
8009 if(pic16_sameRegs(AOP(result),AOP(left))){
8011 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8012 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8013 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8015 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8016 AOP(result)->aopu.aop_dir,
8017 AOP(result)->aopu.aop_dir);
8018 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8019 AOP(right)->aopu.aop_dir,
8020 AOP(right)->aopu.aop_dir);
8021 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8022 AOP(result)->aopu.aop_dir,
8023 AOP(result)->aopu.aop_dir);
8025 if( AOP_TYPE(result) == AOP_ACC) {
8026 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8027 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8028 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8029 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8033 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8034 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8035 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8036 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8038 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8039 AOP(result)->aopu.aop_dir,
8040 AOP(result)->aopu.aop_dir);
8041 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8042 AOP(right)->aopu.aop_dir,
8043 AOP(right)->aopu.aop_dir);
8044 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8045 AOP(left)->aopu.aop_dir,
8046 AOP(left)->aopu.aop_dir);
8047 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8048 AOP(result)->aopu.aop_dir,
8049 AOP(result)->aopu.aop_dir);
8054 symbol *tlbl = newiTempLabel(NULL);
8055 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8058 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8059 if( AOP_TYPE(right) == AOP_ACC) {
8060 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8062 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8063 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8068 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8069 pic16_emitcode(";XXX setb","c");
8070 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8071 AOP(left)->aopu.aop_dir,tlbl->key+100);
8072 pic16_toBoolean(right);
8073 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8074 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8075 jmpTrueOrFalse(ifx, tlbl);
8079 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8086 pic16_outBitC(result);
8088 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8089 genIfxJump(ifx, "c");
8093 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8094 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8095 if((AOP_TYPE(right) == AOP_LIT) &&
8096 (AOP_TYPE(result) == AOP_CRY) &&
8097 (AOP_TYPE(left) != AOP_CRY)){
8099 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8102 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8104 continueIfTrue(ifx);
8107 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8108 // lit = 0, result = boolean(left)
8110 pic16_emitcode(";XXX setb","c");
8111 pic16_toBoolean(right);
8113 symbol *tlbl = newiTempLabel(NULL);
8114 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8116 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8118 genIfxJump (ifx,"a");
8122 pic16_outBitC(result);
8126 /* if left is same as result */
8127 if(pic16_sameRegs(AOP(result),AOP(left))){
8129 for(;size--; offset++,lit>>=8) {
8130 if(AOP_TYPE(right) == AOP_LIT){
8131 if((lit & 0xff) == 0)
8132 /* or'ing with 0 has no effect */
8135 int p = pic16_my_powof2(lit & 0xff);
8137 /* only one bit is set in the literal, so use a bsf instruction */
8138 pic16_emitpcode(POC_BSF,
8139 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8141 if(know_W != (lit & 0xff))
8142 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8143 know_W = lit & 0xff;
8144 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8149 if (AOP_TYPE(left) == AOP_ACC) {
8150 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8151 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8153 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8154 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8156 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8157 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8163 // left & result in different registers
8164 if(AOP_TYPE(result) == AOP_CRY){
8166 // if(size), result in bit
8167 // if(!size && ifx), conditional oper: if(left | right)
8168 symbol *tlbl = newiTempLabel(NULL);
8169 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8170 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8174 pic16_emitcode(";XXX setb","c");
8176 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8177 pic16_emitcode(";XXX orl","a,%s",
8178 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8184 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8185 pic16_outBitC(result);
8187 jmpTrueOrFalse(ifx, tlbl);
8188 } else for(;(size--);offset++){
8190 // result = left & right
8191 if(AOP_TYPE(right) == AOP_LIT){
8192 int t = (lit >> (offset*8)) & 0x0FFL;
8195 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8196 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8198 // pic16_emitcode("movf","%s,w",
8199 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8200 // pic16_emitcode("movwf","%s",
8201 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8204 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8205 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8206 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8208 // pic16_emitcode("movlw","0x%x",t);
8209 // pic16_emitcode("iorwf","%s,w",
8210 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8211 // pic16_emitcode("movwf","%s",
8212 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8218 // faster than result <- left, anl result,right
8219 // and better if result is SFR
8220 if (AOP_TYPE(left) == AOP_ACC) {
8221 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8222 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8224 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8225 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8227 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8228 // pic16_emitcode("iorwf","%s,w",
8229 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8231 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8232 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8237 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8238 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8239 pic16_freeAsmop(result,NULL,ic,TRUE);
8242 /*-----------------------------------------------------------------*/
8243 /* genXor - code for xclusive or */
8244 /*-----------------------------------------------------------------*/
8245 static void genXor (iCode *ic, iCode *ifx)
8247 operand *left, *right, *result;
8249 unsigned long lit = 0L;
8251 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8254 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8255 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8256 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8258 /* if left is a literal & right is not ||
8259 if left needs acc & right does not */
8260 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8261 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8262 operand *tmp = right ;
8267 /* if result = right then exchange them */
8268 if(pic16_sameRegs(AOP(result),AOP(right))){
8269 operand *tmp = right ;
8274 /* if right is bit then exchange them */
8275 if (AOP_TYPE(right) == AOP_CRY &&
8276 AOP_TYPE(left) != AOP_CRY){
8277 operand *tmp = right ;
8281 if(AOP_TYPE(right) == AOP_LIT)
8282 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8284 size = AOP_SIZE(result);
8288 if (AOP_TYPE(left) == AOP_CRY){
8289 if(AOP_TYPE(right) == AOP_LIT){
8290 // c = bit & literal;
8292 // lit>>1 != 0 => result = 1
8293 if(AOP_TYPE(result) == AOP_CRY){
8295 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8296 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8298 continueIfTrue(ifx);
8301 pic16_emitcode("setb","c");
8305 // lit == 0, result = left
8306 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8308 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8310 // lit == 1, result = not(left)
8311 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8312 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8313 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8314 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8317 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8318 pic16_emitcode("cpl","c");
8325 symbol *tlbl = newiTempLabel(NULL);
8326 if (AOP_TYPE(right) == AOP_CRY){
8328 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8331 int sizer = AOP_SIZE(right);
8333 // if val>>1 != 0, result = 1
8334 pic16_emitcode("setb","c");
8336 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8338 // test the msb of the lsb
8339 pic16_emitcode("anl","a,#0xfe");
8340 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8344 pic16_emitcode("rrc","a");
8346 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8347 pic16_emitcode("cpl","c");
8348 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8353 pic16_outBitC(result);
8355 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8356 genIfxJump(ifx, "c");
8360 if(pic16_sameRegs(AOP(result),AOP(left))){
8361 /* if left is same as result */
8362 for(;size--; offset++) {
8363 if(AOP_TYPE(right) == AOP_LIT){
8364 int t = (lit >> (offset*8)) & 0x0FFL;
8368 if (IS_AOP_PREG(left)) {
8369 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8370 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8371 pic16_aopPut(AOP(result),"a",offset);
8373 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8374 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8375 pic16_emitcode("xrl","%s,%s",
8376 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8377 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8380 if (AOP_TYPE(left) == AOP_ACC)
8381 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8383 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8384 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8386 if (IS_AOP_PREG(left)) {
8387 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8388 pic16_aopPut(AOP(result),"a",offset);
8390 pic16_emitcode("xrl","%s,a",
8391 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8397 // left & result in different registers
8398 if(AOP_TYPE(result) == AOP_CRY){
8400 // if(size), result in bit
8401 // if(!size && ifx), conditional oper: if(left ^ right)
8402 symbol *tlbl = newiTempLabel(NULL);
8403 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8405 pic16_emitcode("setb","c");
8407 if((AOP_TYPE(right) == AOP_LIT) &&
8408 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8409 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8411 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8412 pic16_emitcode("xrl","a,%s",
8413 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8415 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8420 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8421 pic16_outBitC(result);
8423 jmpTrueOrFalse(ifx, tlbl);
8424 } else for(;(size--);offset++){
8426 // result = left & right
8427 if(AOP_TYPE(right) == AOP_LIT){
8428 int t = (lit >> (offset*8)) & 0x0FFL;
8431 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8432 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8433 pic16_emitcode("movf","%s,w",
8434 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8435 pic16_emitcode("movwf","%s",
8436 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8439 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8440 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8441 pic16_emitcode("comf","%s,w",
8442 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8443 pic16_emitcode("movwf","%s",
8444 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8447 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8448 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8449 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8450 pic16_emitcode("movlw","0x%x",t);
8451 pic16_emitcode("xorwf","%s,w",
8452 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8453 pic16_emitcode("movwf","%s",
8454 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8460 // faster than result <- left, anl result,right
8461 // and better if result is SFR
8462 if (AOP_TYPE(left) == AOP_ACC) {
8463 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8464 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8466 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8467 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8468 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8469 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8471 if ( AOP_TYPE(result) != AOP_ACC){
8472 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8473 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8479 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8480 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8481 pic16_freeAsmop(result,NULL,ic,TRUE);
8484 /*-----------------------------------------------------------------*/
8485 /* genInline - write the inline code out */
8486 /*-----------------------------------------------------------------*/
8487 static void genInline (iCode *ic)
8489 char *buffer, *bp, *bp1;
8491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8493 _G.inLine += (!options.asmpeep);
8495 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8496 strcpy(buffer,IC_INLINE(ic));
8498 while((bp1=strstr(bp, "\\n"))) {
8506 /* This is an experimental code for #pragma inline
8507 and is temporarily disabled for 2.5.0 release */
8515 cbuf = Safe_strdup(buffer);
8516 cblen = strlen(buffer)+1;
8517 memset(cbuf, 0, cblen);
8522 if(*bp != '%')*bp1++ = *bp++;
8528 if(i>elementsInSet(asmInlineMap))break;
8531 s = indexSet(asmInlineMap, i);
8532 DEBUGpc("searching symbol s = `%s'", s);
8533 sym = findSym(SymbolTab, NULL, s);
8536 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8538 strcat(bp1, sym->rname);
8544 if(strlen(bp1) > cblen - 16) {
8545 int i = strlen(cbuf);
8547 cbuf = realloc(cbuf, cblen);
8548 memset(cbuf+i, 0, 50);
8554 buffer = Safe_strdup( cbuf );
8561 /* emit each line as a code */
8567 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8575 /* print label, use this special format with NULL directive
8576 * to denote that the argument should not be indented with tab */
8577 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8580 /* advance to end of line (prevent splitting of comments at ':' */
8581 while (*bp && *bp != '\n') {
8589 if ((bp1 != bp) && *bp1)
8590 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8595 _G.inLine -= (!options.asmpeep);
8598 /*-----------------------------------------------------------------*/
8599 /* genRRC - rotate right with carry */
8600 /*-----------------------------------------------------------------*/
8601 static void genRRC (iCode *ic)
8603 operand *left , *result ;
8604 int size, offset = 0, same;
8606 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8608 /* rotate right with carry */
8610 result=IC_RESULT(ic);
8611 pic16_aopOp (left,ic,FALSE);
8612 pic16_aopOp (result,ic,TRUE);
8614 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8616 same = pic16_sameRegs(AOP(result),AOP(left));
8618 size = AOP_SIZE(result);
8620 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8622 /* get the lsb and put it into the carry */
8623 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8630 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8632 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8639 pic16_freeAsmop(left,NULL,ic,TRUE);
8640 pic16_freeAsmop(result,NULL,ic,TRUE);
8643 /*-----------------------------------------------------------------*/
8644 /* genRLC - generate code for rotate left with carry */
8645 /*-----------------------------------------------------------------*/
8646 static void genRLC (iCode *ic)
8648 operand *left , *result ;
8649 int size, offset = 0;
8652 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8653 /* rotate right with carry */
8655 result=IC_RESULT(ic);
8656 pic16_aopOp (left,ic,FALSE);
8657 pic16_aopOp (result,ic,TRUE);
8659 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8661 same = pic16_sameRegs(AOP(result),AOP(left));
8663 /* move it to the result */
8664 size = AOP_SIZE(result);
8666 /* get the msb and put it into the carry */
8667 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8674 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8676 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8684 pic16_freeAsmop(left,NULL,ic,TRUE);
8685 pic16_freeAsmop(result,NULL,ic,TRUE);
8689 /* gpasm can get the highest order bit with HIGH/UPPER
8690 * so the following probably is not needed -- VR */
8692 /*-----------------------------------------------------------------*/
8693 /* genGetHbit - generates code get highest order bit */
8694 /*-----------------------------------------------------------------*/
8695 static void genGetHbit (iCode *ic)
8697 operand *left, *result;
8699 result=IC_RESULT(ic);
8700 pic16_aopOp (left,ic,FALSE);
8701 pic16_aopOp (result,ic,FALSE);
8703 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8704 /* get the highest order byte into a */
8705 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8706 if(AOP_TYPE(result) == AOP_CRY){
8707 pic16_emitcode("rlc","a");
8708 pic16_outBitC(result);
8711 pic16_emitcode("rl","a");
8712 pic16_emitcode("anl","a,#0x01");
8713 pic16_outAcc(result);
8717 pic16_freeAsmop(left,NULL,ic,TRUE);
8718 pic16_freeAsmop(result,NULL,ic,TRUE);
8722 /*-----------------------------------------------------------------*/
8723 /* AccRol - rotate left accumulator by known count */
8724 /*-----------------------------------------------------------------*/
8725 static void AccRol (int shCount)
8727 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8728 shCount &= 0x0007; // shCount : 0..7
8733 pic16_emitcode("rl","a");
8736 pic16_emitcode("rl","a");
8737 pic16_emitcode("rl","a");
8740 pic16_emitcode("swap","a");
8741 pic16_emitcode("rr","a");
8744 pic16_emitcode("swap","a");
8747 pic16_emitcode("swap","a");
8748 pic16_emitcode("rl","a");
8751 pic16_emitcode("rr","a");
8752 pic16_emitcode("rr","a");
8755 pic16_emitcode("rr","a");
8761 /*-----------------------------------------------------------------*/
8762 /* AccLsh - left shift accumulator by known count */
8763 /*-----------------------------------------------------------------*/
8764 static void AccLsh (int shCount, int doMask)
8766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8772 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8775 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8776 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8779 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8780 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8783 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8786 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8787 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8790 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8791 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8794 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8798 /* no masking is required in genPackBits */
8799 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8803 /*-----------------------------------------------------------------*/
8804 /* AccRsh - right shift accumulator by known count */
8805 /*-----------------------------------------------------------------*/
8806 static void AccRsh (int shCount, int andmask)
8808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8813 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8816 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8817 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8820 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8821 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8824 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8827 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8828 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8831 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8832 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8835 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8840 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8842 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8846 /*-----------------------------------------------------------------*/
8847 /* AccSRsh - signed right shift accumulator by known count */
8848 /*-----------------------------------------------------------------*/
8849 static void AccSRsh (int shCount)
8852 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8855 pic16_emitcode("mov","c,acc.7");
8856 pic16_emitcode("rrc","a");
8857 } else if(shCount == 2){
8858 pic16_emitcode("mov","c,acc.7");
8859 pic16_emitcode("rrc","a");
8860 pic16_emitcode("mov","c,acc.7");
8861 pic16_emitcode("rrc","a");
8863 tlbl = newiTempLabel(NULL);
8864 /* rotate right accumulator */
8865 AccRol(8 - shCount);
8866 /* and kill the higher order bits */
8867 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8868 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8869 pic16_emitcode("orl","a,#0x%02x",
8870 (unsigned char)~SRMask[shCount]);
8871 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8877 /*-----------------------------------------------------------------*/
8878 /* shiftR1Left2Result - shift right one byte from left to result */
8879 /*-----------------------------------------------------------------*/
8880 static void shiftR1Left2ResultSigned (operand *left, int offl,
8881 operand *result, int offr,
8886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8888 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8892 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8894 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8896 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8897 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8903 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8905 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8907 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8911 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8917 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8920 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8923 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8924 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8925 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8927 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8928 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8934 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8935 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8936 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8937 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8949 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8950 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8957 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8958 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8959 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8960 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8965 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8967 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8973 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8974 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8975 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8980 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8988 /*-----------------------------------------------------------------*/
8989 /* shiftR1Left2Result - shift right one byte from left to result */
8990 /*-----------------------------------------------------------------*/
8991 static void shiftR1Left2Result (operand *left, int offl,
8992 operand *result, int offr,
8993 int shCount, int sign)
8997 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8999 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9001 /* Copy the msb into the carry if signed. */
9003 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9013 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9015 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9016 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9025 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9036 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9040 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9042 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9046 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9047 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9048 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9052 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9053 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9056 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9061 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9062 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9064 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9065 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9071 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9072 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9081 /*-----------------------------------------------------------------*/
9082 /* shiftL1Left2Result - shift left one byte from left to result */
9083 /*-----------------------------------------------------------------*/
9084 static void shiftL1Left2Result (operand *left, int offl,
9085 operand *result, int offr, int shCount)
9090 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9092 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9093 DEBUGpic16_emitcode ("; ***","same = %d",same);
9094 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9096 /* shift left accumulator */
9097 //AccLsh(shCount, 1); // don't comment out just yet...
9098 // pic16_aopPut(AOP(result),"a",offr);
9102 /* Shift left 1 bit position */
9103 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9105 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9107 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9108 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9113 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9114 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9119 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9120 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9126 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9127 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9130 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9131 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9132 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9133 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9136 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9137 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9138 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9139 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9144 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9145 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9149 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9154 /*-----------------------------------------------------------------*/
9155 /* movLeft2Result - move byte from left to result */
9156 /*-----------------------------------------------------------------*/
9157 static void movLeft2Result (operand *left, int offl,
9158 operand *result, int offr)
9161 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9162 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9163 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9165 if (*l == '@' && (IS_AOP_PREG(result))) {
9166 pic16_emitcode("mov","a,%s",l);
9167 pic16_aopPut(AOP(result),"a",offr);
9169 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9170 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9175 /*-----------------------------------------------------------------*/
9176 /* shiftL2Left2Result - shift left two bytes from left to result */
9177 /*-----------------------------------------------------------------*/
9178 static void shiftL2Left2Result (operand *left, int offl,
9179 operand *result, int offr, int shCount)
9181 int same = pic16_sameRegs(AOP(result), AOP(left));
9184 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9186 if (same && (offl != offr)) { // shift bytes
9189 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9190 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9192 } else { // just treat as different later on
9205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9206 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9207 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9211 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9212 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9218 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9219 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9220 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9221 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9222 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9223 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9224 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9226 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9227 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9231 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9232 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9234 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9235 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9236 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9237 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9238 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9239 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9240 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9243 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9244 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9245 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9246 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9247 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9257 /* note, use a mov/add for the shift since the mov has a
9258 chance of getting optimized out */
9259 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9260 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9261 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9262 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9263 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9267 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9268 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9274 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9275 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9277 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9279 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9280 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9281 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9285 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9286 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9291 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9292 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9293 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9295 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9297 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9298 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9299 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9300 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9301 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9302 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9305 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9306 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9307 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9308 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9309 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9314 /*-----------------------------------------------------------------*/
9315 /* shiftR2Left2Result - shift right two bytes from left to result */
9316 /*-----------------------------------------------------------------*/
9317 static void shiftR2Left2Result (operand *left, int offl,
9318 operand *result, int offr,
9319 int shCount, int sign)
9321 int same = pic16_sameRegs(AOP(result), AOP(left));
9323 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9325 if (same && (offl != offr)) { // shift right bytes
9328 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9329 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9331 } else { // just treat as different later on
9342 /* obtain sign from left operand */
9344 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9349 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9350 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9352 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9353 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9354 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9355 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9360 /* now get sign from already assigned result (avoid BANKSEL) */
9361 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9364 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9365 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9372 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9373 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9374 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9376 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9377 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9378 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9379 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9381 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9382 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9383 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9385 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9386 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9387 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9388 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9389 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9393 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9394 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9398 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9399 pic16_emitpcode(POC_BTFSC,
9400 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9401 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9409 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9410 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9412 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9413 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9414 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9415 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9417 pic16_emitpcode(POC_BTFSC,
9418 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9419 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9421 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9422 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9424 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9426 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9427 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9428 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9429 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9430 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9431 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9432 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9433 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9435 pic16_emitpcode(POC_BTFSC,
9436 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9437 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9439 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9440 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9447 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9448 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9449 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9450 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9453 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9455 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9460 /*-----------------------------------------------------------------*/
9461 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9462 /*-----------------------------------------------------------------*/
9463 static void shiftLLeftOrResult (operand *left, int offl,
9464 operand *result, int offr, int shCount)
9466 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9468 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9469 /* shift left accumulator */
9471 /* or with result */
9472 /* back to result */
9473 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9476 /*-----------------------------------------------------------------*/
9477 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9478 /*-----------------------------------------------------------------*/
9479 static void shiftRLeftOrResult (operand *left, int offl,
9480 operand *result, int offr, int shCount)
9482 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9484 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9485 /* shift right accumulator */
9487 /* or with result */
9488 /* back to result */
9489 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9492 /*-----------------------------------------------------------------*/
9493 /* genlshOne - left shift a one byte quantity by known count */
9494 /*-----------------------------------------------------------------*/
9495 static void genlshOne (operand *result, operand *left, int shCount)
9497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9501 /*-----------------------------------------------------------------*/
9502 /* genlshTwo - left shift two bytes by known amount != 0 */
9503 /*-----------------------------------------------------------------*/
9504 static void genlshTwo (operand *result,operand *left, int shCount)
9508 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9509 size = pic16_getDataSize(result);
9511 /* if shCount >= 8 */
9517 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9519 movLeft2Result(left, LSB, result, MSB16);
9521 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9524 /* 1 <= shCount <= 7 */
9527 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9529 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9533 /*-----------------------------------------------------------------*/
9534 /* shiftLLong - shift left one long from left to result */
9535 /* offr = LSB or MSB16 */
9536 /*-----------------------------------------------------------------*/
9537 static void shiftLLong (operand *left, operand *result, int offr )
9539 int size = AOP_SIZE(result);
9540 int same = pic16_sameRegs(AOP(left),AOP(result));
9543 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9545 if (same && (offr == MSB16)) { //shift one byte
9546 for(i=size-1;i>=MSB16;i--) {
9547 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9548 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9551 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9554 if (size > LSB+offr ){
9556 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9558 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9559 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9563 if(size > MSB16+offr){
9565 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9567 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9568 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9572 if(size > MSB24+offr){
9574 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9576 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9577 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9581 if(size > MSB32+offr){
9583 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9585 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9586 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9590 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9594 /*-----------------------------------------------------------------*/
9595 /* genlshFour - shift four byte by a known amount != 0 */
9596 /*-----------------------------------------------------------------*/
9597 static void genlshFour (operand *result, operand *left, int shCount)
9601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9602 size = AOP_SIZE(result);
9604 /* if shifting more that 3 bytes */
9605 if (shCount >= 24 ) {
9608 /* lowest order of left goes to the highest
9609 order of the destination */
9610 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9612 movLeft2Result(left, LSB, result, MSB32);
9614 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9615 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9616 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9621 /* more than two bytes */
9622 else if ( shCount >= 16 ) {
9623 /* lower order two bytes goes to higher order two bytes */
9625 /* if some more remaining */
9627 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9629 movLeft2Result(left, MSB16, result, MSB32);
9630 movLeft2Result(left, LSB, result, MSB24);
9632 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9633 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9637 /* if more than 1 byte */
9638 else if ( shCount >= 8 ) {
9639 /* lower order three bytes goes to higher order three bytes */
9643 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9645 movLeft2Result(left, LSB, result, MSB16);
9647 else{ /* size = 4 */
9649 movLeft2Result(left, MSB24, result, MSB32);
9650 movLeft2Result(left, MSB16, result, MSB24);
9651 movLeft2Result(left, LSB, result, MSB16);
9652 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9654 else if(shCount == 1)
9655 shiftLLong(left, result, MSB16);
9657 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9658 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9659 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9660 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9665 /* 1 <= shCount <= 7 */
9666 else if(shCount <= 3)
9668 shiftLLong(left, result, LSB);
9669 while(--shCount >= 1)
9670 shiftLLong(result, result, LSB);
9672 /* 3 <= shCount <= 7, optimize */
9674 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9675 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9676 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9680 /*-----------------------------------------------------------------*/
9681 /* genLeftShiftLiteral - left shifting by known count */
9682 /*-----------------------------------------------------------------*/
9683 void pic16_genLeftShiftLiteral (operand *left,
9688 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9692 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9693 pic16_freeAsmop(right,NULL,ic,TRUE);
9695 pic16_aopOp(left,ic,FALSE);
9696 pic16_aopOp(result,ic,TRUE);
9698 size = getSize(operandType(result));
9701 pic16_emitcode("; shift left ","result %d, left %d",size,
9705 /* I suppose that the left size >= result size */
9708 movLeft2Result(left, size, result, size);
9712 else if(shCount >= (size * 8))
9714 pic16_aopPut(AOP(result),zero,size);
9718 genlshOne (result,left,shCount);
9723 genlshTwo (result,left,shCount);
9727 genlshFour (result,left,shCount);
9731 pic16_freeAsmop(left,NULL,ic,TRUE);
9732 pic16_freeAsmop(result,NULL,ic,TRUE);
9735 /*-----------------------------------------------------------------*
9736 * genMultiAsm - repeat assembly instruction for size of register.
9737 * if endian == 1, then the high byte (i.e base address + size of
9738 * register) is used first else the low byte is used first;
9739 *-----------------------------------------------------------------*/
9740 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9758 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9764 #if !(USE_GENERIC_SIGNED_SHIFT)
9765 /*-----------------------------------------------------------------*/
9766 /* genLeftShift - generates code for left shifting */
9767 /*-----------------------------------------------------------------*/
9768 static void genLeftShift (iCode *ic)
9770 operand *left,*right, *result;
9773 symbol *tlbl , *tlbl1;
9776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9778 right = IC_RIGHT(ic);
9780 result = IC_RESULT(ic);
9782 pic16_aopOp(right,ic,FALSE);
9784 /* if the shift count is known then do it
9785 as efficiently as possible */
9786 if (AOP_TYPE(right) == AOP_LIT) {
9787 pic16_genLeftShiftLiteral (left,right,result,ic);
9791 /* shift count is unknown then we have to form
9792 * a loop. Get the loop count in WREG : Note: we take
9793 * only the lower order byte since shifting
9794 * more than 32 bits make no sense anyway, ( the
9795 * largest size of an object can be only 32 bits ) */
9797 pic16_aopOp(left,ic,FALSE);
9798 pic16_aopOp(result,ic,FALSE);
9800 /* now move the left to the result if they are not the
9801 * same, and if size > 1,
9802 * and if right is not same to result (!!!) -- VR */
9803 if (!pic16_sameRegs(AOP(left),AOP(result))
9804 && (AOP_SIZE(result) > 1)) {
9806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9808 size = AOP_SIZE(result);
9813 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9814 if (*l == '@' && (IS_AOP_PREG(result))) {
9816 pic16_emitcode("mov","a,%s",l);
9817 pic16_aopPut(AOP(result),"a",offset);
9821 /* we don't know if left is a literal or a register, take care -- VR */
9822 pic16_mov2f(AOP(result), AOP(left), offset);
9828 size = AOP_SIZE(result);
9830 /* if it is only one byte then */
9832 if(optimized_for_speed) {
9833 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9834 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9835 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9838 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9839 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9840 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9841 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9842 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9843 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9844 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9847 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9849 tlbl = newiTempLabel(NULL);
9852 /* this is already done, why change it? */
9853 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9854 pic16_mov2f(AOP(result), AOP(left), 0);
9858 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9859 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9860 pic16_emitpLabel(tlbl->key);
9861 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9862 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9864 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9869 if (pic16_sameRegs(AOP(left),AOP(result))) {
9871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9873 tlbl = newiTempLabel(NULL);
9874 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9875 genMultiAsm(POC_RRCF, result, size,1);
9876 pic16_emitpLabel(tlbl->key);
9877 genMultiAsm(POC_RLCF, result, size,0);
9878 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9880 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9884 //tlbl = newiTempLabel(NULL);
9886 //tlbl1 = newiTempLabel(NULL);
9888 //reAdjustPreg(AOP(result));
9890 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9891 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9892 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9894 //pic16_emitcode("add","a,acc");
9895 //pic16_aopPut(AOP(result),"a",offset++);
9897 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9899 // pic16_emitcode("rlc","a");
9900 // pic16_aopPut(AOP(result),"a",offset++);
9902 //reAdjustPreg(AOP(result));
9904 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9905 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9908 tlbl = newiTempLabel(NULL);
9909 tlbl1= newiTempLabel(NULL);
9911 size = AOP_SIZE(result);
9914 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9916 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9918 /* offset should be 0, 1 or 3 */
9920 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9922 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9924 pic16_emitpcode(POC_MOVWF, pctemp);
9927 pic16_emitpLabel(tlbl->key);
9930 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9932 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9934 pic16_emitpcode(POC_DECFSZ, pctemp);
9935 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9936 pic16_emitpLabel(tlbl1->key);
9938 pic16_popReleaseTempReg(pctemp,1);
9942 pic16_freeAsmop (right,NULL,ic,TRUE);
9943 pic16_freeAsmop(left,NULL,ic,TRUE);
9944 pic16_freeAsmop(result,NULL,ic,TRUE);
9950 #error old code (left here for reference)
9951 /*-----------------------------------------------------------------*/
9952 /* genLeftShift - generates code for left shifting */
9953 /*-----------------------------------------------------------------*/
9954 static void genLeftShift (iCode *ic)
9956 operand *left,*right, *result;
9959 symbol *tlbl , *tlbl1;
9962 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9964 right = IC_RIGHT(ic);
9966 result = IC_RESULT(ic);
9968 pic16_aopOp(right,ic,FALSE);
9970 /* if the shift count is known then do it
9971 as efficiently as possible */
9972 if (AOP_TYPE(right) == AOP_LIT) {
9973 pic16_genLeftShiftLiteral (left,right,result,ic);
9977 /* shift count is unknown then we have to form
9978 a loop get the loop count in B : Note: we take
9979 only the lower order byte since shifting
9980 more that 32 bits make no sense anyway, ( the
9981 largest size of an object can be only 32 bits ) */
9984 pic16_aopOp(left,ic,FALSE);
9985 pic16_aopOp(result,ic,FALSE);
9987 /* now move the left to the result if they are not the
9989 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9990 AOP_SIZE(result) > 1) {
9992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9994 size = AOP_SIZE(result);
9997 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9998 if (*l == '@' && (IS_AOP_PREG(result))) {
10000 pic16_emitcode("mov","a,%s",l);
10001 pic16_aopPut(AOP(result),"a",offset);
10004 /* we don't know if left is a literal or a register, take care -- VR */
10005 pic16_mov2f(AOP(result), AOP(left), offset);
10011 size = AOP_SIZE(result);
10013 /* if it is only one byte then */
10015 if(optimized_for_speed) {
10016 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10017 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10018 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10019 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10021 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10022 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10023 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10024 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10025 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10026 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10027 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10030 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10032 tlbl = newiTempLabel(NULL);
10033 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10034 pic16_mov2f(AOP(result), AOP(left), 0);
10036 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10037 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10040 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10041 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10042 pic16_emitpLabel(tlbl->key);
10043 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10044 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10046 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10051 if (pic16_sameRegs(AOP(left),AOP(result))) {
10053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10055 tlbl = newiTempLabel(NULL);
10056 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10057 genMultiAsm(POC_RRCF, result, size,1);
10058 pic16_emitpLabel(tlbl->key);
10059 genMultiAsm(POC_RLCF, result, size,0);
10060 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10062 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10066 //tlbl = newiTempLabel(NULL);
10068 //tlbl1 = newiTempLabel(NULL);
10070 //reAdjustPreg(AOP(result));
10072 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10073 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10074 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10076 //pic16_emitcode("add","a,acc");
10077 //pic16_aopPut(AOP(result),"a",offset++);
10079 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10081 // pic16_emitcode("rlc","a");
10082 // pic16_aopPut(AOP(result),"a",offset++);
10084 //reAdjustPreg(AOP(result));
10086 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10087 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10090 tlbl = newiTempLabel(NULL);
10091 tlbl1= newiTempLabel(NULL);
10093 size = AOP_SIZE(result);
10096 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10100 /* offset should be 0, 1 or 3 */
10102 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10104 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10106 pic16_emitpcode(POC_MOVWF, pctemp);
10109 pic16_emitpLabel(tlbl->key);
10112 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10114 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10116 pic16_emitpcode(POC_DECFSZ, pctemp);
10117 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10118 pic16_emitpLabel(tlbl1->key);
10120 pic16_popReleaseTempReg(pctemp,1);
10124 pic16_freeAsmop (right,NULL,ic,TRUE);
10125 pic16_freeAsmop(left,NULL,ic,TRUE);
10126 pic16_freeAsmop(result,NULL,ic,TRUE);
10130 /*-----------------------------------------------------------------*/
10131 /* genrshOne - right shift a one byte quantity by known count */
10132 /*-----------------------------------------------------------------*/
10133 static void genrshOne (operand *result, operand *left,
10134 int shCount, int sign)
10136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10137 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10140 /*-----------------------------------------------------------------*/
10141 /* genrshTwo - right shift two bytes by known amount != 0 */
10142 /*-----------------------------------------------------------------*/
10143 static void genrshTwo (operand *result,operand *left,
10144 int shCount, int sign)
10146 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10147 /* if shCount >= 8 */
10148 if (shCount >= 8) {
10151 shiftR1Left2Result(left, MSB16, result, LSB,
10154 movLeft2Result(left, MSB16, result, LSB);
10156 pic16_addSign (result, 1, sign);
10159 /* 1 <= shCount <= 7 */
10161 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10164 /*-----------------------------------------------------------------*/
10165 /* shiftRLong - shift right one long from left to result */
10166 /* offl = LSB or MSB16 */
10167 /*-----------------------------------------------------------------*/
10168 static void shiftRLong (operand *left, int offl,
10169 operand *result, int sign)
10171 int size = AOP_SIZE(result);
10172 int same = pic16_sameRegs(AOP(left),AOP(result));
10174 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10176 if (same && (offl == MSB16)) { //shift one byte right
10177 for(i=MSB16;i<size;i++) {
10178 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10179 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10184 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10190 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10192 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10196 if(offl == MSB16) {
10197 /* add sign of "a" */
10198 pic16_addSign(result, MSB32, sign);
10202 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10204 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10205 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10209 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10211 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10212 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10216 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10219 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10220 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10225 /*-----------------------------------------------------------------*/
10226 /* genrshFour - shift four byte by a known amount != 0 */
10227 /*-----------------------------------------------------------------*/
10228 static void genrshFour (operand *result, operand *left,
10229 int shCount, int sign)
10231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10232 /* if shifting more that 3 bytes */
10233 if(shCount >= 24 ) {
10236 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10238 movLeft2Result(left, MSB32, result, LSB);
10240 pic16_addSign(result, MSB16, sign);
10242 else if(shCount >= 16){
10245 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10247 movLeft2Result(left, MSB24, result, LSB);
10248 movLeft2Result(left, MSB32, result, MSB16);
10250 pic16_addSign(result, MSB24, sign);
10252 else if(shCount >= 8){
10255 shiftRLong(left, MSB16, result, sign);
10256 else if(shCount == 0){
10257 movLeft2Result(left, MSB16, result, LSB);
10258 movLeft2Result(left, MSB24, result, MSB16);
10259 movLeft2Result(left, MSB32, result, MSB24);
10260 pic16_addSign(result, MSB32, sign);
10262 else{ //shcount >= 2
10263 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10264 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10265 /* the last shift is signed */
10266 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10267 pic16_addSign(result, MSB32, sign);
10270 else{ /* 1 <= shCount <= 7 */
10272 shiftRLong(left, LSB, result, sign);
10274 shiftRLong(result, LSB, result, sign);
10277 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10278 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10279 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10284 /*-----------------------------------------------------------------*/
10285 /* genRightShiftLiteral - right shifting by known count */
10286 /*-----------------------------------------------------------------*/
10287 static void genRightShiftLiteral (operand *left,
10293 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10294 int lsize,res_size;
10296 pic16_freeAsmop(right,NULL,ic,TRUE);
10298 pic16_aopOp(left,ic,FALSE);
10299 pic16_aopOp(result,ic,TRUE);
10301 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10304 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10308 lsize = pic16_getDataSize(left);
10309 res_size = pic16_getDataSize(result);
10310 /* test the LEFT size !!! */
10312 /* I suppose that the left size >= result size */
10314 assert (res_size <= lsize);
10315 while (res_size--) {
10316 pic16_mov2f (AOP(result), AOP(left), res_size);
10320 else if(shCount >= (lsize * 8)){
10322 if(res_size == 1) {
10323 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10325 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10326 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10331 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10332 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10333 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10335 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10340 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10345 switch (res_size) {
10347 genrshOne (result,left,shCount,sign);
10351 genrshTwo (result,left,shCount,sign);
10355 genrshFour (result,left,shCount,sign);
10363 pic16_freeAsmop(left,NULL,ic,TRUE);
10364 pic16_freeAsmop(result,NULL,ic,TRUE);
10367 #if !(USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genSignedRightShift - right shift of signed number */
10370 /*-----------------------------------------------------------------*/
10371 static void genSignedRightShift (iCode *ic)
10373 operand *right, *left, *result;
10376 symbol *tlbl, *tlbl1 ;
10379 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10381 /* we do it the hard way put the shift count in b
10382 and loop thru preserving the sign */
10383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10385 right = IC_RIGHT(ic);
10386 left = IC_LEFT(ic);
10387 result = IC_RESULT(ic);
10389 pic16_aopOp(right,ic,FALSE);
10390 pic16_aopOp(left,ic,FALSE);
10391 pic16_aopOp(result,ic,FALSE);
10394 if ( AOP_TYPE(right) == AOP_LIT) {
10395 genRightShiftLiteral (left,right,result,ic,1);
10398 /* shift count is unknown then we have to form
10399 a loop get the loop count in B : Note: we take
10400 only the lower order byte since shifting
10401 more that 32 bits make no sense anyway, ( the
10402 largest size of an object can be only 32 bits ) */
10404 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10405 //pic16_emitcode("inc","b");
10406 //pic16_freeAsmop (right,NULL,ic,TRUE);
10407 //pic16_aopOp(left,ic,FALSE);
10408 //pic16_aopOp(result,ic,FALSE);
10410 /* now move the left to the result if they are not the
10412 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10413 AOP_SIZE(result) > 1) {
10415 size = AOP_SIZE(result);
10419 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10420 if (*l == '@' && IS_AOP_PREG(result)) {
10422 pic16_emitcode("mov","a,%s",l);
10423 pic16_aopPut(AOP(result),"a",offset);
10425 pic16_aopPut(AOP(result),l,offset);
10427 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10428 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10434 /* mov the highest order bit to OVR */
10435 tlbl = newiTempLabel(NULL);
10436 tlbl1= newiTempLabel(NULL);
10438 size = AOP_SIZE(result);
10441 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10443 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10445 /* offset should be 0, 1 or 3 */
10446 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10448 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10450 pic16_emitpcode(POC_MOVWF, pctemp);
10453 pic16_emitpLabel(tlbl->key);
10455 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10456 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10459 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10462 pic16_emitpcode(POC_DECFSZ, pctemp);
10463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10464 pic16_emitpLabel(tlbl1->key);
10466 pic16_popReleaseTempReg(pctemp,1);
10468 size = AOP_SIZE(result);
10470 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10471 pic16_emitcode("rlc","a");
10472 pic16_emitcode("mov","ov,c");
10473 /* if it is only one byte then */
10475 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10477 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10478 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10479 pic16_emitcode("mov","c,ov");
10480 pic16_emitcode("rrc","a");
10481 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10482 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10483 pic16_aopPut(AOP(result),"a",0);
10487 reAdjustPreg(AOP(result));
10488 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10489 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10490 pic16_emitcode("mov","c,ov");
10492 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10494 pic16_emitcode("rrc","a");
10495 pic16_aopPut(AOP(result),"a",offset--);
10497 reAdjustPreg(AOP(result));
10498 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10499 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10504 pic16_freeAsmop(left,NULL,ic,TRUE);
10505 pic16_freeAsmop(result,NULL,ic,TRUE);
10506 pic16_freeAsmop(right,NULL,ic,TRUE);
10510 #if !(USE_GENERIC_SIGNED_SHIFT)
10511 #warning This implementation of genRightShift() is incomplete!
10512 /*-----------------------------------------------------------------*/
10513 /* genRightShift - generate code for right shifting */
10514 /*-----------------------------------------------------------------*/
10515 static void genRightShift (iCode *ic)
10517 operand *right, *left, *result;
10521 symbol *tlbl, *tlbl1 ;
10523 /* if signed then we do it the hard way preserve the
10524 sign bit moving it inwards */
10525 letype = getSpec(operandType(IC_LEFT(ic)));
10526 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10528 if (!SPEC_USIGN(letype)) {
10529 genSignedRightShift (ic);
10533 /* signed & unsigned types are treated the same : i.e. the
10534 signed is NOT propagated inwards : quoting from the
10535 ANSI - standard : "for E1 >> E2, is equivalent to division
10536 by 2**E2 if unsigned or if it has a non-negative value,
10537 otherwise the result is implementation defined ", MY definition
10538 is that the sign does not get propagated */
10540 right = IC_RIGHT(ic);
10541 left = IC_LEFT(ic);
10542 result = IC_RESULT(ic);
10544 pic16_aopOp(right,ic,FALSE);
10546 /* if the shift count is known then do it
10547 as efficiently as possible */
10548 if (AOP_TYPE(right) == AOP_LIT) {
10549 genRightShiftLiteral (left,right,result,ic, 0);
10553 /* shift count is unknown then we have to form
10554 a loop get the loop count in B : Note: we take
10555 only the lower order byte since shifting
10556 more that 32 bits make no sense anyway, ( the
10557 largest size of an object can be only 32 bits ) */
10559 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10560 pic16_emitcode("inc","b");
10561 pic16_aopOp(left,ic,FALSE);
10562 pic16_aopOp(result,ic,FALSE);
10564 /* now move the left to the result if they are not the
10566 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10567 AOP_SIZE(result) > 1) {
10569 size = AOP_SIZE(result);
10572 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10573 if (*l == '@' && IS_AOP_PREG(result)) {
10575 pic16_emitcode("mov","a,%s",l);
10576 pic16_aopPut(AOP(result),"a",offset);
10578 pic16_aopPut(AOP(result),l,offset);
10583 tlbl = newiTempLabel(NULL);
10584 tlbl1= newiTempLabel(NULL);
10585 size = AOP_SIZE(result);
10588 /* if it is only one byte then */
10591 tlbl = newiTempLabel(NULL);
10592 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10593 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10594 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10597 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10598 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10599 pic16_emitpLabel(tlbl->key);
10600 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10601 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10608 reAdjustPreg(AOP(result));
10609 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10610 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10613 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10615 pic16_emitcode("rrc","a");
10616 pic16_aopPut(AOP(result),"a",offset--);
10618 reAdjustPreg(AOP(result));
10620 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10621 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10624 pic16_freeAsmop(left,NULL,ic,TRUE);
10625 pic16_freeAsmop (right,NULL,ic,TRUE);
10626 pic16_freeAsmop(result,NULL,ic,TRUE);
10630 #if (USE_GENERIC_SIGNED_SHIFT)
10631 /*-----------------------------------------------------------------*/
10632 /* genGenericShift - generates code for left or right shifting */
10633 /*-----------------------------------------------------------------*/
10634 static void genGenericShift (iCode *ic, int isShiftLeft) {
10635 operand *left,*right, *result;
10637 int sign, signedCount;
10638 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10639 PIC_OPCODE pos_shift, neg_shift;
10643 right = IC_RIGHT(ic);
10644 left = IC_LEFT(ic);
10645 result = IC_RESULT(ic);
10647 pic16_aopOp(right,ic,FALSE);
10648 pic16_aopOp(left,ic,FALSE);
10649 pic16_aopOp(result,ic,TRUE);
10651 sign = !SPEC_USIGN(operandType (left));
10652 signedCount = !SPEC_USIGN(operandType (right));
10654 /* if the shift count is known then do it
10655 as efficiently as possible */
10656 if (AOP_TYPE(right) == AOP_LIT) {
10657 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10658 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10659 // we should modify right->aopu.aop_lit here!
10660 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10661 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10663 pic16_genLeftShiftLiteral (left,right,result,ic);
10665 genRightShiftLiteral (left,right,result,ic, sign);
10668 } // if (right is literal)
10670 /* shift count is unknown then we have to form a loop.
10671 * Note: we take only the lower order byte since shifting
10672 * more than 32 bits make no sense anyway, ( the
10673 * largest size of an object can be only 32 bits )
10674 * Note: we perform arithmetic shifts if the left operand is
10675 * signed and we do an (effective) right shift, i. e. we
10676 * shift in the sign bit from the left. */
10678 label_complete = newiTempLabel ( NULL );
10679 label_loop_pos = newiTempLabel ( NULL );
10680 label_loop_neg = NULL;
10681 label_negative = NULL;
10682 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10683 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10686 // additional labels needed
10687 label_loop_neg = newiTempLabel ( NULL );
10688 label_negative = newiTempLabel ( NULL );
10691 // copy source to result -- this will effectively truncate the left operand to the size of result!
10692 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10693 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10694 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10695 pic16_mov2f (AOP(result),AOP(left), offset);
10698 // if result is longer than left, fill with zeros (or sign)
10699 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10700 if (sign && AOP_SIZE(left) > 0) {
10701 // shift signed operand -- fill with sign
10702 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10703 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10704 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10705 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10706 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10709 // shift unsigned operand -- fill result with zeros
10710 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10711 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10714 } // if (size mismatch)
10716 pic16_mov2w (AOP(right), 0);
10717 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10718 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10721 // perform a shift by one (shift count is positive)
10722 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10723 // 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])
10724 pic16_emitpLabel (label_loop_pos->key);
10726 if (sign && (pos_shift == POC_RRCF)) {
10727 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10730 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10731 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10732 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10734 // perform a shift by one (shift count is positive)
10735 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10736 // 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])
10737 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10738 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10740 pic16_emitpLabel (label_loop_pos->key);
10741 if (sign && (pos_shift == POC_RRCF)) {
10742 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10745 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10746 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10747 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10748 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10752 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10754 pic16_emitpLabel (label_negative->key);
10755 // perform a shift by -1 (shift count is negative)
10756 // 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)
10758 pic16_emitpLabel (label_loop_neg->key);
10759 if (sign && (neg_shift == POC_RRCF)) {
10760 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10763 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10764 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10765 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10766 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10767 } // if (signedCount)
10769 pic16_emitpLabel (label_complete->key);
10772 pic16_freeAsmop (right,NULL,ic,TRUE);
10773 pic16_freeAsmop(left,NULL,ic,TRUE);
10774 pic16_freeAsmop(result,NULL,ic,TRUE);
10777 static void genLeftShift (iCode *ic) {
10778 genGenericShift (ic, 1);
10781 static void genRightShift (iCode *ic) {
10782 genGenericShift (ic, 0);
10787 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10788 void pic16_loadFSR0(operand *op, int lit)
10790 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10791 if (AOP_TYPE(op) == AOP_LIT) {
10792 /* handle 12 bit integers correctly */
10793 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10794 if ((val & 0x0fff) != val) {
10795 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10796 val, (val & 0x0fff) );
10799 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10801 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10804 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10805 // set up FSR0 with address of result
10806 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10807 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10811 /*----------------------------------------------------------------*/
10812 /* pic16_derefPtr - move one byte from the location ptr points to */
10813 /* to WREG (doWrite == 0) or one byte from WREG */
10814 /* to the location ptr points to (doWrite != 0) */
10815 /*----------------------------------------------------------------*/
10816 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10818 if (!IS_PTR(operandType(ptr)))
10820 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10821 else pic16_mov2w (AOP(ptr), 0);
10825 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10826 /* We might determine pointer type right here: */
10827 p_type = DCL_TYPE(operandType(ptr));
10832 if (!fsr0_setup || !*fsr0_setup)
10834 pic16_loadFSR0( ptr, 0 );
10835 if (fsr0_setup) *fsr0_setup = 1;
10838 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10840 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10844 if (AOP(ptr)->aopu.aop_reg[2]) {
10845 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10846 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10847 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10848 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10849 pic16_mov2w(AOP(ptr), 2);
10850 pic16_callGenericPointerRW(doWrite, 1);
10852 // data pointer (just 2 byte given)
10853 if (!fsr0_setup || !*fsr0_setup)
10855 pic16_loadFSR0( ptr, 0 );
10856 if (fsr0_setup) *fsr0_setup = 1;
10859 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10861 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10866 assert (0 && "invalid pointer type specified");
10871 /*-----------------------------------------------------------------*/
10872 /* genUnpackBits - generates code for unpacking bits */
10873 /*-----------------------------------------------------------------*/
10874 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10877 sym_link *etype, *letype;
10878 int blen=0, bstr=0;
10883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10884 etype = getSpec(operandType(result));
10885 letype = getSpec(operandType(left));
10887 // if(IS_BITFIELD(etype)) {
10888 blen = SPEC_BLEN(etype);
10889 bstr = SPEC_BSTR(etype);
10892 lbstr = SPEC_BSTR( letype );
10894 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10895 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10898 if((blen == 1) && (bstr < 8)
10899 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10900 /* it is a single bit, so use the appropriate bit instructions */
10901 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10903 same = pic16_sameRegs(AOP(left),AOP(result));
10904 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10905 pic16_emitpcode(POC_CLRF, op);
10907 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10908 /* workaround to reduce the extra lfsr instruction */
10909 pic16_emitpcode(POC_BTFSC,
10910 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10912 assert (PIC_IS_DATA_PTR (operandType(left)));
10913 pic16_loadFSR0 (left, 0);
10914 pic16_emitpcode(POC_BTFSC,
10915 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10918 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10919 /* unsigned bitfields result in either 0 or 1 */
10920 pic16_emitpcode(POC_INCF, op);
10922 /* signed bitfields result in either 0 or -1 */
10923 pic16_emitpcode(POC_DECF, op);
10926 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10929 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10935 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10936 // access symbol directly
10937 pic16_mov2w (AOP(left), 0);
10939 pic16_derefPtr (left, ptype, 0, NULL);
10942 /* if we have bitdisplacement then it fits */
10943 /* into this byte completely or if length is */
10944 /* less than a byte */
10945 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10947 /* shift right acc */
10950 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10951 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10953 /* VR -- normally I would use the following, but since we use the hack,
10954 * to avoid the masking from AccRsh, why not mask it right now? */
10957 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10960 /* extend signed bitfields to 8 bits */
10961 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10963 assert (blen + bstr > 0);
10964 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10965 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10970 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10974 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10975 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10976 exit(EXIT_FAILURE);
10982 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10984 int size, offset = 0, leoffset=0 ;
10986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10987 pic16_aopOp(result, ic, TRUE);
10991 size = AOP_SIZE(result);
10992 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10996 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10997 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10998 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11003 if(AOP(left)->aopu.pcop->type == PO_DIR)
11004 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11006 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11009 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11011 // pic16_DumpOp("(result)",result);
11012 if(is_LitAOp(AOP(result))) {
11013 pic16_mov2w(AOP(left), offset); // patch 8
11014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11016 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11017 pic16_popGet(AOP(left), offset), //patch 8
11018 pic16_popGet(AOP(result), offset)));
11026 pic16_freeAsmop(result,NULL,ic,TRUE);
11031 /*-----------------------------------------------------------------*/
11032 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11033 /*-----------------------------------------------------------------*/
11034 static void genNearPointerGet (operand *left,
11038 // asmop *aop = NULL;
11039 //regs *preg = NULL ;
11040 sym_link *rtype, *retype;
11041 sym_link *ltype, *letype;
11045 rtype = operandType(result);
11046 retype= getSpec(rtype);
11047 ltype = operandType(left);
11048 letype= getSpec(ltype);
11050 pic16_aopOp(left,ic,FALSE);
11052 // pic16_DumpOp("(left)",left);
11053 // pic16_DumpOp("(result)",result);
11055 /* if left is rematerialisable and
11056 * result is not bit variable type and
11057 * the left is pointer to data space i.e
11058 * lower 128 bytes of space */
11060 if (AOP_TYPE(left) == AOP_PCODE
11061 && !IS_BITFIELD(retype)
11062 && DCL_TYPE(ltype) == POINTER) {
11064 genDataPointerGet (left,result,ic);
11065 pic16_freeAsmop(left, NULL, ic, TRUE);
11069 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11070 pic16_aopOp (result,ic,TRUE);
11072 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11075 if(IS_BITFIELD( retype )
11076 && (SPEC_BLEN(operandType(result))==1)
11080 int bitstrt, bytestrt;
11082 /* if this is bitfield of size 1, see if we are checking the value
11083 * of a single bit in an if-statement,
11084 * if yes, then don't generate usual code, but execute the
11085 * genIfx directly -- VR */
11089 /* CHECK: if next iCode is IFX
11090 * and current result operand is nextic's conditional operand
11091 * and current result operand live ranges ends at nextic's key number
11093 if((nextic->op == IFX)
11094 && (result == IC_COND(nextic))
11095 && (OP_LIVETO(result) == nextic->seq)
11096 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11098 /* everything is ok then */
11099 /* find a way to optimize the genIfx iCode */
11101 bytestrt = SPEC_BSTR(operandType(result))/8;
11102 bitstrt = SPEC_BSTR(operandType(result))%8;
11104 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11106 genIfxpCOpJump(nextic, jop);
11108 pic16_freeAsmop(left, NULL, ic, TRUE);
11109 pic16_freeAsmop(result, NULL, ic, TRUE);
11115 /* if bitfield then unpack the bits */
11116 if (IS_BITFIELD(letype))
11117 genUnpackBits (result, left, NULL, POINTER);
11119 /* we have can just get the values */
11120 int size = AOP_SIZE(result);
11123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11125 pic16_loadFSR0( left, 0 );
11129 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11130 pic16_popGet(AOP(result), offset++)));
11132 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11133 pic16_popGet(AOP(result), offset++)));
11139 /* now some housekeeping stuff */
11141 /* we had to allocate for this iCode */
11142 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11143 pic16_freeAsmop(NULL,aop,ic,TRUE);
11145 /* we did not allocate which means left
11146 * already in a pointer register, then
11147 * if size > 0 && this could be used again
11148 * we have to point it back to where it
11150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11151 if (AOP_SIZE(result) > 1
11152 && !OP_SYMBOL(left)->remat
11153 && ( OP_SYMBOL(left)->liveTo > ic->seq
11155 // int size = AOP_SIZE(result) - 1;
11157 // pic16_emitcode("dec","%s",rname);
11163 pic16_freeAsmop(left,NULL,ic,TRUE);
11164 pic16_freeAsmop(result,NULL,ic,TRUE);
11167 /*-----------------------------------------------------------------*/
11168 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11169 /*-----------------------------------------------------------------*/
11170 static void genPagedPointerGet (operand *left,
11175 regs *preg = NULL ;
11177 sym_link *rtype, *retype;
11179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11181 rtype = operandType(result);
11182 retype= getSpec(rtype);
11184 pic16_aopOp(left,ic,FALSE);
11186 /* if the value is already in a pointer register
11187 then don't need anything more */
11188 if (!AOP_INPREG(AOP(left))) {
11189 /* otherwise get a free pointer register */
11191 preg = getFreePtr(ic,&aop,FALSE);
11192 pic16_emitcode("mov","%s,%s",
11194 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11195 rname = preg->name ;
11197 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11199 pic16_freeAsmop(left,NULL,ic,TRUE);
11200 pic16_aopOp (result,ic,TRUE);
11202 /* if bitfield then unpack the bits */
11203 if (IS_BITFIELD(retype))
11204 genUnpackBits (result,left,rname,PPOINTER);
11206 /* we have can just get the values */
11207 int size = AOP_SIZE(result);
11212 pic16_emitcode("movx","a,@%s",rname);
11213 pic16_aopPut(AOP(result),"a",offset);
11218 pic16_emitcode("inc","%s",rname);
11222 /* now some housekeeping stuff */
11224 /* we had to allocate for this iCode */
11225 pic16_freeAsmop(NULL,aop,ic,TRUE);
11227 /* we did not allocate which means left
11228 already in a pointer register, then
11229 if size > 0 && this could be used again
11230 we have to point it back to where it
11232 if (AOP_SIZE(result) > 1 &&
11233 !OP_SYMBOL(left)->remat &&
11234 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11236 int size = AOP_SIZE(result) - 1;
11238 pic16_emitcode("dec","%s",rname);
11243 pic16_freeAsmop(result,NULL,ic,TRUE);
11249 /* This code is not adjusted to PIC16 and fails utterly.
11250 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11252 /*-----------------------------------------------------------------*/
11253 /* genFarPointerGet - gget value from far space */
11254 /*-----------------------------------------------------------------*/
11255 static void genFarPointerGet (operand *left,
11256 operand *result, iCode *ic)
11259 sym_link *retype = getSpec(operandType(result));
11261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11263 pic16_aopOp(left,ic,FALSE);
11265 /* if the operand is already in dptr
11266 then we do nothing else we move the value to dptr */
11267 if (AOP_TYPE(left) != AOP_STR) {
11268 /* if this is remateriazable */
11269 if (AOP_TYPE(left) == AOP_IMMD)
11270 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11271 else { /* we need to get it byte by byte */
11272 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11273 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11274 if (options.model == MODEL_FLAT24)
11276 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11280 /* so dptr know contains the address */
11281 pic16_freeAsmop(left,NULL,ic,TRUE);
11282 pic16_aopOp(result,ic,TRUE);
11284 /* if bit then unpack */
11285 if (IS_BITFIELD(retype))
11286 genUnpackBits(result,left,"dptr",FPOINTER);
11288 size = AOP_SIZE(result);
11292 pic16_emitcode("movx","a,@dptr");
11293 pic16_aopPut(AOP(result),"a",offset++);
11295 pic16_emitcode("inc","dptr");
11299 pic16_freeAsmop(result,NULL,ic,TRUE);
11304 /*-----------------------------------------------------------------*/
11305 /* genCodePointerGet - get value from code space */
11306 /*-----------------------------------------------------------------*/
11307 static void genCodePointerGet (operand *left,
11308 operand *result, iCode *ic)
11311 sym_link *retype = getSpec(operandType(result));
11313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11315 pic16_aopOp(left,ic,FALSE);
11317 /* if the operand is already in dptr
11318 then we do nothing else we move the value to dptr */
11319 if (AOP_TYPE(left) != AOP_STR) {
11320 /* if this is remateriazable */
11321 if (AOP_TYPE(left) == AOP_IMMD)
11322 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11323 else { /* we need to get it byte by byte */
11324 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11325 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11326 if (options.model == MODEL_FLAT24)
11328 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11332 /* so dptr know contains the address */
11333 pic16_freeAsmop(left,NULL,ic,TRUE);
11334 pic16_aopOp(result,ic,FALSE);
11336 /* if bit then unpack */
11337 if (IS_BITFIELD(retype))
11338 genUnpackBits(result,left,"dptr",CPOINTER);
11340 size = AOP_SIZE(result);
11344 pic16_emitcode("clr","a");
11345 pic16_emitcode("movc","a,@a+dptr");
11346 pic16_aopPut(AOP(result),"a",offset++);
11348 pic16_emitcode("inc","dptr");
11352 pic16_freeAsmop(result,NULL,ic,TRUE);
11357 /*-----------------------------------------------------------------*/
11358 /* genGenPointerGet - gget value from generic pointer space */
11359 /*-----------------------------------------------------------------*/
11360 static void genGenPointerGet (operand *left,
11361 operand *result, iCode *ic)
11363 int size, offset, lit;
11364 sym_link *retype = getSpec(operandType(result));
11366 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11367 pic16_aopOp(left,ic,FALSE);
11368 pic16_aopOp(result,ic,FALSE);
11369 size = AOP_SIZE(result);
11371 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11373 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11375 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11376 // load FSR0 from immediate
11377 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11379 // pic16_loadFSR0( left );
11384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11386 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11393 else { /* we need to get it byte by byte */
11394 // set up FSR0 with address from left
11395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11396 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11402 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11404 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11411 /* if bit then unpack */
11412 if (IS_BITFIELD(retype))
11413 genUnpackBits(result,left,"BAD",GPOINTER);
11416 pic16_freeAsmop(left,NULL,ic,TRUE);
11417 pic16_freeAsmop(result,NULL,ic,TRUE);
11423 /*-----------------------------------------------------------------*/
11424 /* genGenPointerGet - gget value from generic pointer space */
11425 /*-----------------------------------------------------------------*/
11426 static void genGenPointerGet (operand *left,
11427 operand *result, iCode *ic)
11429 int size, offset, lit;
11430 sym_link *letype = getSpec(operandType(left));
11432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11433 pic16_aopOp(left,ic,FALSE);
11434 pic16_aopOp(result,ic,TRUE);
11435 size = AOP_SIZE(result);
11437 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11439 /* if bit then unpack */
11440 if (IS_BITFIELD(letype)) {
11441 genUnpackBits(result,left,"BAD",GPOINTER);
11445 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11447 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11448 // load FSR0 from immediate
11449 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11451 werror(W_POSSBUG2, __FILE__, __LINE__);
11456 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11458 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11465 } else { /* we need to get it byte by byte */
11467 /* set up WREG:PRODL:FSR0L with address from left */
11468 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11469 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11470 pic16_mov2w(AOP(left), 2);
11471 pic16_callGenericPointerRW(0, size);
11473 assignResultValue(result, size, 1);
11479 pic16_freeAsmop(left,NULL,ic,TRUE);
11480 pic16_freeAsmop(result,NULL,ic,TRUE);
11483 /*-----------------------------------------------------------------*/
11484 /* genConstPointerGet - get value from const generic pointer space */
11485 /*-----------------------------------------------------------------*/
11486 static void genConstPointerGet (operand *left,
11487 operand *result, iCode *ic)
11489 //sym_link *retype = getSpec(operandType(result));
11490 // symbol *albl = newiTempLabel(NULL); // patch 15
11491 // symbol *blbl = newiTempLabel(NULL); //
11492 // PIC_OPCODE poc; // patch 15
11496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11497 pic16_aopOp(left,ic,FALSE);
11498 pic16_aopOp(result,ic,TRUE);
11499 size = AOP_SIZE(result);
11501 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11503 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11505 // set up table pointer
11506 if( (AOP_TYPE(left) == AOP_PCODE)
11507 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11508 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11510 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11511 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11512 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11513 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11514 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11515 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11517 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11518 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11519 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11523 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11524 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11528 pic16_freeAsmop(left,NULL,ic,TRUE);
11529 pic16_freeAsmop(result,NULL,ic,TRUE);
11533 /*-----------------------------------------------------------------*/
11534 /* genPointerGet - generate code for pointer get */
11535 /*-----------------------------------------------------------------*/
11536 static void genPointerGet (iCode *ic)
11538 operand *left, *result ;
11539 sym_link *type, *etype;
11544 left = IC_LEFT(ic);
11545 result = IC_RESULT(ic) ;
11547 /* depending on the type of pointer we need to
11548 move it to the correct pointer register */
11549 type = operandType(left);
11550 etype = getSpec(type);
11553 if (IS_PTR_CONST(type))
11555 if (IS_CODEPTR(type))
11557 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11559 /* if left is of type of pointer then it is simple */
11560 if (IS_PTR(type) && !IS_FUNC(type->next))
11561 p_type = DCL_TYPE(type);
11563 /* we have to go by the storage class */
11564 p_type = PTR_TYPE(SPEC_OCLS(etype));
11566 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11568 if (SPEC_OCLS(etype)->codesp ) {
11569 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11570 //p_type = CPOINTER ;
11572 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11573 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11574 /*p_type = FPOINTER ;*/
11576 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11577 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11578 /* p_type = PPOINTER; */
11580 if (SPEC_OCLS(etype) == idata ) {
11581 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11582 /* p_type = IPOINTER; */
11584 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11585 /* p_type = POINTER ; */
11589 /* now that we have the pointer type we assign
11590 the pointer values */
11595 genNearPointerGet (left,result,ic);
11599 genPagedPointerGet(left,result,ic);
11603 /* PICs do not support FAR pointers... */
11604 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11606 genFarPointerGet (left,result,ic);
11611 genConstPointerGet (left,result,ic);
11612 //pic16_emitcodePointerGet (left,result,ic);
11617 if (IS_PTR_CONST(type))
11618 genConstPointerGet (left,result,ic);
11621 genGenPointerGet (left,result,ic);
11625 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11626 "genPointerGet: illegal pointer type");
11631 /*-----------------------------------------------------------------*/
11632 /* genPackBits - generates code for packed bit storage */
11633 /*-----------------------------------------------------------------*/
11634 static void genPackBits (sym_link *etype , operand *result,
11636 char *rname, int p_type)
11642 int shifted_and_masked = 0;
11643 unsigned long lit = (unsigned long)-1;
11646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11647 blen = SPEC_BLEN(etype);
11648 bstr = SPEC_BSTR(etype);
11650 retype = getSpec(operandType(right));
11652 if(AOP_TYPE(right) == AOP_LIT) {
11653 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11655 if((blen == 1) && (bstr < 8)) {
11656 /* it is a single bit, so use the appropriate bit instructions */
11658 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11660 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11661 /* workaround to reduce the extra lfsr instruction */
11663 pic16_emitpcode(POC_BSF,
11664 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11666 pic16_emitpcode(POC_BCF,
11667 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11670 if (PIC_IS_DATA_PTR(operandType(result))) {
11671 pic16_loadFSR0(result, 0);
11672 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11673 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11675 /* get old value */
11676 pic16_derefPtr (result, p_type, 0, NULL);
11677 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11678 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11679 /* write back new value */
11680 pic16_derefPtr (result, p_type, 1, NULL);
11686 /* IORLW below is more efficient */
11687 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11688 lit = (lit & ((1UL << blen) - 1)) << bstr;
11689 shifted_and_masked = 1;
11692 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11693 && IS_BITFIELD(retype)
11694 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11698 rblen = SPEC_BLEN( retype );
11699 rbstr = SPEC_BSTR( retype );
11701 if(IS_BITFIELD(etype)) {
11702 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11703 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11705 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11708 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11710 if(IS_BITFIELD(etype)) {
11711 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11713 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11716 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11720 /* move right to W */
11721 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11724 /* if the bit length is less than or */
11725 /* it exactly fits a byte then */
11726 if((shCnt=SPEC_BSTR(etype))
11727 || SPEC_BLEN(etype) <= 8 ) {
11728 int fsr0_setup = 0;
11730 if (blen != 8 || (bstr % 8) != 0) {
11731 // we need to combine the value with the old value
11732 if(!shifted_and_masked)
11734 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11736 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11737 SPEC_BSTR(etype), SPEC_BLEN(etype));
11739 /* shift left acc, do NOT mask the result again */
11742 /* using PRODH as a temporary register here */
11743 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11746 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11747 || IS_DIRECT(result)) {
11748 /* access symbol directly */
11749 pic16_mov2w (AOP(result), 0);
11751 /* get old value */
11752 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11755 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11756 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11757 (unsigned char)(0xff >> (8-bstr))) ));
11758 if (!shifted_and_masked) {
11759 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11761 /* We have the shifted and masked (literal) right value in `lit' */
11763 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11765 } else { // if (blen == 8 && (bstr % 8) == 0)
11766 if (shifted_and_masked) {
11767 // move right (literal) to WREG (only case where right is not yet in WREG)
11768 pic16_mov2w(AOP(right), (bstr / 8));
11772 /* write new value back */
11773 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11774 || IS_DIRECT(result)) {
11775 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11777 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11786 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11787 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11788 exit(EXIT_FAILURE);
11792 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11793 rLen = SPEC_BLEN(etype)-8;
11795 /* now generate for lengths greater than one byte */
11799 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11805 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11811 pic16_emitcode("movx","@dptr,a");
11816 DEBUGpic16_emitcode(";lcall","__gptrput");
11824 pic16_mov2w(AOP(right), offset++);
11827 /* last last was not complete */
11829 /* save the byte & read byte */
11832 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11833 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11838 pic16_emitcode ("mov","b,a");
11839 pic16_emitcode("movx","a,@dptr");
11843 pic16_emitcode ("push","b");
11844 pic16_emitcode ("push","acc");
11845 pic16_emitcode ("lcall","__gptrget");
11846 pic16_emitcode ("pop","b");
11852 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11854 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11855 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11856 // pic16_emitcode ("orl","a,b");
11859 // if (p_type == GPOINTER)
11860 // pic16_emitcode("pop","b");
11865 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11866 // pic16_emitcode("mov","@%s,a",rname);
11870 pic16_emitcode("movx","@dptr,a");
11874 DEBUGpic16_emitcode(";lcall","__gptrput");
11881 // pic16_freeAsmop(right, NULL, ic, TRUE);
11884 /*-----------------------------------------------------------------*/
11885 /* genDataPointerSet - remat pointer to data space */
11886 /*-----------------------------------------------------------------*/
11887 static void genDataPointerSet(operand *right,
11891 int size, offset = 0, resoffset=0 ;
11893 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11894 pic16_aopOp(right,ic,FALSE);
11896 size = AOP_SIZE(right);
11898 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11901 if ( AOP_TYPE(result) == AOP_PCODE) {
11902 fprintf(stderr,"genDataPointerSet %s, %d\n",
11903 AOP(result)->aopu.pcop->name,
11904 (AOP(result)->aopu.pcop->type == PO_DIR)?
11905 PCOR(AOP(result)->aopu.pcop)->instance:
11906 PCOI(AOP(result)->aopu.pcop)->offset);
11910 if(AOP(result)->aopu.pcop->type == PO_DIR)
11911 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11914 if (AOP_TYPE(right) == AOP_LIT) {
11915 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11916 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11918 pic16_mov2w(AOP(right), offset);
11919 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11925 pic16_freeAsmop(right,NULL,ic,TRUE);
11930 /*-----------------------------------------------------------------*/
11931 /* genNearPointerSet - pic16_emitcode for near pointer put */
11932 /*-----------------------------------------------------------------*/
11933 static void genNearPointerSet (operand *right,
11939 sym_link *ptype = operandType(result);
11940 sym_link *resetype;
11942 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11943 retype= getSpec(operandType(right));
11944 resetype = getSpec(operandType(result));
11946 pic16_aopOp(result,ic,FALSE);
11948 /* if the result is rematerializable &
11949 * in data space & not a bit variable */
11951 /* and result is not a bit variable */
11952 if (AOP_TYPE(result) == AOP_PCODE
11953 // && AOP_TYPE(result) == AOP_IMMD
11954 && DCL_TYPE(ptype) == POINTER
11955 && !IS_BITFIELD(retype)
11956 && !IS_BITFIELD(resetype)) {
11958 genDataPointerSet (right,result,ic);
11959 pic16_freeAsmop(result,NULL,ic,TRUE);
11963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11964 pic16_aopOp(right,ic,FALSE);
11965 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11967 /* if bitfield then unpack the bits */
11968 if (IS_BITFIELD(resetype)) {
11969 genPackBits (resetype, result, right, NULL, POINTER);
11971 /* we have can just get the values */
11972 int size = AOP_SIZE(right);
11975 pic16_loadFSR0(result, 0);
11977 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11979 if (AOP_TYPE(right) == AOP_LIT) {
11980 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11982 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11984 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11986 } else { // no literal
11988 pic16_emitpcode(POC_MOVFF,
11989 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11990 pic16_popCopyReg(&pic16_pc_postinc0)));
11992 pic16_emitpcode(POC_MOVFF,
11993 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11994 pic16_popCopyReg(&pic16_pc_indf0)));
12002 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12003 /* now some housekeeping stuff */
12005 /* we had to allocate for this iCode */
12006 pic16_freeAsmop(NULL,aop,ic,TRUE);
12008 /* we did not allocate which means left
12009 * already in a pointer register, then
12010 * if size > 0 && this could be used again
12011 * we have to point it back to where it
12013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12014 if (AOP_SIZE(right) > 1
12015 && !OP_SYMBOL(result)->remat
12016 && ( OP_SYMBOL(result)->liveTo > ic->seq
12019 int size = AOP_SIZE(right) - 1;
12022 pic16_emitcode("decf","fsr0,f");
12023 //pic16_emitcode("dec","%s",rname);
12027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12030 pic16_freeAsmop(right,NULL,ic,TRUE);
12031 pic16_freeAsmop(result,NULL,ic,TRUE);
12034 /*-----------------------------------------------------------------*/
12035 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12036 /*-----------------------------------------------------------------*/
12037 static void genPagedPointerSet (operand *right,
12042 regs *preg = NULL ;
12046 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12048 retype= getSpec(operandType(right));
12050 pic16_aopOp(result,ic,FALSE);
12052 /* if the value is already in a pointer register
12053 then don't need anything more */
12054 if (!AOP_INPREG(AOP(result))) {
12055 /* otherwise get a free pointer register */
12057 preg = getFreePtr(ic,&aop,FALSE);
12058 pic16_emitcode("mov","%s,%s",
12060 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12061 rname = preg->name ;
12063 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12065 pic16_freeAsmop(result,NULL,ic,TRUE);
12066 pic16_aopOp (right,ic,FALSE);
12068 /* if bitfield then unpack the bits */
12069 if (IS_BITFIELD(retype))
12070 genPackBits (retype,result,right,rname,PPOINTER);
12072 /* we have can just get the values */
12073 int size = AOP_SIZE(right);
12077 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12080 pic16_emitcode("movx","@%s,a",rname);
12083 pic16_emitcode("inc","%s",rname);
12089 /* now some housekeeping stuff */
12091 /* we had to allocate for this iCode */
12092 pic16_freeAsmop(NULL,aop,ic,TRUE);
12094 /* we did not allocate which means left
12095 already in a pointer register, then
12096 if size > 0 && this could be used again
12097 we have to point it back to where it
12099 if (AOP_SIZE(right) > 1 &&
12100 !OP_SYMBOL(result)->remat &&
12101 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12103 int size = AOP_SIZE(right) - 1;
12105 pic16_emitcode("dec","%s",rname);
12110 pic16_freeAsmop(right,NULL,ic,TRUE);
12116 /* This code is not adjusted to PIC16 and fails utterly...
12117 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12119 /*-----------------------------------------------------------------*/
12120 /* genFarPointerSet - set value from far space */
12121 /*-----------------------------------------------------------------*/
12122 static void genFarPointerSet (operand *right,
12123 operand *result, iCode *ic)
12126 sym_link *retype = getSpec(operandType(right));
12128 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12129 pic16_aopOp(result,ic,FALSE);
12131 /* if the operand is already in dptr
12132 then we do nothing else we move the value to dptr */
12133 if (AOP_TYPE(result) != AOP_STR) {
12134 /* if this is remateriazable */
12135 if (AOP_TYPE(result) == AOP_IMMD)
12136 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12137 else { /* we need to get it byte by byte */
12138 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12139 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12140 if (options.model == MODEL_FLAT24)
12142 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12146 /* so dptr know contains the address */
12147 pic16_freeAsmop(result,NULL,ic,TRUE);
12148 pic16_aopOp(right,ic,FALSE);
12150 /* if bit then unpack */
12151 if (IS_BITFIELD(retype))
12152 genPackBits(retype,result,right,"dptr",FPOINTER);
12154 size = AOP_SIZE(right);
12158 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12160 pic16_emitcode("movx","@dptr,a");
12162 pic16_emitcode("inc","dptr");
12166 pic16_freeAsmop(right,NULL,ic,TRUE);
12170 /*-----------------------------------------------------------------*/
12171 /* genGenPointerSet - set value from generic pointer space */
12172 /*-----------------------------------------------------------------*/
12174 static void genGenPointerSet (operand *right,
12175 operand *result, iCode *ic)
12177 int i, size, offset, lit;
12178 sym_link *retype = getSpec(operandType(right));
12180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12182 pic16_aopOp(result,ic,FALSE);
12183 pic16_aopOp(right,ic,FALSE);
12184 size = AOP_SIZE(right);
12187 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12189 /* if the operand is already in dptr
12190 then we do nothing else we move the value to dptr */
12191 if (AOP_TYPE(result) != AOP_STR) {
12192 /* if this is remateriazable */
12193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12194 // WARNING: anythig until "else" is untested!
12195 if (AOP_TYPE(result) == AOP_IMMD) {
12196 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12197 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12198 // load FSR0 from immediate
12199 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12203 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12205 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12211 else { /* we need to get it byte by byte */
12212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12213 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12215 // set up FSR0 with address of result
12216 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12217 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12219 /* hack hack! see if this the FSR. If so don't load W */
12220 if(AOP_TYPE(right) != AOP_ACC) {
12222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12224 if(AOP_TYPE(right) == AOP_LIT)
12227 // note: pic16_popGet handles sign extension
12228 for(i=0;i<size;i++) {
12229 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12231 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12233 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12238 for(i=0;i<size;i++) {
12240 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12241 pic16_popCopyReg(&pic16_pc_postinc0)));
12243 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12244 pic16_popCopyReg(&pic16_pc_indf0)));
12250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12251 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12253 } // if (AOP_TYPE(result) != AOP_IMMD)
12255 } // if (AOP_TYPE(result) != AOP_STR)
12256 /* so dptr know contains the address */
12259 /* if bit then unpack */
12260 if (IS_BITFIELD(retype))
12261 genPackBits(retype,result,right,"dptr",GPOINTER);
12263 size = AOP_SIZE(right);
12266 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12268 // set up FSR0 with address of result
12269 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12270 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12273 if (AOP_TYPE(right) == AOP_LIT) {
12274 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12276 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12278 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12280 } else { // no literal
12282 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12284 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12292 pic16_freeAsmop(right,NULL,ic,TRUE);
12293 pic16_freeAsmop(result,NULL,ic,TRUE);
12297 static void genGenPointerSet (operand *right,
12298 operand *result, iCode *ic)
12301 sym_link *retype = getSpec(operandType(result));
12303 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12305 pic16_aopOp(result,ic,FALSE);
12306 pic16_aopOp(right,ic,FALSE);
12307 size = AOP_SIZE(right);
12309 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12312 /* if bit then unpack */
12313 if (IS_BITFIELD(retype)) {
12314 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12315 genPackBits(retype,result,right,"dptr",GPOINTER);
12319 size = AOP_SIZE(right);
12321 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12324 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12326 /* value of right+0 is placed on stack, which will be retrieved
12327 * by the support function thus restoring the stack. The important
12328 * thing is that there is no need to manually restore stack pointer
12330 pushaop(AOP(right), 0);
12331 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12332 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12333 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12334 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12336 /* load address to write to in WREG:FSR0H:FSR0L */
12337 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12338 pic16_popCopyReg(&pic16_pc_fsr0l)));
12339 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12340 pic16_popCopyReg(&pic16_pc_prodl)));
12341 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12343 pic16_callGenericPointerRW(1, size);
12346 pic16_freeAsmop(right,NULL,ic,TRUE);
12347 pic16_freeAsmop(result,NULL,ic,TRUE);
12350 /*-----------------------------------------------------------------*/
12351 /* genPointerSet - stores the value into a pointer location */
12352 /*-----------------------------------------------------------------*/
12353 static void genPointerSet (iCode *ic)
12355 operand *right, *result ;
12356 sym_link *type, *etype;
12361 right = IC_RIGHT(ic);
12362 result = IC_RESULT(ic) ;
12364 /* depending on the type of pointer we need to
12365 move it to the correct pointer register */
12366 type = operandType(result);
12367 etype = getSpec(type);
12369 /* if left is of type of pointer then it is simple */
12370 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12371 p_type = DCL_TYPE(type);
12374 /* we have to go by the storage class */
12375 p_type = PTR_TYPE(SPEC_OCLS(etype));
12377 /* if (SPEC_OCLS(etype)->codesp ) { */
12378 /* p_type = CPOINTER ; */
12381 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12382 /* p_type = FPOINTER ; */
12384 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12385 /* p_type = PPOINTER ; */
12387 /* if (SPEC_OCLS(etype) == idata ) */
12388 /* p_type = IPOINTER ; */
12390 /* p_type = POINTER ; */
12393 /* now that we have the pointer type we assign
12394 the pointer values */
12399 genNearPointerSet (right,result,ic);
12403 genPagedPointerSet (right,result,ic);
12407 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12409 genFarPointerSet (right,result,ic);
12414 genGenPointerSet (right,result,ic);
12418 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12419 "genPointerSet: illegal pointer type");
12423 /*-----------------------------------------------------------------*/
12424 /* genIfx - generate code for Ifx statement */
12425 /*-----------------------------------------------------------------*/
12426 static void genIfx (iCode *ic, iCode *popIc)
12428 operand *cond = IC_COND(ic);
12433 pic16_aopOp(cond,ic,FALSE);
12435 /* get the value into acc */
12436 if (AOP_TYPE(cond) != AOP_CRY)
12437 pic16_toBoolean(cond);
12440 /* the result is now in the accumulator */
12441 pic16_freeAsmop(cond,NULL,ic,TRUE);
12443 /* if there was something to be popped then do it */
12447 /* if the condition is a bit variable */
12448 if (isbit && IS_ITEMP(cond) &&
12450 genIfxJump(ic,"c");
12451 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12453 if (isbit && !IS_ITEMP(cond))
12454 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12456 genIfxJump(ic,"a");
12461 /*-----------------------------------------------------------------*/
12462 /* genAddrOf - generates code for address of */
12463 /*-----------------------------------------------------------------*/
12464 static void genAddrOf (iCode *ic)
12466 operand *result, *left;
12468 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12469 pCodeOp *pcop0, *pcop1, *pcop2;
12473 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12475 sym = OP_SYMBOL( IC_LEFT(ic) );
12478 /* get address of symbol on stack */
12479 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12481 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12482 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12485 // operands on stack are accessible via "FSR2 + index" with index
12486 // starting at 2 for arguments and growing from 0 downwards for
12487 // local variables (index == 0 is not assigned so we add one here)
12489 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12492 assert (soffs < 0);
12496 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12497 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12498 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12499 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12500 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12501 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12502 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12508 // if(pic16_debug_verbose) {
12509 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12510 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12513 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12514 size = AOP_SIZE(IC_RESULT(ic));
12516 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12517 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12518 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12521 pic16_emitpcode(POC_MOVLW, pcop0);
12522 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12523 pic16_emitpcode(POC_MOVLW, pcop1);
12524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12525 pic16_emitpcode(POC_MOVLW, pcop2);
12526 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12529 pic16_emitpcode(POC_MOVLW, pcop0);
12530 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12531 pic16_emitpcode(POC_MOVLW, pcop1);
12532 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12534 pic16_emitpcode(POC_MOVLW, pcop0);
12535 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12538 pic16_freeAsmop(left, NULL, ic, FALSE);
12540 pic16_freeAsmop(result,NULL,ic,TRUE);
12545 /*-----------------------------------------------------------------*/
12546 /* genFarFarAssign - assignment when both are in far space */
12547 /*-----------------------------------------------------------------*/
12548 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12550 int size = AOP_SIZE(right);
12553 /* first push the right side on to the stack */
12555 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12557 pic16_emitcode ("push","acc");
12560 pic16_freeAsmop(right,NULL,ic,FALSE);
12561 /* now assign DPTR to result */
12562 pic16_aopOp(result,ic,FALSE);
12563 size = AOP_SIZE(result);
12565 pic16_emitcode ("pop","acc");
12566 pic16_aopPut(AOP(result),"a",--offset);
12568 pic16_freeAsmop(result,NULL,ic,FALSE);
12573 /*-----------------------------------------------------------------*/
12574 /* genAssign - generate code for assignment */
12575 /*-----------------------------------------------------------------*/
12576 static void genAssign (iCode *ic)
12578 operand *result, *right;
12579 sym_link *restype, *rtype;
12580 int size, offset,know_W;
12581 unsigned long lit = 0L;
12583 result = IC_RESULT(ic);
12584 right = IC_RIGHT(ic) ;
12588 /* if they are the same */
12589 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12592 /* reversed order operands are aopOp'ed so that result operand
12593 * is effective in case right is a stack symbol. This maneauver
12594 * allows to use the _G.resDirect flag later */
12595 pic16_aopOp(result,ic,TRUE);
12596 pic16_aopOp(right,ic,FALSE);
12598 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12600 /* if they are the same registers */
12601 if (pic16_sameRegs(AOP(right),AOP(result)))
12604 /* if the result is a bit */
12605 if (AOP_TYPE(result) == AOP_CRY) {
12606 /* if the right size is a literal then
12607 we know what the value is */
12608 if (AOP_TYPE(right) == AOP_LIT) {
12610 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12611 pic16_popGet(AOP(result),0));
12613 if (((int) operandLitValue(right)))
12614 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12615 AOP(result)->aopu.aop_dir,
12616 AOP(result)->aopu.aop_dir);
12618 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12619 AOP(result)->aopu.aop_dir,
12620 AOP(result)->aopu.aop_dir);
12625 /* the right is also a bit variable */
12626 if (AOP_TYPE(right) == AOP_CRY) {
12627 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12628 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12629 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12634 /* we need to or */
12635 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12636 pic16_toBoolean(right);
12638 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12639 //pic16_aopPut(AOP(result),"a",0);
12643 /* bit variables done */
12645 size = AOP_SIZE(result);
12648 /* bit variables done */
12650 size = AOP_SIZE(result);
12651 restype = operandType(result);
12652 rtype = operandType(right);
12655 if(AOP_TYPE(right) == AOP_LIT) {
12656 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12658 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12660 /* patch tag for literals that are cast to pointers */
12661 if (IS_CODEPTR(restype)) {
12662 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12663 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12665 if (IS_GENPTR(restype))
12667 if (IS_CODEPTR(rtype)) {
12668 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12669 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12670 } else if (PIC_IS_DATA_PTR(rtype)) {
12671 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12672 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12673 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12674 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12675 } else if (IS_PTR(rtype)) {
12676 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12677 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12683 unsigned long lit_int;
12688 if(IS_FIXED16X16(operandType(right))) {
12689 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12691 /* take care if literal is a float */
12692 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12693 lit = info.lit_int;
12698 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12699 // sizeof(unsigned long int), sizeof(float));
12702 if (AOP_TYPE(right) == AOP_REG) {
12703 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12705 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12710 /* when do we have to read the program memory?
12711 * - if right itself is a symbol in code space
12712 * (we don't care what it points to if it's a pointer)
12713 * - AND right is not a function (we would want its address)
12715 if(AOP_TYPE(right) != AOP_LIT
12716 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12717 && !IS_FUNC(OP_SYM_TYPE(right))
12718 && !IS_ITEMP(right)) {
12720 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12721 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12723 // set up table pointer
12724 if(is_LitOp(right)) {
12725 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12726 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12727 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12728 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12729 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12730 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12731 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12733 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12734 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12735 pic16_popCopyReg(&pic16_pc_tblptrl)));
12736 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12737 pic16_popCopyReg(&pic16_pc_tblptrh)));
12738 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12739 pic16_popCopyReg(&pic16_pc_tblptru)));
12742 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12743 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12745 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12746 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12747 pic16_popGet(AOP(result),offset)));
12751 /* FIXME: for pointers we need to extend differently (according
12752 * to pointer type DATA/CODE/EEPROM/... :*/
12753 size = getSize(OP_SYM_TYPE(right));
12754 if(AOP_SIZE(result) > size) {
12755 size = AOP_SIZE(result) - size;
12757 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12765 /* VR - What is this?! */
12766 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12769 if(aopIdx(AOP(result),0) == 4) {
12770 /* this is a workaround to save value of right into wreg too,
12771 * value of wreg is going to be used later */
12772 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12773 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12774 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12778 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12782 size = AOP_SIZE(right);
12783 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12786 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12787 if(AOP_TYPE(right) == AOP_LIT) {
12789 if(know_W != (lit&0xff))
12790 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12794 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12798 } else if (AOP_TYPE(right) == AOP_CRY) {
12799 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12801 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12802 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12803 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12805 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12806 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12807 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12811 if(!_G.resDirect) { /* use this aopForSym feature */
12812 if(AOP_TYPE(result) == AOP_ACC) {
12813 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12815 if(AOP_TYPE(right) == AOP_ACC) {
12816 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12818 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12825 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12828 pic16_freeAsmop (right,NULL,ic,FALSE);
12829 pic16_freeAsmop (result,NULL,ic,TRUE);
12832 /*-----------------------------------------------------------------*/
12833 /* genJumpTab - generates code for jump table */
12834 /*-----------------------------------------------------------------*/
12835 static void genJumpTab (iCode *ic)
12840 pCodeOp *jt_offs_hi;
12845 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12846 /* get the condition into accumulator */
12847 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12849 /* multiply by three */
12850 pic16_emitcode("add","a,acc");
12851 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12853 jtab = newiTempLabel(NULL);
12854 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12855 pic16_emitcode("jmp","@a+dptr");
12856 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12859 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12860 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12862 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12863 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12864 pic16_emitpLabel(jtab->key);
12868 jt_offs = pic16_popGetTempReg(0);
12869 jt_offs_hi = pic16_popGetTempReg(1);
12870 jt_label = pic16_popGetLabel (jtab->key);
12871 //fprintf (stderr, "Creating jump table...\n");
12873 // calculate offset into jump table (idx * sizeof (GOTO))
12874 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12875 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12876 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12877 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12878 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12879 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12880 pic16_emitpcode(POC_MOVWF , jt_offs);
12882 // prepare PCLATx (set to first entry in jump table)
12883 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12884 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12885 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12886 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12887 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12889 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12890 pic16_emitpcode(POC_ADDWF , jt_offs);
12891 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12892 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12894 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12896 // release temporaries and prepare jump into table (new PCL --> WREG)
12897 pic16_emitpcode(POC_MOVFW , jt_offs);
12898 pic16_popReleaseTempReg (jt_offs_hi, 1);
12899 pic16_popReleaseTempReg (jt_offs, 0);
12901 // jump into the table
12902 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12904 pic16_emitpLabelFORCE(jtab->key);
12907 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12908 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12910 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12911 /* now generate the jump labels */
12912 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12913 jtab = setNextItem(IC_JTLABELS(ic))) {
12914 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12915 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12918 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12922 /*-----------------------------------------------------------------*/
12923 /* genMixedOperation - gen code for operators between mixed types */
12924 /*-----------------------------------------------------------------*/
12926 TSD - Written for the PIC port - but this unfortunately is buggy.
12927 This routine is good in that it is able to efficiently promote
12928 types to different (larger) sizes. Unfortunately, the temporary
12929 variables that are optimized out by this routine are sometimes
12930 used in other places. So until I know how to really parse the
12931 iCode tree, I'm going to not be using this routine :(.
12933 static int genMixedOperation (iCode *ic)
12936 operand *result = IC_RESULT(ic);
12937 sym_link *ctype = operandType(IC_LEFT(ic));
12938 operand *right = IC_RIGHT(ic);
12944 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12946 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12952 nextright = IC_RIGHT(nextic);
12953 nextleft = IC_LEFT(nextic);
12954 nextresult = IC_RESULT(nextic);
12956 pic16_aopOp(right,ic,FALSE);
12957 pic16_aopOp(result,ic,FALSE);
12958 pic16_aopOp(nextright, nextic, FALSE);
12959 pic16_aopOp(nextleft, nextic, FALSE);
12960 pic16_aopOp(nextresult, nextic, FALSE);
12962 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12964 operand *t = right;
12968 pic16_emitcode(";remove right +","");
12970 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12972 operand *t = right;
12976 pic16_emitcode(";remove left +","");
12980 big = AOP_SIZE(nextleft);
12981 small = AOP_SIZE(nextright);
12983 switch(nextic->op) {
12986 pic16_emitcode(";optimize a +","");
12987 /* if unsigned or not an integral type */
12988 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12989 pic16_emitcode(";add a bit to something","");
12992 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12994 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12995 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12996 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12998 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13006 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13007 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13008 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13011 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13013 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13014 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13015 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13016 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13017 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13020 pic16_emitcode("rlf","known_zero,w");
13027 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13028 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13029 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13031 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13041 pic16_freeAsmop(right,NULL,ic,TRUE);
13042 pic16_freeAsmop(result,NULL,ic,TRUE);
13043 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13044 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13046 nextic->generated = 1;
13053 /*-----------------------------------------------------------------*/
13054 /* genCast - gen code for casting */
13055 /*-----------------------------------------------------------------*/
13056 static void genCast (iCode *ic)
13058 operand *result = IC_RESULT(ic);
13059 sym_link *ctype = operandType(IC_LEFT(ic));
13060 sym_link *rtype = operandType(IC_RIGHT(ic));
13061 sym_link *restype = operandType(IC_RESULT(ic));
13062 operand *right = IC_RIGHT(ic);
13068 /* if they are equivalent then do nothing */
13069 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13072 pic16_aopOp(result,ic,FALSE);
13073 pic16_aopOp(right,ic,FALSE) ;
13075 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13078 /* if the result is a bit */
13079 if (AOP_TYPE(result) == AOP_CRY) {
13081 /* if the right size is a literal then
13082 * we know what the value is */
13083 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13085 if (AOP_TYPE(right) == AOP_LIT) {
13086 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13087 pic16_popGet(AOP(result),0));
13089 if (((int) operandLitValue(right)))
13090 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13091 AOP(result)->aopu.aop_dir,
13092 AOP(result)->aopu.aop_dir);
13094 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13095 AOP(result)->aopu.aop_dir,
13096 AOP(result)->aopu.aop_dir);
13100 /* the right is also a bit variable */
13101 if (AOP_TYPE(right) == AOP_CRY) {
13103 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13105 pic16_emitcode("clrc","");
13106 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13107 AOP(right)->aopu.aop_dir,
13108 AOP(right)->aopu.aop_dir);
13109 pic16_aopPut(AOP(result),"c",0);
13113 /* we need to or */
13114 if (AOP_TYPE(right) == AOP_REG) {
13115 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13116 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13117 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13119 pic16_toBoolean(right);
13120 pic16_aopPut(AOP(result),"a",0);
13124 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13127 size = AOP_SIZE(result);
13129 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13131 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13132 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13133 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13136 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13141 if(IS_BITFIELD(getSpec(restype))
13142 && IS_BITFIELD(getSpec(rtype))) {
13143 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13146 /* port from pic14 to cope with generic pointers */
13147 if (PIC_IS_TAGGED(restype))
13149 operand *result = IC_RESULT(ic);
13150 //operand *left = IC_LEFT(ic);
13151 operand *right = IC_RIGHT(ic);
13154 /* copy common part */
13155 int max, size = AOP_SIZE(result);
13156 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13157 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13162 pic16_mov2w (AOP(right), size);
13163 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13166 /* upcast into generic pointer type? */
13167 if (IS_GENPTR(restype)
13168 && !PIC_IS_TAGGED(rtype)
13169 && (AOP_SIZE(result) > max))
13171 /* determine appropriate tag for right */
13172 if (PIC_IS_DATA_PTR(rtype))
13173 tag = GPTR_TAG_DATA;
13174 else if (IS_CODEPTR(rtype))
13175 tag = GPTR_TAG_CODE;
13176 else if (PIC_IS_DATA_PTR(ctype)) {
13177 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13178 tag = GPTR_TAG_DATA;
13179 } else if (IS_CODEPTR(ctype)) {
13180 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13181 tag = GPTR_TAG_CODE;
13182 } else if (IS_PTR(rtype)) {
13183 PERFORM_ONCE(weirdcast,
13184 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13186 tag = GPTR_TAG_DATA;
13188 PERFORM_ONCE(weirdcast,
13189 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13191 tag = GPTR_TAG_DATA;
13194 assert (AOP_SIZE(result) == 3);
13195 /* zero-extend address... */
13196 for (size = max; size < AOP_SIZE(result)-1; size++)
13197 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13198 /* ...and add tag */
13199 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13200 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13201 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13202 for (size = max; size < AOP_SIZE(result)-1; size++)
13203 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13204 /* add __code tag */
13205 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13206 } else if (AOP_SIZE(result) > max) {
13207 /* extend non-pointers */
13208 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13209 pic16_addSign(result, max, 0);
13214 /* if they are the same size : or less */
13215 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13217 /* if they are in the same place */
13218 if (pic16_sameRegs(AOP(right),AOP(result)))
13221 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13223 if (IS_PTR_CONST(rtype))
13225 if (IS_CODEPTR(rtype))
13227 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13230 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13232 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13234 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13237 if(AOP_TYPE(right) == AOP_IMMD) {
13238 pCodeOp *pcop0, *pcop1, *pcop2;
13239 symbol *sym = OP_SYMBOL( right );
13241 size = AOP_SIZE(result);
13243 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13245 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13247 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13250 pic16_emitpcode(POC_MOVLW, pcop0);
13251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13252 pic16_emitpcode(POC_MOVLW, pcop1);
13253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13254 pic16_emitpcode(POC_MOVLW, pcop2);
13255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13258 pic16_emitpcode(POC_MOVLW, pcop0);
13259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13260 pic16_emitpcode(POC_MOVLW, pcop1);
13261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13263 pic16_emitpcode(POC_MOVLW, pcop0);
13264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13268 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13269 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13272 if(AOP_SIZE(result) < 2) {
13273 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13275 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13279 /* if they in different places then copy */
13280 size = AOP_SIZE(result);
13283 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13284 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13291 /* if the result is of type pointer */
13292 if (IS_PTR(ctype)) {
13294 sym_link *type = operandType(right);
13295 sym_link *etype = getSpec(type);
13297 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13299 /* pointer to generic pointer */
13300 if (IS_GENPTR(ctype)) {
13304 p_type = DCL_TYPE(type);
13306 /* we have to go by the storage class */
13307 p_type = PTR_TYPE(SPEC_OCLS(etype));
13309 /* if (SPEC_OCLS(etype)->codesp ) */
13310 /* p_type = CPOINTER ; */
13312 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13313 /* p_type = FPOINTER ; */
13315 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13316 /* p_type = PPOINTER; */
13318 /* if (SPEC_OCLS(etype) == idata ) */
13319 /* p_type = IPOINTER ; */
13321 /* p_type = POINTER ; */
13324 /* the first two bytes are known */
13325 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13326 size = GPTRSIZE - 1;
13329 if(offset < AOP_SIZE(right)) {
13330 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13331 pic16_mov2f(AOP(result), AOP(right), offset);
13333 if ((AOP_TYPE(right) == AOP_PCODE) &&
13334 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13335 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13339 pic16_aopPut(AOP(result),
13340 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13345 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13348 /* the last byte depending on type */
13353 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13357 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13361 pic16_emitcode(";BUG!? ","%d",__LINE__);
13366 if (GPTRSIZE > AOP_SIZE(right)) {
13367 // assume __data pointer... THIS MIGHT BE WRONG!
13368 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13370 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13375 /* this should never happen */
13376 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13377 "got unknown pointer type");
13380 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13386 /* just copy the pointers */
13387 size = AOP_SIZE(result);
13390 pic16_aopPut(AOP(result),
13391 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13400 /* so we now know that the size of destination is greater
13401 than the size of the source.
13402 Now, if the next iCode is an operator then we might be
13403 able to optimize the operation without performing a cast.
13405 if(genMixedOperation(ic))
13408 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13410 /* we move to result for the size of source */
13411 size = AOP_SIZE(right);
13416 pic16_mov2f(AOP(result), AOP(right), offset);
13420 /* now depending on the sign of the destination */
13421 size = AOP_SIZE(result) - AOP_SIZE(right);
13422 /* if unsigned or not an integral type */
13423 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13425 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13427 /* we need to extend the sign :( */
13430 /* Save one instruction of casting char to int */
13431 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13432 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13433 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13435 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13438 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13440 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13442 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13445 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13450 pic16_freeAsmop(right,NULL,ic,TRUE);
13451 pic16_freeAsmop(result,NULL,ic,TRUE);
13455 /*-----------------------------------------------------------------*/
13456 /* genDjnz - generate decrement & jump if not zero instrucion */
13457 /*-----------------------------------------------------------------*/
13458 static int genDjnz (iCode *ic, iCode *ifx)
13460 symbol *lbl, *lbl1;
13461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13466 /* if the if condition has a false label
13467 then we cannot save */
13471 /* if the minus is not of the form
13473 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13474 !IS_OP_LITERAL(IC_RIGHT(ic)))
13477 if (operandLitValue(IC_RIGHT(ic)) != 1)
13480 /* if the size of this greater than one then no
13482 if (getSize(operandType(IC_RESULT(ic))) > 1)
13485 /* otherwise we can save BIG */
13486 lbl = newiTempLabel(NULL);
13487 lbl1= newiTempLabel(NULL);
13489 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13491 if (IS_AOP_PREG(IC_RESULT(ic))) {
13492 pic16_emitcode("dec","%s",
13493 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13494 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13495 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13499 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13500 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13502 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13503 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13507 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13508 ifx->generated = 1;
13512 /*-----------------------------------------------------------------*/
13513 /* genReceive - generate code for a receive iCode */
13514 /*-----------------------------------------------------------------*/
13515 static void genReceive (iCode *ic)
13521 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13522 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13524 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13526 if (isOperandInFarSpace(IC_RESULT(ic))
13527 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13528 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13530 int size = getSize(operandType(IC_RESULT(ic)));
13531 int offset = pic16_fReturnSizePic - size;
13535 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13536 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13540 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13542 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13543 size = AOP_SIZE(IC_RESULT(ic));
13546 pic16_emitcode ("pop","acc");
13547 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13550 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13552 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13555 /* set pseudo stack pointer to where it should be - dw*/
13556 GpsuedoStkPtr = ic->parmBytes;
13558 /* setting GpsuedoStkPtr has side effects here: */
13559 /* FIXME: What's the correct size of the return(ed) value?
13560 * For now, assuming '4' as before... */
13561 assignResultValue(IC_RESULT(ic), 4, 0);
13564 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13567 /*-----------------------------------------------------------------*/
13568 /* genDummyRead - generate code for dummy read of volatiles */
13569 /*-----------------------------------------------------------------*/
13571 genDummyRead (iCode * ic)
13577 if (op && IS_SYMOP(op)) {
13578 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13579 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13582 pic16_aopOp (op, ic, FALSE);
13583 for (i=0; i < AOP_SIZE(op); i++) {
13584 // may need to protect this from the peepholer -- this is not nice but works...
13585 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13586 pic16_mov2w (AOP(op),i);
13587 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13589 pic16_freeAsmop (op, NULL, ic, TRUE);
13591 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13595 /*-----------------------------------------------------------------*/
13596 /* genpic16Code - generate code for pic16 based controllers */
13597 /*-----------------------------------------------------------------*/
13599 * At this point, ralloc.c has gone through the iCode and attempted
13600 * to optimize in a way suitable for a PIC. Now we've got to generate
13601 * PIC instructions that correspond to the iCode.
13603 * Once the instructions are generated, we'll pass through both the
13604 * peep hole optimizer and the pCode optimizer.
13605 *-----------------------------------------------------------------*/
13607 void genpic16Code (iCode *lic)
13612 lineHead = lineCurr = NULL;
13614 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13615 pic16_addpBlock(pb);
13618 /* if debug information required */
13619 if (options.debug && currFunc) {
13621 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13626 for (ic = lic ; ic ; ic = ic->next ) {
13628 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13629 if ( cln != ic->lineno ) {
13630 if ( options.debug ) {
13631 debugFile->writeCLine (ic);
13634 if(!options.noCcodeInAsm) {
13635 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13636 printCLine(ic->filename, ic->lineno)));
13642 if(options.iCodeInAsm) {
13645 /* insert here code to print iCode as comment */
13646 iLine = printILine(ic);
13647 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13651 /* if the result is marked as
13652 * spilt and rematerializable or code for
13653 * this has already been generated then
13655 if (resultRemat(ic) || ic->generated )
13658 /* depending on the operation */
13677 /* IPOP happens only when trying to restore a
13678 * spilt live range, if there is an ifx statement
13679 * following this pop then the if statement might
13680 * be using some of the registers being popped which
13681 * would destroy the contents of the register so
13682 * we need to check for this condition and handle it */
13684 && ic->next->op == IFX
13685 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13686 genIfx (ic->next,ic);
13704 genEndFunction (ic);
13720 pic16_genPlus (ic) ;
13724 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13725 pic16_genMinus (ic);
13741 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13745 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13751 /* note these two are xlated by algebraic equivalence
13752 * during parsing SDCC.y */
13753 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13754 "got '>=' or '<=' shouldn't have come here");
13758 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13770 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13774 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13778 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13802 genRightShift (ic);
13805 case GET_VALUE_AT_ADDRESS:
13810 if (POINTER_SET(ic))
13837 addSet(&_G.sendSet,ic);
13840 case DUMMY_READ_VOLATILE:
13850 /* now we are ready to call the
13851 peep hole optimizer */
13852 if (!options.nopeep)
13853 peepHole (&lineHead);
13855 /* now do the actual printing */
13856 printLine (lineHead, codeOutBuf);
13859 DFPRINTF((stderr,"printing pBlock\n\n"));
13860 pic16_printpBlock(stdout,pb);