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))
3602 /*-----------------------------------------------------------------*/
3603 /* inExcludeList - return 1 if the string is in exclude Reg list */
3604 /*-----------------------------------------------------------------*/
3605 static bool inExcludeList(char *s)
3607 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3611 if (options.excludeRegs[i] &&
3612 STRCASECMP(options.excludeRegs[i],"none") == 0)
3615 for ( i = 0 ; options.excludeRegs[i]; i++) {
3616 if (options.excludeRegs[i] &&
3617 STRCASECMP(s,options.excludeRegs[i]) == 0)
3624 /*-----------------------------------------------------------------*/
3625 /* genFunction - generated code for function entry */
3626 /*-----------------------------------------------------------------*/
3627 static void genFunction (iCode *ic)
3633 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3635 pic16_labelOffset += (max_key+4);
3640 ftype = operandType(IC_LEFT(ic));
3641 sym = OP_SYMBOL(IC_LEFT(ic));
3643 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3644 /* create an absolute section at the interrupt vector:
3645 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3650 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3652 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3653 sprintf(asymname, "ivec_%s", sym->name);
3655 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3657 /* when an interrupt is declared as naked, do not emit the special
3658 * wrapper segment at vector address. The user should take care for
3659 * this instead. -- VR */
3661 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3662 asym = newSymbol(asymname, 0);
3663 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3664 pic16_addpBlock( apb );
3666 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3667 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3668 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3669 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3670 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3672 /* mark the end of this tiny function */
3673 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3675 sprintf(asymname, "%s", sym->rname);
3681 abSym = Safe_calloc(1, sizeof(absSym));
3682 strcpy(abSym->name, asymname);
3684 switch( FUNC_INTNO(sym->type) ) {
3685 case 0: abSym->address = 0x000000; break;
3686 case 1: abSym->address = 0x000008; break;
3687 case 2: abSym->address = 0x000018; break;
3690 // fprintf(stderr, "no interrupt number is given\n");
3691 abSym->address = -1; break;
3694 /* relocate interrupt vectors if needed */
3695 if(abSym->address != -1)
3696 abSym->address += pic16_options.ivt_loc;
3698 addSet(&absSymSet, abSym);
3702 /* create the function header */
3703 pic16_emitcode(";","-----------------------------------------");
3704 pic16_emitcode(";"," function %s",sym->name);
3705 pic16_emitcode(";","-----------------------------------------");
3707 /* prevent this symbol from being emitted as 'extern' */
3708 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3710 pic16_emitcode("","%s:",sym->rname);
3711 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3716 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3717 if(!strcmp(ab->name, sym->rname)) {
3718 pic16_pBlockConvert2Absolute(pb);
3724 if(IFFUNC_ISNAKED(ftype)) {
3725 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3729 /* if critical function then turn interrupts off */
3730 if (IFFUNC_ISCRITICAL(ftype)) {
3731 //pic16_emitcode("clr","ea");
3734 currFunc = sym; /* update the currFunc symbol */
3735 _G.fregsUsed = sym->regsUsed;
3736 _G.sregsAlloc = newBitVect(128);
3739 /* if this is an interrupt service routine then
3740 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3741 if (IFFUNC_ISISR(sym->type)) {
3742 _G.usefastretfie = 1; /* use shadow registers by default */
3744 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3745 if(!FUNC_ISSHADOWREGS(sym->type)) {
3746 /* do not save WREG,STATUS,BSR for high priority interrupts
3747 * because they are stored in the hardware shadow registers already */
3748 _G.usefastretfie = 0;
3749 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3750 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3751 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3754 /* these should really be optimized somehow, because not all
3755 * interrupt handlers modify them */
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3758 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3759 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3763 // pic16_pBlockConvert2ISR(pb);
3766 /* emit code to setup stack frame if user enabled,
3767 * and function is not main() */
3769 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3770 if(strcmp(sym->name, "main")) {
3772 || !options.ommitFramePtr
3774 || IFFUNC_ARGS(sym->type)
3775 || FUNC_HASSTACKPARM(sym->etype)
3777 /* setup the stack frame */
3778 if(STACK_MODEL_LARGE)
3779 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3780 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3782 if(STACK_MODEL_LARGE)
3783 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3784 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3788 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3791 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3793 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3794 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3796 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3799 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3800 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3807 /* if callee-save to be used for this function
3808 * then save the registers being used in this function */
3809 // if (IFFUNC_CALLEESAVES(sym->type))
3810 if(strcmp(sym->name, "main")) {
3813 /* if any registers used */
3814 if (sym->regsUsed) {
3815 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3818 /* save the registers used */
3819 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3820 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3821 if (bitVectBitValue(sym->regsUsed,i)) {
3823 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3825 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3828 if(!pic16_regWithIdx(i)->wasUsed) {
3829 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3830 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831 pic16_regWithIdx(i)->wasUsed = 1;
3838 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3839 for(i=0;i<sym->regsUsed->size;i++) {
3840 if(bitVectBitValue(sym->regsUsed, i)) {
3845 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3848 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3853 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3854 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3857 /*-----------------------------------------------------------------*/
3858 /* genEndFunction - generates epilogue for functions */
3859 /*-----------------------------------------------------------------*/
3860 static void genEndFunction (iCode *ic)
3862 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3866 if(IFFUNC_ISNAKED(sym->type)) {
3867 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3873 /* add code for ISCRITICAL */
3874 if(IFFUNC_ISCRITICAL(sym->type)) {
3875 /* if critical function, turn on interrupts */
3877 /* TODO: add code here -- VR */
3880 // sym->regsUsed = _G.fregsUsed;
3882 /* now we need to restore the registers */
3883 /* if any registers used */
3885 /* first restore registers that might be used for stack access */
3886 if(_G.sregsAllocSet) {
3889 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3890 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3891 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3895 if (strcmp(sym->name, "main") && sym->regsUsed) {
3898 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3899 /* restore registers used */
3900 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3901 for ( i = sym->regsUsed->size; i >= 0; i--) {
3902 if (bitVectBitValue(sym->regsUsed,i)) {
3903 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3907 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3912 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3914 if (sym->stack == 1) {
3915 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3916 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3918 // we have to add more than one...
3919 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3920 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3921 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3923 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3924 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3925 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3929 if(strcmp(sym->name, "main")) {
3931 || !options.ommitFramePtr
3933 || IFFUNC_ARGS(sym->type)
3934 || FUNC_HASSTACKPARM(sym->etype)
3936 /* restore stack frame */
3937 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3938 if(STACK_MODEL_LARGE)
3939 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3945 if (IFFUNC_ISISR(sym->type)) {
3946 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3947 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3948 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3949 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3950 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3951 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3953 if(!FUNC_ISSHADOWREGS(sym->type)) {
3954 /* do not restore interrupt vector for WREG,STATUS,BSR
3955 * for high priority interrupt, see genFunction */
3956 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3957 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3958 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3960 // _G.interruptvector = 0; /* sanity check */
3963 /* if debug then send end of function */
3964 /* if (options.debug && currFunc) */
3966 debugFile->writeEndFunction (currFunc, ic, 1);
3969 if(_G.usefastretfie)
3970 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3972 pic16_emitpcodeNULLop(POC_RETFIE);
3974 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3976 _G.usefastretfie = 0;
3980 if (IFFUNC_ISCRITICAL(sym->type)) {
3981 pic16_emitcode("setb","ea");
3984 /* if debug then send end of function */
3986 debugFile->writeEndFunction (currFunc, ic, 1);
3989 /* insert code to restore stack frame, if user enabled it
3990 * and function is not main() */
3993 pic16_emitpcodeNULLop(POC_RETURN);
3995 /* Mark the end of a function */
3996 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4000 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4002 unsigned long lit=1;
4007 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4008 if(AOP_TYPE(op) == AOP_LIT) {
4009 if(!IS_FLOAT(operandType( op ))) {
4010 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4013 unsigned long lit_int;
4017 /* take care if literal is a float */
4018 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4023 if (AOP_TYPE(op) == AOP_LIT) {
4024 /* FIXME: broken for
4025 * char __at(0x456) foo;
4027 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4028 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4029 } else if (AOP_TYPE(op) == AOP_PCODE
4030 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4031 /* char *s= "aaa"; return s; */
4032 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4033 * that the generic pointer is interpreted correctly
4034 * as referring to __code space, but this is fragile! */
4035 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4036 /* XXX: should check that dest != WREG */
4037 pic16_emitpcode(POC_MOVWF, dest);
4039 if(dest->type == PO_WREG && (offset == 0)) {
4040 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4043 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4047 /*-----------------------------------------------------------------*/
4048 /* genRet - generate code for return statement */
4049 /*-----------------------------------------------------------------*/
4050 static void genRet (iCode *ic)
4056 /* if we have no return value then
4057 * just generate the "ret" */
4062 /* we have something to return then
4063 * move the return value into place */
4064 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4065 size = AOP_SIZE(IC_LEFT(ic));
4069 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4072 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4075 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4077 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4080 /* >32-bits, setup stack and FSR0 */
4082 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4083 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4085 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4087 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4092 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4093 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4095 if(STACK_MODEL_LARGE) {
4096 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4097 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4099 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4104 /* old code, left here for reference -- VR */
4108 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4110 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4111 pic16_emitpcomment("push %s",l);
4114 DEBUGpic16_emitcode(";", "%d", __LINE__);
4115 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4116 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4118 if (strcmp(fReturn[offset],l)) {
4119 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4120 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4121 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4123 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4127 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4137 if (strcmp(fReturn[pushed],"a"))
4138 pic16_emitcode("pop",fReturn[pushed]);
4140 pic16_emitcode("pop","acc");
4146 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4149 /* generate a jump to the return label
4150 * if the next is not the return statement */
4151 if (!(ic->next && ic->next->op == LABEL
4152 && IC_LABEL(ic->next) == returnLabel)) {
4154 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4155 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4159 /*-----------------------------------------------------------------*/
4160 /* genLabel - generates a label */
4161 /*-----------------------------------------------------------------*/
4162 static void genLabel (iCode *ic)
4166 /* special case never generate */
4167 if (IC_LABEL(ic) == entryLabel)
4170 pic16_emitpLabel(IC_LABEL(ic)->key);
4171 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4174 /*-----------------------------------------------------------------*/
4175 /* genGoto - generates a goto */
4176 /*-----------------------------------------------------------------*/
4178 static void genGoto (iCode *ic)
4181 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4182 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4186 /*-----------------------------------------------------------------*/
4187 /* genMultbits :- multiplication of bits */
4188 /*-----------------------------------------------------------------*/
4189 static void genMultbits (operand *left,
4195 if(!pic16_sameRegs(AOP(result),AOP(right)))
4196 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4198 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4199 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4200 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4205 /*-----------------------------------------------------------------*/
4206 /* genMultOneByte : 8 bit multiplication & division */
4207 /*-----------------------------------------------------------------*/
4208 static void genMultOneByte (operand *left,
4214 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4217 /* (if two literals, the value is computed before) */
4218 /* if one literal, literal on the right */
4219 if (AOP_TYPE(left) == AOP_LIT){
4225 /* size is already checked in genMult == 1 */
4226 // size = AOP_SIZE(result);
4228 if (AOP_TYPE(right) == AOP_LIT){
4229 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4230 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4231 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4232 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4234 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4235 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4236 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4237 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4240 pic16_genMult8X8_n (left, right,result);
4244 /*-----------------------------------------------------------------*/
4245 /* genMultOneWord : 16 bit multiplication */
4246 /*-----------------------------------------------------------------*/
4247 static void genMultOneWord (operand *left,
4252 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4253 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4255 /* (if two literals, the value is computed before)
4256 * if one literal, literal on the right */
4257 if (AOP_TYPE(left) == AOP_LIT){
4263 /* size is checked already == 2 */
4264 // size = AOP_SIZE(result);
4266 if (AOP_TYPE(right) == AOP_LIT) {
4267 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4268 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4269 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4270 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4272 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4273 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4274 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4275 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4278 pic16_genMult16X16_16(left, right,result);
4283 /*-----------------------------------------------------------------*/
4284 /* genMultOneLong : 32 bit multiplication */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultOneLong (operand *left,
4291 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4292 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4294 /* (if two literals, the value is computed before)
4295 * if one literal, literal on the right */
4296 if (AOP_TYPE(left) == AOP_LIT){
4302 /* size is checked already == 4 */
4303 // size = AOP_SIZE(result);
4305 if (AOP_TYPE(right) == AOP_LIT) {
4306 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4307 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4308 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4309 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4311 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4312 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4313 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4314 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4317 pic16_genMult32X32_32(left, right,result);
4323 /*-----------------------------------------------------------------*/
4324 /* genMult - generates code for multiplication */
4325 /*-----------------------------------------------------------------*/
4326 static void genMult (iCode *ic)
4328 operand *left = IC_LEFT(ic);
4329 operand *right = IC_RIGHT(ic);
4330 operand *result= IC_RESULT(ic);
4333 /* assign the amsops */
4334 pic16_aopOp (left,ic,FALSE);
4335 pic16_aopOp (right,ic,FALSE);
4336 pic16_aopOp (result,ic,TRUE);
4338 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4340 /* special cases first *
4342 if (AOP_TYPE(left) == AOP_CRY
4343 && AOP_TYPE(right)== AOP_CRY) {
4344 genMultbits(left,right,result);
4348 /* if both are of size == 1 */
4349 if(AOP_SIZE(left) == 1
4350 && AOP_SIZE(right) == 1) {
4351 genMultOneByte(left,right,result);
4356 /* if both are of size == 2 */
4357 if(AOP_SIZE(left) == 2
4358 && AOP_SIZE(right) == 2) {
4359 genMultOneWord(left, right, result);
4363 /* if both are of size == 4 */
4364 if(AOP_SIZE(left) == 4
4365 && AOP_SIZE(right) == 4) {
4366 genMultOneLong(left, right, result);
4371 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4372 assert( !"Multiplication should have been transformed into function call!" );
4374 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4377 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4378 /* should have been converted to function call */
4382 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4383 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384 pic16_freeAsmop(result,NULL,ic,TRUE);
4388 /*-----------------------------------------------------------------*/
4389 /* genDivbits :- division of bits */
4390 /*-----------------------------------------------------------------*/
4391 static void genDivbits (operand *left,
4398 /* the result must be bit */
4399 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4400 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4404 pic16_emitcode("div","ab");
4405 pic16_emitcode("rrc","a");
4406 pic16_aopPut(AOP(result),"c",0);
4409 /*-----------------------------------------------------------------*/
4410 /* genDivOneByte : 8 bit division */
4411 /*-----------------------------------------------------------------*/
4412 static void genDivOneByte (operand *left,
4416 sym_link *opetype = operandType(result);
4421 /* result = divident / divisor
4422 * - divident may be a register or a literal,
4423 * - divisor may be a register or a literal,
4424 * so there are 3 cases (literal / literal is optimized
4425 * by the front-end) to handle.
4426 * In addition we must handle signed and unsigned, which
4427 * result in 6 final different cases -- VR */
4431 size = AOP_SIZE(result) - 1;
4433 /* signed or unsigned */
4434 if (SPEC_USIGN(opetype)) {
4435 pCodeOp *pct1, /* count */
4438 symbol *label1, *label2, *label3;;
4441 /* unsigned is easy */
4443 pct1 = pic16_popGetTempReg(1);
4444 pct2 = pic16_popGetTempReg(1);
4445 pct3 = pic16_popGetTempReg(1);
4447 label1 = newiTempLabel(NULL);
4448 label2 = newiTempLabel(NULL);
4449 label3 = newiTempLabel(NULL);
4451 /* the following algorithm is extracted from divuint.c */
4453 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4454 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4456 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4458 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4460 pic16_emitpLabel(label1->key);
4463 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4467 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4471 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4473 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4474 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4476 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4477 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4478 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4480 pic16_emitpLabel( label3->key );
4481 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4482 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4486 pic16_emitpLabel(label2->key);
4487 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4488 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4489 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4491 /* result is in wreg */
4492 if(AOP_TYPE(result) != AOP_ACC)
4493 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4495 pic16_popReleaseTempReg( pct3, 1);
4496 pic16_popReleaseTempReg( pct2, 1);
4497 pic16_popReleaseTempReg( pct1, 1);
4502 /* signed is a little bit more difficult */
4504 /* save the signs of the operands */
4505 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4507 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4508 pic16_emitcode("push","acc"); /* save it on the stack */
4510 /* now sign adjust for both left & right */
4511 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4513 lbl = newiTempLabel(NULL);
4514 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4515 pic16_emitcode("cpl","a");
4516 pic16_emitcode("inc","a");
4517 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4518 pic16_emitcode("mov","b,a");
4520 /* sign adjust left side */
4521 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4524 lbl = newiTempLabel(NULL);
4525 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4526 pic16_emitcode("cpl","a");
4527 pic16_emitcode("inc","a");
4528 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4530 /* now the division */
4531 pic16_emitcode("div","ab");
4532 /* we are interested in the lower order
4534 pic16_emitcode("mov","b,a");
4535 lbl = newiTempLabel(NULL);
4536 pic16_emitcode("pop","acc");
4537 /* if there was an over flow we don't
4538 adjust the sign of the result */
4539 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4540 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4542 pic16_emitcode("clr","a");
4543 pic16_emitcode("subb","a,b");
4544 pic16_emitcode("mov","b,a");
4545 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4547 /* now we are done */
4548 pic16_aopPut(AOP(result),"b",0);
4550 pic16_emitcode("mov","c,b.7");
4551 pic16_emitcode("subb","a,acc");
4554 pic16_aopPut(AOP(result),"a",offset++);
4559 /*-----------------------------------------------------------------*/
4560 /* genDiv - generates code for division */
4561 /*-----------------------------------------------------------------*/
4562 static void genDiv (iCode *ic)
4564 operand *left = IC_LEFT(ic);
4565 operand *right = IC_RIGHT(ic);
4566 operand *result= IC_RESULT(ic);
4568 int leftVal = 0, rightVal = 0;
4570 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4573 /* Division is a very lengthy algorithm, so it is better
4574 * to call support routines than inlining algorithm.
4575 * Division functions written here just in case someone
4576 * wants to inline and not use the support libraries -- VR */
4580 /* assign the amsops */
4581 pic16_aopOp (left,ic,FALSE);
4582 pic16_aopOp (right,ic,FALSE);
4583 pic16_aopOp (result,ic,TRUE);
4587 else if (ic->op == '%')
4590 assert( !"invalid operation requested in genDivMod" );
4592 /* get literal values */
4593 if (IS_VALOP(left)) {
4594 leftVal = (int)floatFromVal( OP_VALUE(left) );
4595 assert( leftVal >= -128 && leftVal < 256 );
4596 if (leftVal < 0) { signedLits++; }
4598 if (IS_VALOP(right)) {
4599 rightVal = (int)floatFromVal( OP_VALUE(right) );
4600 assert( rightVal >= -128 && rightVal < 256 );
4601 if (rightVal < 0) { signedLits++; }
4604 /* We should only come here to convert all
4605 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4606 * with exactly one operand being s8_t into
4607 * u8_t x u8_t -> u8_t. All other cases should have been
4608 * turned into calls to support routines beforehand... */
4609 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4610 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4612 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4613 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4615 /* Both operands are signed or negative, use _divschar
4616 * instead of _divuchar */
4617 pushaop(AOP(right), 0);
4618 pushaop(AOP(left), 0);
4620 /* call _divschar */
4621 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4625 sym = newSymbol( functions[op][0], 0 );
4627 strcpy(sym->rname, functions[op][0]);
4628 checkAddSym(&externs, sym);
4632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4633 if (AOP_SIZE(result) > 1)
4635 pic16_emitpcode(POC_MOVFF,
4636 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4637 pic16_popGet(AOP(result), 1)));
4639 pic16_addSign(result, 2, 1);
4642 /* clean up stack */
4643 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4644 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4649 /* push right operand */
4650 if (IS_VALOP(right)) {
4652 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4655 pushaop(AOP(right), 0);
4657 } else if (!IS_UNSIGNED(operandType(right))) {
4658 pic16_mov2w(AOP(right), 0);
4659 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4660 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4661 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4664 pushaop(AOP(right), 0);
4667 /* push left operand */
4668 if (IS_VALOP(left)) {
4670 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4673 pushaop(AOP(left), 0);
4675 } else if (!IS_UNSIGNED(operandType(left))) {
4676 pic16_mov2w(AOP(left),0);
4677 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4678 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4679 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4682 pushaop(AOP(left), 0);
4685 /* call _divuchar */
4686 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4690 sym = newSymbol( functions[op][1], 0 );
4692 strcpy(sym->rname, functions[op][1]);
4693 checkAddSym(&externs, sym);
4696 /* Revert negation(s) from above.
4697 * This is inefficient: if both operands are negative, this
4698 * should not touch WREG. However, determining that exactly
4699 * one operand was negated costs at least 3 instructions,
4700 * so there is nothing to be gained here, is there?
4702 * I negate WREG because either operand might share registers with
4703 * result, so assigning first might destroy an operand. */
4705 /* For the modulus operator, (a/b)*b == a shall hold.
4706 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4707 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4708 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4709 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4710 * Only invert the result if the left operand is negative (sigh).
4712 if (AOP_SIZE(result) <= 1 || !negated)
4716 if (IS_VALOP(right)) {
4718 /* we negated this operand above */
4719 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4721 } else if (!IS_UNSIGNED(operandType(right))) {
4722 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4723 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4727 if (IS_VALOP(left)) {
4729 /* we negated this operand above */
4730 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4732 } else if (!IS_UNSIGNED(operandType(left))) {
4733 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4734 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4737 /* Move result to destination. */
4738 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4740 /* Zero-extend: no operand was signed (or result is just a byte). */
4741 pic16_addSign(result, 1, 0);
4743 assert( AOP_SIZE(result) > 1 );
4744 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4747 if (IS_VALOP(right)) {
4749 /* we negated this operand above */
4750 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4752 } else if (!IS_UNSIGNED(operandType(right))) {
4753 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4754 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4758 if (IS_VALOP(left)) {
4760 /* we negated this operand above */
4761 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4763 } else if (!IS_UNSIGNED(operandType(left))) {
4764 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4765 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4768 /* Move result to destination. */
4769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4771 /* Negate result if required. */
4772 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4773 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4776 pic16_addSign(result, 2, 1);
4779 /* clean up stack */
4780 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4781 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4786 /* special cases first */
4788 if (AOP_TYPE(left) == AOP_CRY &&
4789 AOP_TYPE(right)== AOP_CRY) {
4790 genDivbits(left,right,result);
4794 /* if both are of size == 1 */
4795 if (AOP_SIZE(left) == 1 &&
4796 AOP_SIZE(right) == 1 ) {
4797 genDivOneByte(left,right,result);
4802 /* should have been converted to function call */
4805 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4806 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807 pic16_freeAsmop(result,NULL,ic,TRUE);
4811 /*-----------------------------------------------------------------*/
4812 /* genModbits :- modulus of bits */
4813 /*-----------------------------------------------------------------*/
4814 static void genModbits (operand *left,
4822 werror(W_POSSBUG2, __FILE__, __LINE__);
4823 /* the result must be bit */
4824 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4825 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4829 pic16_emitcode("div","ab");
4830 pic16_emitcode("mov","a,b");
4831 pic16_emitcode("rrc","a");
4832 pic16_aopPut(AOP(result),"c",0);
4835 /*-----------------------------------------------------------------*/
4836 /* genModOneByte : 8 bit modulus */
4837 /*-----------------------------------------------------------------*/
4838 static void genModOneByte (operand *left,
4842 sym_link *opetype = operandType(result);
4847 werror(W_POSSBUG2, __FILE__, __LINE__);
4849 /* signed or unsigned */
4850 if (SPEC_USIGN(opetype)) {
4851 /* unsigned is easy */
4852 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4853 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4855 pic16_emitcode("div","ab");
4856 pic16_aopPut(AOP(result),"b",0);
4860 /* signed is a little bit more difficult */
4862 /* save the signs of the operands */
4863 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4866 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4867 pic16_emitcode("push","acc"); /* save it on the stack */
4869 /* now sign adjust for both left & right */
4870 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4873 lbl = newiTempLabel(NULL);
4874 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4875 pic16_emitcode("cpl","a");
4876 pic16_emitcode("inc","a");
4877 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4878 pic16_emitcode("mov","b,a");
4880 /* sign adjust left side */
4881 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4884 lbl = newiTempLabel(NULL);
4885 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4886 pic16_emitcode("cpl","a");
4887 pic16_emitcode("inc","a");
4888 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4890 /* now the multiplication */
4891 pic16_emitcode("div","ab");
4892 /* we are interested in the lower order
4894 lbl = newiTempLabel(NULL);
4895 pic16_emitcode("pop","acc");
4896 /* if there was an over flow we don't
4897 adjust the sign of the result */
4898 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4899 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4901 pic16_emitcode("clr","a");
4902 pic16_emitcode("subb","a,b");
4903 pic16_emitcode("mov","b,a");
4904 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4906 /* now we are done */
4907 pic16_aopPut(AOP(result),"b",0);
4912 /*-----------------------------------------------------------------*/
4913 /* genMod - generates code for division */
4914 /*-----------------------------------------------------------------*/
4915 static void genMod (iCode *ic)
4917 /* Task deferred to genDiv */
4920 operand *left = IC_LEFT(ic);
4921 operand *right = IC_RIGHT(ic);
4922 operand *result= IC_RESULT(ic);
4926 /* assign the amsops */
4927 pic16_aopOp (left,ic,FALSE);
4928 pic16_aopOp (right,ic,FALSE);
4929 pic16_aopOp (result,ic,TRUE);
4931 /* special cases first */
4933 if (AOP_TYPE(left) == AOP_CRY &&
4934 AOP_TYPE(right)== AOP_CRY) {
4935 genModbits(left,right,result);
4939 /* if both are of size == 1 */
4940 if (AOP_SIZE(left) == 1 &&
4941 AOP_SIZE(right) == 1 ) {
4942 genModOneByte(left,right,result);
4946 /* should have been converted to function call */
4950 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4951 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952 pic16_freeAsmop(result,NULL,ic,TRUE);
4956 /*-----------------------------------------------------------------*/
4957 /* genIfxJump :- will create a jump depending on the ifx */
4958 /*-----------------------------------------------------------------*/
4960 note: May need to add parameter to indicate when a variable is in bit space.
4962 static void genIfxJump (iCode *ic, char *jval)
4966 /* if true label then we jump if condition
4968 if ( IC_TRUE(ic) ) {
4970 if(strcmp(jval,"a") == 0)
4972 else if (strcmp(jval,"c") == 0)
4975 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4976 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4979 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4980 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4984 /* false label is present */
4985 if(strcmp(jval,"a") == 0)
4987 else if (strcmp(jval,"c") == 0)
4990 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4991 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4994 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4995 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5000 /* mark the icode as generated */
5004 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5008 /* if true label then we jump if condition
5010 if ( IC_TRUE(ic) ) {
5011 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5012 pic16_emitpcode(POC_BTFSC, jop);
5014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5015 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5018 /* false label is present */
5019 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5020 pic16_emitpcode(POC_BTFSS, jop);
5022 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5023 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5027 /* mark the icode as generated */
5034 /*-----------------------------------------------------------------*/
5036 /*-----------------------------------------------------------------*/
5037 static void genSkip(iCode *ifx,int status_bit)
5039 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5043 if ( IC_TRUE(ifx) ) {
5044 switch(status_bit) {
5059 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5060 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5064 switch(status_bit) {
5078 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5079 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5086 /*-----------------------------------------------------------------*/
5088 /*-----------------------------------------------------------------*/
5089 static void genSkipc(resolvedIfx *rifx)
5091 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5101 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5102 rifx->generated = 1;
5105 #if !(USE_SIMPLE_GENCMP)
5106 /*-----------------------------------------------------------------*/
5108 /*-----------------------------------------------------------------*/
5109 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5111 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5116 if( (rifx->condition ^ invert_condition) & 1)
5121 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5122 rifx->generated = 1;
5127 /*-----------------------------------------------------------------*/
5129 /*-----------------------------------------------------------------*/
5130 static void genSkipz(iCode *ifx, int condition)
5141 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5143 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5146 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5148 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5153 #if !(USE_SIMPLE_GENCMP)
5154 /*-----------------------------------------------------------------*/
5156 /*-----------------------------------------------------------------*/
5157 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5163 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5165 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5168 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5169 rifx->generated = 1;
5174 /*-----------------------------------------------------------------*/
5175 /* genChkZeroes :- greater or less than comparison */
5176 /* For each byte in a literal that is zero, inclusive or the */
5177 /* the corresponding byte in the operand with W */
5178 /* returns true if any of the bytes are zero */
5179 /*-----------------------------------------------------------------*/
5180 static int genChkZeroes(operand *op, int lit, int size)
5187 i = (lit >> (size*8)) & 0xff;
5191 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5193 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5203 /*-----------------------------------------------------------------*/
5204 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5205 /* aop (if it's NOT a literal) or from lit (if */
5206 /* aop is a literal) */
5207 /*-----------------------------------------------------------------*/
5208 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5209 if (aop->type == AOP_LIT) {
5210 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5212 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5216 /*-----------------------------------------------------------------*/
5217 /* genCmp :- greater or less than comparison */
5218 /*-----------------------------------------------------------------*/
5220 #if USE_SIMPLE_GENCMP /* { */
5222 /* genCmp performs a left < right comparison, stores
5223 * the outcome in result (if != NULL) and generates
5224 * control flow code for the ifx (if != NULL).
5226 * This version leaves in sequences like
5227 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5228 * which should be optmized by the peephole
5229 * optimizer - RN 2005-01-01 */
5230 static void genCmp (operand *left,operand *right,
5231 operand *result, iCode *ifx, int sign)
5244 assert (left && right);
5245 assert (AOP_SIZE(left) == AOP_SIZE(right));
5247 size = AOP_SIZE(right) - 1;
5248 mask = (0x100UL << (size*8)) - 1;
5249 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5254 resolveIfx (&rIfx, ifx);
5256 /* handle for special cases */
5257 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5260 /**********************************************************************
5261 * handle bits - bit compares are promoted to int compares seemingly! *
5262 **********************************************************************/
5264 // THIS IS COMPLETELY UNTESTED!
5265 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5266 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5267 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5268 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5271 // 1 < {0,1} is false --> clear C by skipping the next instruction
5272 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5273 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5274 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5275 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5276 emitCLRC; // only skipped for left=0 && right=1
5278 goto correct_result_in_carry;
5282 /*************************************************
5283 * make sure that left is register (or the like) *
5284 *************************************************/
5285 if (!isAOP_REGlike(left)) {
5286 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5287 assert (isAOP_LIT(left));
5288 assert (isAOP_REGlike(right));
5289 // swap left and right
5290 // left < right <==> right > left <==> (right >= left + 1)
5291 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5293 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5294 // MAXVALUE < right? always false
5295 if (performedLt) emitCLRC; else emitSETC;
5296 goto correct_result_in_carry;
5299 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5300 // that's why we handled it above.
5307 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5308 } else if (isAOP_LIT(right)) {
5309 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5312 assert (isAOP_REGlike(left)); // left must be register or the like
5313 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5315 /*************************************************
5316 * special cases go here *
5317 *************************************************/
5319 if (isAOP_LIT(right)) {
5321 // unsigned comparison to a literal
5322 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5324 // unsigned left < 0? always false
5325 if (performedLt) emitCLRC; else emitSETC;
5326 goto correct_result_in_carry;
5329 // signed comparison to a literal
5330 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5331 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5332 // signed left < 0x80000000? always false
5333 if (performedLt) emitCLRC; else emitSETC;
5334 goto correct_result_in_carry;
5335 } else if (lit == 0) {
5336 // compare left < 0; set CARRY if SIGNBIT(left) is set
5337 if (performedLt) emitSETC; else emitCLRC;
5338 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5339 if (performedLt) emitCLRC; else emitSETC;
5340 goto correct_result_in_carry;
5343 } // right is literal
5345 /*************************************************
5346 * perform a general case comparison *
5347 * make sure we get CARRY==1 <==> left >= right *
5348 *************************************************/
5349 // compare most significant bytes
5350 //DEBUGpc ("comparing bytes at offset %d", size);
5352 // unsigned comparison
5353 mov2w_regOrLit (AOP(right), lit, size);
5354 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5356 // signed comparison
5357 // (add 2^n to both operands then perform an unsigned comparison)
5358 if (isAOP_LIT(right)) {
5359 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5360 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5362 if (litbyte == 0x80) {
5363 // left >= 0x80 -- always true, but more bytes to come
5364 pic16_mov2w (AOP(left), size);
5365 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5368 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5369 pic16_mov2w (AOP(left), size);
5370 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5371 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5374 /* using PRODL as a temporary register here */
5375 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5376 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5377 pic16_mov2w (AOP(left), size);
5378 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5379 pic16_emitpcode (POC_MOVWF, pctemp);
5380 pic16_mov2w (AOP(right), size);
5381 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5382 pic16_emitpcode (POC_SUBFW, pctemp);
5383 //pic16_popReleaseTempReg(pctemp, 1);
5387 // compare remaining bytes (treat as unsigned case from above)
5388 templbl = newiTempLabel ( NULL );
5391 //DEBUGpc ("comparing bytes at offset %d", offs);
5392 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5393 mov2w_regOrLit (AOP(right), lit, offs);
5394 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5396 pic16_emitpLabel (templbl->key);
5397 goto result_in_carry;
5401 /****************************************************
5402 * now CARRY contains the result of the comparison: *
5403 * SUBWF sets CARRY iff *
5404 * F-W >= 0 <==> F >= W <==> !(F < W) *
5405 * (F=left, W=right) *
5406 ****************************************************/
5409 if (result && AOP_TYPE(result) != AOP_CRY) {
5410 // value will be stored
5413 // value wil only be used in the following genSkipc()
5414 rIfx.condition ^= 1;
5418 correct_result_in_carry:
5420 // assign result to variable (if neccessary)
5421 if (result && AOP_TYPE(result) != AOP_CRY) {
5422 //DEBUGpc ("assign result");
5423 size = AOP_SIZE(result);
5425 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5427 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5430 // perform conditional jump
5432 //DEBUGpc ("generate control flow");
5441 static void genCmp (operand *left,operand *right,
5442 operand *result, iCode *ifx, int sign)
5444 int size; //, offset = 0 ;
5445 unsigned long lit = 0L,i = 0;
5446 resolvedIfx rFalseIfx;
5447 // resolvedIfx rTrueIfx;
5449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5452 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5453 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5459 resolveIfx(&rFalseIfx,ifx);
5460 truelbl = newiTempLabel(NULL);
5461 size = max(AOP_SIZE(left),AOP_SIZE(right));
5463 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5467 /* if literal is on the right then swap with left */
5468 if ((AOP_TYPE(right) == AOP_LIT)) {
5469 operand *tmp = right ;
5470 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5471 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5474 lit = (lit - 1) & mask;
5477 rFalseIfx.condition ^= 1;
5480 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5481 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5485 //if(IC_TRUE(ifx) == NULL)
5486 /* if left & right are bit variables */
5487 if (AOP_TYPE(left) == AOP_CRY &&
5488 AOP_TYPE(right) == AOP_CRY ) {
5489 assert (0 && "bit variables used in genCmp");
5490 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5491 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5493 /* subtract right from left if at the
5494 end the carry flag is set then we know that
5495 left is greater than right */
5497 symbol *lbl = newiTempLabel(NULL);
5500 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5501 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5505 if(AOP_TYPE(right) == AOP_LIT) {
5507 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5509 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5516 genSkipCond(&rFalseIfx,left,size-1,7);
5518 /* no need to compare to 0...*/
5519 /* NOTE: this is a de-generate compare that most certainly
5520 * creates some dead code. */
5521 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5523 if(ifx) ifx->generated = 1;
5530 //i = (lit >> (size*8)) & 0xff;
5531 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5535 i = ((0-lit) & 0xff);
5538 /* lit is 0x7f, all signed chars are less than
5539 * this except for 0x7f itself */
5540 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5541 genSkipz2(&rFalseIfx,0);
5543 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5544 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5545 genSkipc(&rFalseIfx);
5550 genSkipz2(&rFalseIfx,1);
5552 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5553 genSkipc(&rFalseIfx);
5557 if(ifx) ifx->generated = 1;
5561 /* chars are out of the way. now do ints and longs */
5564 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5571 genSkipCond(&rFalseIfx,left,size,7);
5572 if(ifx) ifx->generated = 1;
5577 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5579 //rFalseIfx.condition ^= 1;
5580 //genSkipCond(&rFalseIfx,left,size,7);
5581 //rFalseIfx.condition ^= 1;
5583 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5584 if(rFalseIfx.condition)
5585 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5587 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5589 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5590 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5591 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5594 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5596 if(rFalseIfx.condition) {
5598 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5604 genSkipc(&rFalseIfx);
5605 pic16_emitpLabel(truelbl->key);
5606 if(ifx) ifx->generated = 1;
5613 if( (lit & 0xff) == 0) {
5614 /* lower byte is zero */
5615 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5616 i = ((lit >> 8) & 0xff) ^0x80;
5617 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5618 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5619 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5620 genSkipc(&rFalseIfx);
5623 if(ifx) ifx->generated = 1;
5628 /* Special cases for signed longs */
5629 if( (lit & 0xffffff) == 0) {
5630 /* lower byte is zero */
5631 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5632 i = ((lit >> 8*3) & 0xff) ^0x80;
5633 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5634 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5635 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5636 genSkipc(&rFalseIfx);
5639 if(ifx) ifx->generated = 1;
5647 if(lit & (0x80 << (size*8))) {
5648 /* lit is negative */
5649 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5651 //genSkipCond(&rFalseIfx,left,size,7);
5653 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5655 if(rFalseIfx.condition)
5656 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5658 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5662 /* lit is positive */
5663 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5664 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5665 if(rFalseIfx.condition)
5666 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5668 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5673 This works, but is only good for ints.
5674 It also requires a "known zero" register.
5675 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5676 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5677 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5678 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5679 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5680 genSkipc(&rFalseIfx);
5682 pic16_emitpLabel(truelbl->key);
5683 if(ifx) ifx->generated = 1;
5687 /* There are no more special cases, so perform a general compare */
5689 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5690 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5694 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5696 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5698 //rFalseIfx.condition ^= 1;
5699 genSkipc(&rFalseIfx);
5701 pic16_emitpLabel(truelbl->key);
5703 if(ifx) ifx->generated = 1;
5710 /* sign is out of the way. So now do an unsigned compare */
5711 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5714 /* General case - compare to an unsigned literal on the right.*/
5716 i = (lit >> (size*8)) & 0xff;
5717 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5718 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5720 i = (lit >> (size*8)) & 0xff;
5723 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5725 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5727 /* this byte of the lit is zero,
5728 *if it's not the last then OR in the variable */
5730 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5735 pic16_emitpLabel(lbl->key);
5736 // pic16_emitpLabel(truelbl->key);
5737 //if(emitFinalCheck)
5738 genSkipc(&rFalseIfx);
5740 pic16_emitpLabel(truelbl->key);
5742 if(ifx) ifx->generated = 1;
5749 if(AOP_TYPE(left) == AOP_LIT) {
5750 //symbol *lbl = newiTempLabel(NULL);
5752 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5755 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5758 if((lit == 0) && (sign == 0)){
5761 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5763 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5765 genSkipz2(&rFalseIfx,0);
5766 if(ifx) ifx->generated = 1;
5773 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5774 /* degenerate compare can never be true */
5775 if(rFalseIfx.condition == 0)
5776 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5778 if(ifx) ifx->generated = 1;
5783 /* signed comparisons to a literal byte */
5785 int lp1 = (lit+1) & 0xff;
5787 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5790 rFalseIfx.condition ^= 1;
5791 genSkipCond(&rFalseIfx,right,0,7);
5794 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5795 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5796 genSkipz2(&rFalseIfx,1);
5799 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5800 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5801 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5802 rFalseIfx.condition ^= 1;
5803 genSkipc(&rFalseIfx);
5807 /* unsigned comparisons to a literal byte */
5809 switch(lit & 0xff ) {
5811 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5812 genSkipz2(&rFalseIfx,0);
5815 rFalseIfx.condition ^= 1;
5816 genSkipCond(&rFalseIfx,right,0,7);
5820 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5821 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5823 rFalseIfx.condition ^= 1;
5824 if (AOP_TYPE(result) == AOP_CRY)
5825 genSkipc(&rFalseIfx);
5827 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5828 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5834 if(ifx) ifx->generated = 1;
5835 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5841 /* Size is greater than 1 */
5849 /* this means lit = 0xffffffff, or -1 */
5852 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5853 rFalseIfx.condition ^= 1;
5854 genSkipCond(&rFalseIfx,right,size,7);
5855 if(ifx) ifx->generated = 1;
5857 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5866 if(rFalseIfx.condition) {
5867 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5868 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5871 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5873 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5877 if(rFalseIfx.condition) {
5878 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5879 pic16_emitpLabel(truelbl->key);
5881 rFalseIfx.condition ^= 1;
5882 genSkipCond(&rFalseIfx,right,s,7);
5885 if(ifx) ifx->generated = 1;
5887 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5893 if((size == 1) && (0 == (lp1&0xff))) {
5894 /* lower byte of signed word is zero */
5895 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5896 i = ((lp1 >> 8) & 0xff) ^0x80;
5897 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5898 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5899 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5901 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5903 if(ifx) ifx->generated = 1;
5906 rFalseIfx.condition ^= 1;
5907 genSkipc(&rFalseIfx);
5908 if(ifx) ifx->generated = 1;
5914 if(lit & (0x80 << (size*8))) {
5915 /* Lit is less than zero */
5916 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5917 //rFalseIfx.condition ^= 1;
5918 //genSkipCond(&rFalseIfx,left,size,7);
5919 //rFalseIfx.condition ^= 1;
5920 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5921 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5923 if(rFalseIfx.condition)
5924 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5926 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5930 /* Lit is greater than or equal to zero */
5931 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5932 //rFalseIfx.condition ^= 1;
5933 //genSkipCond(&rFalseIfx,right,size,7);
5934 //rFalseIfx.condition ^= 1;
5936 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5937 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5939 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5940 if(rFalseIfx.condition)
5941 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5943 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5948 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5952 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5954 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5956 rFalseIfx.condition ^= 1;
5957 //rFalseIfx.condition = 1;
5958 genSkipc(&rFalseIfx);
5960 pic16_emitpLabel(truelbl->key);
5962 if(ifx) ifx->generated = 1;
5965 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5972 /* compare word or long to an unsigned literal on the right.*/
5977 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5980 break; /* handled above */
5983 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5985 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5986 genSkipz2(&rFalseIfx,0);
5990 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5992 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5995 if(rFalseIfx.condition)
5996 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5998 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6001 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6002 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6004 rFalseIfx.condition ^= 1;
6005 genSkipc(&rFalseIfx);
6008 pic16_emitpLabel(truelbl->key);
6010 if(ifx) ifx->generated = 1;
6012 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6020 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6021 i = (lit >> (size*8)) & 0xff;
6023 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6024 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6027 i = (lit >> (size*8)) & 0xff;
6030 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6032 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6034 /* this byte of the lit is zero,
6035 * if it's not the last then OR in the variable */
6037 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6042 pic16_emitpLabel(lbl->key);
6044 rFalseIfx.condition ^= 1;
6046 genSkipc(&rFalseIfx);
6050 pic16_emitpLabel(truelbl->key);
6051 if(ifx) ifx->generated = 1;
6053 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6059 /* Compare two variables */
6061 DEBUGpic16_emitcode(";sign","%d",sign);
6065 /* Sigh. thus sucks... */
6069 pctemp = pic16_popGetTempReg(1);
6070 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6071 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6072 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6073 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6074 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6075 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6076 pic16_popReleaseTempReg(pctemp, 1);
6078 /* Signed char comparison */
6079 /* Special thanks to Nikolai Golovchenko for this snippet */
6080 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6081 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6082 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6083 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6084 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6085 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6087 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6088 genSkipc(&rFalseIfx);
6090 if(ifx) ifx->generated = 1;
6092 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6100 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6101 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6105 /* The rest of the bytes of a multi-byte compare */
6109 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6112 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6113 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6118 pic16_emitpLabel(lbl->key);
6120 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6121 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6122 (AOP_TYPE(result) == AOP_REG)) {
6123 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6124 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6126 genSkipc(&rFalseIfx);
6128 //genSkipc(&rFalseIfx);
6129 if(ifx) ifx->generated = 1;
6132 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6140 if ((AOP_TYPE(result) != AOP_CRY)
6141 && AOP_SIZE(result)) {
6142 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6144 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6146 pic16_outBitC(result);
6148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6149 /* if the result is used in the next
6150 ifx conditional branch then generate
6151 code a little differently */
6153 genIfxJump (ifx,"c");
6155 pic16_outBitC(result);
6156 /* leave the result in acc */
6161 #elif 0 /* VR version of genCmp() */ /* } else { */
6163 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6164 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6165 operand *result, int offset, int invert_op)
6169 /* check condition, > or < ?? */
6170 if(rIfx->condition != 0)invert_op ^= 1;
6172 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6174 if(!ifx)invert_op ^= 1;
6176 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6177 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6180 if(!invert_op)return POC_CPFSGT;
6181 else return POC_CPFSLT;
6184 static int compareAopfirstpass=1;
6186 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6187 operand *oper, int offset, operand *result,
6188 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6194 /* invert if there is a result to be loaded, in order to fit,
6195 * SETC/CLRC sequence */
6196 if(AOP_SIZE(result))invert_op ^= 1;
6198 // if(sign && !offset)invert_op ^= 1;
6200 // if(sign)invert_op ^= 1;
6202 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6204 if(AOP_SIZE(result) && compareAopfirstpass) {
6207 pic16_emitpcode(POC_SETF, pcop2);
6212 pic16_emitpcode(POC_CLRF, pcop2);
6218 compareAopfirstpass = 0;
6220 /* there is a bug when comparing operands with size > 1,
6221 * because higher bytes can be equal and test should be performed
6222 * to the next lower byte, current algorithm, considers operands
6223 * inequal in these cases! -- VR 20041107 */
6227 pic16_emitpcode(op, pcop);
6229 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6232 if((!sign || !offset) && AOP_SIZE(result)) {
6235 pic16_emitpcode(POC_CLRF, pcop2);
6240 pic16_emitpcode(POC_SETF, pcop2);
6245 /* don't emit final branch (offset == 0) */
6249 pic16_emitpcode(POC_RRCF, pcop2);
6251 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6254 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6255 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6256 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6258 truelbl = newiTempLabel( NULL );
6259 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6260 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6261 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6263 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6264 pic16_emitpLabel(truelbl->key);
6266 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6271 static void genCmp (operand *left, operand *right,
6272 operand *result, iCode *ifx, int sign)
6276 resolvedIfx rFalseIfx;
6277 symbol *falselbl, *tlbl;
6281 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6283 resolveIfx(&rFalseIfx, ifx);
6284 size = max(AOP_SIZE(left), AOP_SIZE(right));
6286 /* if left & right are bit variables */
6287 if(AOP_TYPE(left) == AOP_CRY
6288 && AOP_TYPE(right) == AOP_CRY ) {
6290 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6291 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6293 werror(W_POSSBUG2, __FILE__, __LINE__);
6297 /* if literal is on the right then swap with left */
6298 if((AOP_TYPE(right) == AOP_LIT)) {
6299 operand *tmp = right ;
6300 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6302 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6304 // lit = (lit - 1) & mask;
6307 rFalseIfx.condition ^= 1; /* reverse compare */
6309 if ((AOP_TYPE(left) == AOP_LIT)) {
6310 /* float compares are handled by support functions */
6311 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6314 /* actual comparing algorithm */
6315 // size = AOP_SIZE( right );
6317 falselbl = newiTempLabel( NULL );
6318 if(AOP_TYPE(left) == AOP_LIT) {
6319 /* compare to literal */
6320 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6323 pCodeOp *pct, *pct2;
6326 /* signed compare */
6327 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6329 /* using PRODL:PRODH as a temporary register here */
6330 pct = pic16_popCopyReg(&pic16_pc_prodl);
6331 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6332 tlbl = newiTempLabel( NULL );
6334 /* first compare signs:
6335 * a. if both are positive, compare just like unsigned
6336 * b. if both are negative, invert cmpop, compare just like unsigned
6337 * c. if different signs, determine the result directly */
6343 tlbl1 = newiTempLabel( NULL );
6344 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6348 /* literal is zero or positive:
6349 * a. if carry is zero, too, continue compare,
6350 * b. if carry is set, then continue depending on cmpop ^ condition:
6351 * 1. '<' return false (literal < variable),
6352 * 2. '>' return true (literal > variable) */
6353 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6354 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6357 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6358 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6362 /* literal is negative:
6363 * a. if carry is set, too, continue compare,
6364 * b. if carry is zero, then continue depending on cmpop ^ condition:
6365 * 1. '<' return true (literal < variable),
6366 * 2. '>' return false (literal > variable) */
6367 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6368 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6370 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6371 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6376 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6378 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6379 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6384 pic16_emitpLabel( tlbl1->key );
6387 compareAopfirstpass=1;
6388 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6389 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6390 // pic16_emitpcode(POC_MOVWF, pct);
6392 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6393 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6394 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6395 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6399 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6400 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6401 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6402 // pic16_emitpcode(POC_MOVWF, pct);
6404 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6405 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6406 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6407 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6408 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6411 if(ifx)ifx->generated = 1;
6413 if(AOP_SIZE(result)) {
6414 pic16_emitpLabel(tlbl->key);
6415 pic16_emitpLabel(falselbl->key);
6416 pic16_outBitOp( result, pct2 );
6418 pic16_emitpLabel(tlbl->key);
6422 /* unsigned compare */
6423 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6425 compareAopfirstpass=1;
6428 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6429 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6432 if(ifx)ifx->generated = 1;
6434 if(AOP_SIZE(result)) {
6435 pic16_emitpLabel(falselbl->key);
6436 pic16_outBitC( result );
6441 /* compare registers */
6442 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6446 pCodeOp *pct, *pct2;
6448 /* signed compare */
6449 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6451 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6452 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6453 tlbl = newiTempLabel( NULL );
6455 compareAopfirstpass=1;
6458 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6459 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6460 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6461 pic16_emitpcode(POC_MOVWF, pct);
6463 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6464 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6465 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6467 /* WREG already holds left + 0x80 */
6468 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6471 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6472 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6473 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6474 pic16_emitpcode(POC_MOVWF, pct);
6476 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6477 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6478 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6480 /* WREG already holds left + 0x80 */
6481 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6482 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6485 if(ifx)ifx->generated = 1;
6487 if(AOP_SIZE(result)) {
6488 pic16_emitpLabel(tlbl->key);
6489 pic16_emitpLabel(falselbl->key);
6490 pic16_outBitOp( result, pct2 );
6492 pic16_emitpLabel(tlbl->key);
6496 /* unsigned compare */
6497 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6499 compareAopfirstpass=1;
6502 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6503 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6507 if(ifx)ifx->generated = 1;
6508 if(AOP_SIZE(result)) {
6510 pic16_emitpLabel(falselbl->key);
6511 pic16_outBitC( result );
6522 /*-----------------------------------------------------------------*/
6523 /* genCmpGt :- greater than comparison */
6524 /*-----------------------------------------------------------------*/
6525 static void genCmpGt (iCode *ic, iCode *ifx)
6527 operand *left, *right, *result;
6528 sym_link *letype , *retype;
6534 right= IC_RIGHT(ic);
6535 result = IC_RESULT(ic);
6537 letype = getSpec(operandType(left));
6538 retype =getSpec(operandType(right));
6539 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6540 /* assign the amsops */
6541 pic16_aopOp (left,ic,FALSE);
6542 pic16_aopOp (right,ic,FALSE);
6543 pic16_aopOp (result,ic,TRUE);
6545 genCmp(right, left, result, ifx, sign);
6547 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6548 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549 pic16_freeAsmop(result,NULL,ic,TRUE);
6552 /*-----------------------------------------------------------------*/
6553 /* genCmpLt - less than comparisons */
6554 /*-----------------------------------------------------------------*/
6555 static void genCmpLt (iCode *ic, iCode *ifx)
6557 operand *left, *right, *result;
6558 sym_link *letype , *retype;
6564 right= IC_RIGHT(ic);
6565 result = IC_RESULT(ic);
6567 letype = getSpec(operandType(left));
6568 retype =getSpec(operandType(right));
6569 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6571 /* assign the amsops */
6572 pic16_aopOp (left,ic,FALSE);
6573 pic16_aopOp (right,ic,FALSE);
6574 pic16_aopOp (result,ic,TRUE);
6576 genCmp(left, right, result, ifx, sign);
6578 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6579 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580 pic16_freeAsmop(result,NULL,ic,TRUE);
6585 // FIXME reenable literal optimisation when the pic16 port is stable
6587 /*-----------------------------------------------------------------*/
6588 /* genc16bit2lit - compare a 16 bit value to a literal */
6589 /*-----------------------------------------------------------------*/
6590 static void genc16bit2lit(operand *op, int lit, int offset)
6594 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6595 if( (lit&0xff) == 0)
6600 switch( BYTEofLONG(lit,i)) {
6602 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6605 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6608 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6611 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6612 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6617 switch( BYTEofLONG(lit,i)) {
6619 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6623 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6627 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6630 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6632 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6641 /*-----------------------------------------------------------------*/
6642 /* gencjneshort - compare and jump if not equal */
6643 /*-----------------------------------------------------------------*/
6644 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6646 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6648 int res_offset = 0; /* the result may be a different size then left or right */
6649 int res_size = AOP_SIZE(result);
6651 symbol *lbl, *lbl_done;
6653 unsigned long lit = 0L;
6654 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6657 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6659 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6660 resolveIfx(&rIfx,ifx);
6661 lbl = newiTempLabel(NULL);
6662 lbl_done = newiTempLabel(NULL);
6665 /* if the left side is a literal or
6666 if the right is in a pointer register and left
6668 if ((AOP_TYPE(left) == AOP_LIT) ||
6669 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6674 if(AOP_TYPE(right) == AOP_LIT)
6675 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6677 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6678 preserve_result = 1;
6680 if(result && !preserve_result)
6683 for(i = 0; i < AOP_SIZE(result); i++)
6684 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6688 /* if the right side is a literal then anything goes */
6689 if (AOP_TYPE(right) == AOP_LIT &&
6690 AOP_TYPE(left) != AOP_DIR ) {
6693 genc16bit2lit(left, lit, 0);
6695 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6701 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6702 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6704 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6708 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6710 if(res_offset < res_size-1)
6718 /* if the right side is in a register or in direct space or
6719 if the left is a pointer register & right is not */
6720 else if (AOP_TYPE(right) == AOP_REG ||
6721 AOP_TYPE(right) == AOP_DIR ||
6722 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6723 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6724 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6725 int lbl_key = lbl->key;
6728 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6729 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6731 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6732 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6733 __FUNCTION__,__LINE__);
6737 /* switch(size) { */
6739 /* genc16bit2lit(left, lit, 0); */
6741 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6746 if((AOP_TYPE(left) == AOP_DIR) &&
6747 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6749 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6750 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6752 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6754 switch (lit & 0xff) {
6756 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6759 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6760 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6761 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6765 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6766 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6767 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6768 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6772 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6773 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6778 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6781 if(AOP_TYPE(result) == AOP_CRY) {
6782 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6787 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6789 /* fix me. probably need to check result size too */
6790 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6795 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6796 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6803 if(res_offset < res_size-1)
6808 } else if(AOP_TYPE(right) == AOP_REG &&
6809 AOP_TYPE(left) != AOP_DIR){
6812 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6813 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6814 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6819 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6821 if(res_offset < res_size-1)
6826 /* right is a pointer reg need both a & b */
6828 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6830 pic16_emitcode("mov","b,%s",l);
6831 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6832 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6837 if(result && preserve_result)
6840 for(i = 0; i < AOP_SIZE(result); i++)
6841 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6844 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6846 if(result && preserve_result)
6847 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6850 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6852 pic16_emitpLabel(lbl->key);
6854 if(result && preserve_result)
6857 for(i = 0; i < AOP_SIZE(result); i++)
6858 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6860 pic16_emitpLabel(lbl_done->key);
6863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6871 /*-----------------------------------------------------------------*/
6872 /* gencjne - compare and jump if not equal */
6873 /*-----------------------------------------------------------------*/
6874 static void gencjne(operand *left, operand *right, iCode *ifx)
6876 symbol *tlbl = newiTempLabel(NULL);
6878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6879 gencjneshort(left, right, lbl);
6881 pic16_emitcode("mov","a,%s",one);
6882 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6883 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6884 pic16_emitcode("clr","a");
6885 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6887 pic16_emitpLabel(lbl->key);
6888 pic16_emitpLabel(tlbl->key);
6894 /*-----------------------------------------------------------------*/
6895 /* is_LitOp - check if operand has to be treated as literal */
6896 /*-----------------------------------------------------------------*/
6897 static bool is_LitOp(operand *op)
6899 return ((AOP_TYPE(op) == AOP_LIT)
6900 || ( (AOP_TYPE(op) == AOP_PCODE)
6901 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6902 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6905 /*-----------------------------------------------------------------*/
6906 /* is_LitAOp - check if operand has to be treated as literal */
6907 /*-----------------------------------------------------------------*/
6908 static bool is_LitAOp(asmop *aop)
6910 return ((aop->type == AOP_LIT)
6911 || ( (aop->type == AOP_PCODE)
6912 && ( (aop->aopu.pcop->type == PO_LITERAL)
6913 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6918 /*-----------------------------------------------------------------*/
6919 /* genCmpEq - generates code for equal to */
6920 /*-----------------------------------------------------------------*/
6921 static void genCmpEq (iCode *ic, iCode *ifx)
6923 operand *left, *right, *result;
6924 symbol *falselbl = newiTempLabel(NULL);
6925 symbol *donelbl = newiTempLabel(NULL);
6927 int preserve_result = 0;
6928 int generate_result = 0;
6930 unsigned long lit = -1;
6934 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6935 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6936 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6938 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6940 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6942 werror(W_POSSBUG2, __FILE__, __LINE__);
6943 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6944 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6948 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6950 operand *tmp = right ;
6955 if (AOP_TYPE(right) == AOP_LIT) {
6956 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6959 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6960 preserve_result = 1;
6962 if(result && AOP_SIZE(result))
6963 generate_result = 1;
6965 if(generate_result && !preserve_result)
6967 for(i = 0; i < AOP_SIZE(result); i++)
6968 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6971 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6972 for(i=0; i < AOP_SIZE(left); i++)
6974 if(AOP_TYPE(left) != AOP_ACC)
6977 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6979 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6981 if(is_LitOp(right)) {
6982 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6983 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6986 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6988 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6993 if(generate_result && preserve_result)
6995 for(i = 0; i < AOP_SIZE(result); i++)
6996 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7000 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7002 if(generate_result && preserve_result)
7003 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7005 if(ifx && IC_TRUE(ifx))
7006 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7008 if(ifx && IC_FALSE(ifx))
7009 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7011 pic16_emitpLabel(falselbl->key);
7015 if(ifx && IC_FALSE(ifx))
7016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7018 if(generate_result && preserve_result)
7020 for(i = 0; i < AOP_SIZE(result); i++)
7021 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7024 pic16_emitpLabel(donelbl->key);
7030 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032 pic16_freeAsmop(result,NULL,ic,TRUE);
7038 // old version kept for reference
7040 /*-----------------------------------------------------------------*/
7041 /* genCmpEq - generates code for equal to */
7042 /*-----------------------------------------------------------------*/
7043 static void genCmpEq (iCode *ic, iCode *ifx)
7045 operand *left, *right, *result;
7046 unsigned long lit = 0L;
7048 symbol *falselbl = newiTempLabel(NULL);
7051 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7054 DEBUGpic16_emitcode ("; ifx is non-null","");
7056 DEBUGpic16_emitcode ("; ifx is null","");
7058 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7059 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7060 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7062 size = max(AOP_SIZE(left),AOP_SIZE(right));
7064 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7066 /* if literal, literal on the right or
7067 if the right is in a pointer register and left
7069 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7070 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7071 operand *tmp = right ;
7077 if(ifx && !AOP_SIZE(result)){
7079 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7080 /* if they are both bit variables */
7081 if (AOP_TYPE(left) == AOP_CRY &&
7082 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7083 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7084 if(AOP_TYPE(right) == AOP_LIT){
7085 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7087 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7088 pic16_emitcode("cpl","c");
7089 } else if(lit == 1L) {
7090 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092 pic16_emitcode("clr","c");
7094 /* AOP_TYPE(right) == AOP_CRY */
7096 symbol *lbl = newiTempLabel(NULL);
7097 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7098 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7099 pic16_emitcode("cpl","c");
7100 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7102 /* if true label then we jump if condition
7104 tlbl = newiTempLabel(NULL);
7105 if ( IC_TRUE(ifx) ) {
7106 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7107 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7109 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7110 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7112 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7115 /* left and right are both bit variables, result is carry */
7118 resolveIfx(&rIfx,ifx);
7120 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7121 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7122 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7123 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7128 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7130 /* They're not both bit variables. Is the right a literal? */
7131 if(AOP_TYPE(right) == AOP_LIT) {
7132 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7137 switch(lit & 0xff) {
7139 if ( IC_TRUE(ifx) ) {
7140 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7142 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7144 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7145 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7149 if ( IC_TRUE(ifx) ) {
7150 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7152 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7154 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7159 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7161 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7166 /* end of size == 1 */
7170 genc16bit2lit(left,lit,offset);
7173 /* end of size == 2 */
7178 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7179 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7180 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7181 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7184 /* search for patterns that can be optimized */
7186 genc16bit2lit(left,lit,0);
7190 emitSKPZ; // if hi word unequal
7192 emitSKPNZ; // if hi word equal
7194 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7195 genc16bit2lit(left,lit,2);
7198 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7199 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7203 pic16_emitpLabel(falselbl->key);
7212 } else if(AOP_TYPE(right) == AOP_CRY ) {
7213 /* we know the left is not a bit, but that the right is */
7214 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7215 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7216 pic16_popGet(AOP(right),offset));
7217 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7219 /* if the two are equal, then W will be 0 and the Z bit is set
7220 * we could test Z now, or go ahead and check the high order bytes if
7221 * the variable we're comparing is larger than a byte. */
7224 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7226 if ( IC_TRUE(ifx) ) {
7228 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7229 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7232 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7233 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7237 /* They're both variables that are larger than bits */
7240 tlbl = newiTempLabel(NULL);
7243 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7244 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7246 if ( IC_TRUE(ifx) ) {
7250 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7252 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7253 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7257 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7260 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7261 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7266 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7268 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7269 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7273 if(s>1 && IC_TRUE(ifx)) {
7274 pic16_emitpLabel(tlbl->key);
7275 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7279 /* mark the icode as generated */
7284 /* if they are both bit variables */
7285 if (AOP_TYPE(left) == AOP_CRY &&
7286 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7287 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7288 if(AOP_TYPE(right) == AOP_LIT){
7289 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7291 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7292 pic16_emitcode("cpl","c");
7293 } else if(lit == 1L) {
7294 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296 pic16_emitcode("clr","c");
7298 /* AOP_TYPE(right) == AOP_CRY */
7300 symbol *lbl = newiTempLabel(NULL);
7301 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7302 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7303 pic16_emitcode("cpl","c");
7304 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7307 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7308 pic16_outBitC(result);
7312 genIfxJump (ifx,"c");
7315 /* if the result is used in an arithmetic operation
7316 then put the result in place */
7317 pic16_outBitC(result);
7320 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7321 gencjne(left,right,result,ifx);
7324 gencjne(left,right,newiTempLabel(NULL));
7326 if(IC_TRUE(ifx)->key)
7327 gencjne(left,right,IC_TRUE(ifx)->key);
7329 gencjne(left,right,IC_FALSE(ifx)->key);
7333 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7334 pic16_aopPut(AOP(result),"a",0);
7339 genIfxJump (ifx,"a");
7343 /* if the result is used in an arithmetic operation
7344 then put the result in place */
7346 if (AOP_TYPE(result) != AOP_CRY)
7347 pic16_outAcc(result);
7349 /* leave the result in acc */
7353 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7354 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355 pic16_freeAsmop(result,NULL,ic,TRUE);
7359 /*-----------------------------------------------------------------*/
7360 /* ifxForOp - returns the icode containing the ifx for operand */
7361 /*-----------------------------------------------------------------*/
7362 static iCode *ifxForOp ( operand *op, iCode *ic )
7366 /* if true symbol then needs to be assigned */
7367 if (IS_TRUE_SYMOP(op))
7370 /* if this has register type condition and
7371 the next instruction is ifx with the same operand
7372 and live to of the operand is upto the ifx only then */
7374 && ic->next->op == IFX
7375 && IC_COND(ic->next)->key == op->key
7376 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7378 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7384 ic->next->op == IFX &&
7385 IC_COND(ic->next)->key == op->key) {
7386 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7391 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7393 ic->next->op == IFX)
7394 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7397 ic->next->op == IFX &&
7398 IC_COND(ic->next)->key == op->key) {
7399 DEBUGpic16_emitcode ("; "," key is okay");
7400 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7401 OP_SYMBOL(op)->liveTo,
7406 /* the code below is completely untested
7407 * it just allows ulong2fs.c compile -- VR */
7410 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7411 __FILE__, __FUNCTION__, __LINE__);
7413 /* if this has register type condition and
7414 the next instruction is ifx with the same operand
7415 and live to of the operand is upto the ifx only then */
7417 ic->next->op == IFX &&
7418 IC_COND(ic->next)->key == op->key &&
7419 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7423 ic->next->op == IFX &&
7424 IC_COND(ic->next)->key == op->key) {
7425 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7429 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7430 __FILE__, __FUNCTION__, __LINE__);
7432 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7437 /*-----------------------------------------------------------------*/
7438 /* genAndOp - for && operation */
7439 /*-----------------------------------------------------------------*/
7440 static void genAndOp (iCode *ic)
7442 operand *left,*right, *result;
7447 /* note here that && operations that are in an
7448 if statement are taken away by backPatchLabels
7449 only those used in arthmetic operations remain */
7450 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7451 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7452 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7454 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7456 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7457 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7458 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7460 /* if both are bit variables */
7461 /* if (AOP_TYPE(left) == AOP_CRY && */
7462 /* AOP_TYPE(right) == AOP_CRY ) { */
7463 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7464 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7465 /* pic16_outBitC(result); */
7467 /* tlbl = newiTempLabel(NULL); */
7468 /* pic16_toBoolean(left); */
7469 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7470 /* pic16_toBoolean(right); */
7471 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7472 /* pic16_outBitAcc(result); */
7475 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7476 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477 pic16_freeAsmop(result,NULL,ic,TRUE);
7481 /*-----------------------------------------------------------------*/
7482 /* genOrOp - for || operation */
7483 /*-----------------------------------------------------------------*/
7486 modified this code, but it doesn't appear to ever get called
7489 static void genOrOp (iCode *ic)
7491 operand *left,*right, *result;
7496 /* note here that || operations that are in an
7497 if statement are taken away by backPatchLabels
7498 only those used in arthmetic operations remain */
7499 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7500 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7501 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7503 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7505 /* if both are bit variables */
7506 if (AOP_TYPE(left) == AOP_CRY &&
7507 AOP_TYPE(right) == AOP_CRY ) {
7508 pic16_emitcode("clrc","");
7509 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7510 AOP(left)->aopu.aop_dir,
7511 AOP(left)->aopu.aop_dir);
7512 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7513 AOP(right)->aopu.aop_dir,
7514 AOP(right)->aopu.aop_dir);
7515 pic16_emitcode("setc","");
7518 tlbl = newiTempLabel(NULL);
7519 pic16_toBoolean(left);
7521 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7522 pic16_toBoolean(right);
7523 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7525 pic16_outBitAcc(result);
7528 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7529 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530 pic16_freeAsmop(result,NULL,ic,TRUE);
7533 /*-----------------------------------------------------------------*/
7534 /* isLiteralBit - test if lit == 2^n */
7535 /*-----------------------------------------------------------------*/
7536 static int isLiteralBit(unsigned long lit)
7538 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7539 0x100L,0x200L,0x400L,0x800L,
7540 0x1000L,0x2000L,0x4000L,0x8000L,
7541 0x10000L,0x20000L,0x40000L,0x80000L,
7542 0x100000L,0x200000L,0x400000L,0x800000L,
7543 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7544 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7548 for(idx = 0; idx < 32; idx++)
7554 /*-----------------------------------------------------------------*/
7555 /* continueIfTrue - */
7556 /*-----------------------------------------------------------------*/
7557 static void continueIfTrue (iCode *ic)
7561 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7565 /*-----------------------------------------------------------------*/
7567 /*-----------------------------------------------------------------*/
7568 static void jumpIfTrue (iCode *ic)
7572 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7576 /*-----------------------------------------------------------------*/
7577 /* jmpTrueOrFalse - */
7578 /*-----------------------------------------------------------------*/
7579 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7581 // ugly but optimized by peephole
7584 symbol *nlbl = newiTempLabel(NULL);
7585 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7586 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7587 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7588 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7590 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7591 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7596 /*-----------------------------------------------------------------*/
7597 /* genAnd - code for and */
7598 /*-----------------------------------------------------------------*/
7599 static void genAnd (iCode *ic, iCode *ifx)
7601 operand *left, *right, *result;
7603 unsigned long lit = 0L;
7609 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7610 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7611 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7613 resolveIfx(&rIfx,ifx);
7615 /* if left is a literal & right is not then exchange them */
7616 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7617 AOP_NEEDSACC(left)) {
7618 operand *tmp = right ;
7623 /* if result = right then exchange them */
7624 if(pic16_sameRegs(AOP(result),AOP(right))){
7625 operand *tmp = right ;
7630 /* if right is bit then exchange them */
7631 if (AOP_TYPE(right) == AOP_CRY &&
7632 AOP_TYPE(left) != AOP_CRY){
7633 operand *tmp = right ;
7637 if(AOP_TYPE(right) == AOP_LIT)
7638 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7640 size = AOP_SIZE(result);
7642 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7645 // result = bit & yy;
7646 if (AOP_TYPE(left) == AOP_CRY){
7647 // c = bit & literal;
7648 if(AOP_TYPE(right) == AOP_LIT){
7650 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7653 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7656 if(size && (AOP_TYPE(result) == AOP_CRY)){
7657 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7660 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7664 pic16_emitcode("clr","c");
7667 if (AOP_TYPE(right) == AOP_CRY){
7669 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7670 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7673 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7675 pic16_emitcode("rrc","a");
7676 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7682 pic16_outBitC(result);
7684 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7685 genIfxJump(ifx, "c");
7689 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7690 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7691 if((AOP_TYPE(right) == AOP_LIT) &&
7692 (AOP_TYPE(result) == AOP_CRY) &&
7693 (AOP_TYPE(left) != AOP_CRY)){
7694 int posbit = isLiteralBit(lit);
7698 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7701 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7707 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7708 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7710 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7711 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7714 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7715 size = AOP_SIZE(left);
7718 int bp = posbit, ofs=0;
7725 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7726 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7730 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7731 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7733 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7740 symbol *tlbl = newiTempLabel(NULL);
7741 int sizel = AOP_SIZE(left);
7747 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7749 /* patch provided by Aaron Colwell */
7750 if((posbit = isLiteralBit(bytelit)) != 0) {
7751 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7752 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7753 (posbit-1),0, PO_GPR_REGISTER));
7755 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7756 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7758 if (bytelit == 0xff) {
7759 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7760 * a peephole could optimize it out -- VR */
7761 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7764 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7767 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7768 pic16_popGetLabel(tlbl->key));
7772 /* old code, left here for reference -- VR 09/2004 */
7773 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7775 if((posbit = isLiteralBit(bytelit)) != 0)
7776 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7778 if(bytelit != 0x0FFL)
7779 pic16_emitcode("anl","a,%s",
7780 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7781 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7787 // bit = left & literal
7790 pic16_emitpLabel(tlbl->key);
7792 // if(left & literal)
7795 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7798 pic16_emitpLabel(tlbl->key);
7803 pic16_outBitC(result);
7807 /* if left is same as result */
7808 if(pic16_sameRegs(AOP(result),AOP(left))){
7810 for(;size--; offset++,lit>>=8) {
7811 if(AOP_TYPE(right) == AOP_LIT){
7812 switch(lit & 0xff) {
7814 /* and'ing with 0 has clears the result */
7815 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7816 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7819 /* and'ing with 0xff is a nop when the result and left are the same */
7824 int p = pic16_my_powof2( (~lit) & 0xff );
7826 /* only one bit is set in the literal, so use a bcf instruction */
7827 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7828 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7831 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7832 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7833 if(know_W != (lit&0xff))
7834 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7836 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7841 if (AOP_TYPE(left) == AOP_ACC) {
7842 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7844 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7845 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7852 // left & result in different registers
7853 if(AOP_TYPE(result) == AOP_CRY){
7855 // if(size), result in bit
7856 // if(!size && ifx), conditional oper: if(left & right)
7857 symbol *tlbl = newiTempLabel(NULL);
7858 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7860 pic16_emitcode("setb","c");
7862 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7863 pic16_emitcode("anl","a,%s",
7864 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7865 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7870 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7871 pic16_outBitC(result);
7873 jmpTrueOrFalse(ifx, tlbl);
7875 for(;(size--);offset++) {
7877 // result = left & right
7878 if(AOP_TYPE(right) == AOP_LIT){
7879 int t = (lit >> (offset*8)) & 0x0FFL;
7882 pic16_emitcode("clrf","%s",
7883 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7884 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7887 pic16_emitcode("movf","%s,w",
7888 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7889 pic16_emitcode("movwf","%s",
7890 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7891 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7892 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7895 pic16_emitcode("movlw","0x%x",t);
7896 pic16_emitcode("andwf","%s,w",
7897 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7898 pic16_emitcode("movwf","%s",
7899 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7901 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7902 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7903 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7908 if (AOP_TYPE(left) == AOP_ACC) {
7909 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7912 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7913 pic16_emitcode("andwf","%s,w",
7914 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7916 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7918 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7919 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7925 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7926 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7927 pic16_freeAsmop(result,NULL,ic,TRUE);
7930 /*-----------------------------------------------------------------*/
7931 /* genOr - code for or */
7932 /*-----------------------------------------------------------------*/
7933 static void genOr (iCode *ic, iCode *ifx)
7935 operand *left, *right, *result;
7937 unsigned long lit = 0L;
7939 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7942 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7943 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7944 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7946 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7948 /* if left is a literal & right is not then exchange them */
7949 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7950 AOP_NEEDSACC(left)) {
7951 operand *tmp = right ;
7956 /* if result = right then exchange them */
7957 if(pic16_sameRegs(AOP(result),AOP(right))){
7958 operand *tmp = right ;
7963 /* if right is bit then exchange them */
7964 if (AOP_TYPE(right) == AOP_CRY &&
7965 AOP_TYPE(left) != AOP_CRY){
7966 operand *tmp = right ;
7971 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7973 if(AOP_TYPE(right) == AOP_LIT)
7974 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7976 size = AOP_SIZE(result);
7980 if (AOP_TYPE(left) == AOP_CRY){
7981 if(AOP_TYPE(right) == AOP_LIT){
7982 // c = bit & literal;
7984 // lit != 0 => result = 1
7985 if(AOP_TYPE(result) == AOP_CRY){
7987 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7988 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7989 // AOP(result)->aopu.aop_dir,
7990 // AOP(result)->aopu.aop_dir);
7992 continueIfTrue(ifx);
7996 // lit == 0 => result = left
7997 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7999 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8002 if (AOP_TYPE(right) == AOP_CRY){
8003 if(pic16_sameRegs(AOP(result),AOP(left))){
8005 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8006 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8007 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8009 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8010 AOP(result)->aopu.aop_dir,
8011 AOP(result)->aopu.aop_dir);
8012 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8013 AOP(right)->aopu.aop_dir,
8014 AOP(right)->aopu.aop_dir);
8015 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8016 AOP(result)->aopu.aop_dir,
8017 AOP(result)->aopu.aop_dir);
8019 if( AOP_TYPE(result) == AOP_ACC) {
8020 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8021 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8022 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8023 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8027 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8028 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8029 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8030 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8032 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8033 AOP(result)->aopu.aop_dir,
8034 AOP(result)->aopu.aop_dir);
8035 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8036 AOP(right)->aopu.aop_dir,
8037 AOP(right)->aopu.aop_dir);
8038 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8039 AOP(left)->aopu.aop_dir,
8040 AOP(left)->aopu.aop_dir);
8041 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8042 AOP(result)->aopu.aop_dir,
8043 AOP(result)->aopu.aop_dir);
8048 symbol *tlbl = newiTempLabel(NULL);
8049 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8052 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8053 if( AOP_TYPE(right) == AOP_ACC) {
8054 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8056 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8057 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8062 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8063 pic16_emitcode(";XXX setb","c");
8064 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8065 AOP(left)->aopu.aop_dir,tlbl->key+100);
8066 pic16_toBoolean(right);
8067 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8068 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8069 jmpTrueOrFalse(ifx, tlbl);
8073 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8080 pic16_outBitC(result);
8082 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8083 genIfxJump(ifx, "c");
8087 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8088 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8089 if((AOP_TYPE(right) == AOP_LIT) &&
8090 (AOP_TYPE(result) == AOP_CRY) &&
8091 (AOP_TYPE(left) != AOP_CRY)){
8093 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8096 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8098 continueIfTrue(ifx);
8101 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8102 // lit = 0, result = boolean(left)
8104 pic16_emitcode(";XXX setb","c");
8105 pic16_toBoolean(right);
8107 symbol *tlbl = newiTempLabel(NULL);
8108 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8110 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8112 genIfxJump (ifx,"a");
8116 pic16_outBitC(result);
8120 /* if left is same as result */
8121 if(pic16_sameRegs(AOP(result),AOP(left))){
8123 for(;size--; offset++,lit>>=8) {
8124 if(AOP_TYPE(right) == AOP_LIT){
8125 if((lit & 0xff) == 0)
8126 /* or'ing with 0 has no effect */
8129 int p = pic16_my_powof2(lit & 0xff);
8131 /* only one bit is set in the literal, so use a bsf instruction */
8132 pic16_emitpcode(POC_BSF,
8133 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8135 if(know_W != (lit & 0xff))
8136 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8137 know_W = lit & 0xff;
8138 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8143 if (AOP_TYPE(left) == AOP_ACC) {
8144 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8145 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8147 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8148 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8150 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8157 // left & result in different registers
8158 if(AOP_TYPE(result) == AOP_CRY){
8160 // if(size), result in bit
8161 // if(!size && ifx), conditional oper: if(left | right)
8162 symbol *tlbl = newiTempLabel(NULL);
8163 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8164 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8168 pic16_emitcode(";XXX setb","c");
8170 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8171 pic16_emitcode(";XXX orl","a,%s",
8172 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8178 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8179 pic16_outBitC(result);
8181 jmpTrueOrFalse(ifx, tlbl);
8182 } else for(;(size--);offset++){
8184 // result = left & right
8185 if(AOP_TYPE(right) == AOP_LIT){
8186 int t = (lit >> (offset*8)) & 0x0FFL;
8189 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8190 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8192 // pic16_emitcode("movf","%s,w",
8193 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8194 // pic16_emitcode("movwf","%s",
8195 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8198 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8199 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8200 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8202 // pic16_emitcode("movlw","0x%x",t);
8203 // pic16_emitcode("iorwf","%s,w",
8204 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8205 // pic16_emitcode("movwf","%s",
8206 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8212 // faster than result <- left, anl result,right
8213 // and better if result is SFR
8214 if (AOP_TYPE(left) == AOP_ACC) {
8215 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8216 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8219 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8221 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8222 // pic16_emitcode("iorwf","%s,w",
8223 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8225 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8226 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8231 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8232 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8233 pic16_freeAsmop(result,NULL,ic,TRUE);
8236 /*-----------------------------------------------------------------*/
8237 /* genXor - code for xclusive or */
8238 /*-----------------------------------------------------------------*/
8239 static void genXor (iCode *ic, iCode *ifx)
8241 operand *left, *right, *result;
8243 unsigned long lit = 0L;
8245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8248 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8249 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8250 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8252 /* if left is a literal & right is not ||
8253 if left needs acc & right does not */
8254 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8255 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8256 operand *tmp = right ;
8261 /* if result = right then exchange them */
8262 if(pic16_sameRegs(AOP(result),AOP(right))){
8263 operand *tmp = right ;
8268 /* if right is bit then exchange them */
8269 if (AOP_TYPE(right) == AOP_CRY &&
8270 AOP_TYPE(left) != AOP_CRY){
8271 operand *tmp = right ;
8275 if(AOP_TYPE(right) == AOP_LIT)
8276 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8278 size = AOP_SIZE(result);
8282 if (AOP_TYPE(left) == AOP_CRY){
8283 if(AOP_TYPE(right) == AOP_LIT){
8284 // c = bit & literal;
8286 // lit>>1 != 0 => result = 1
8287 if(AOP_TYPE(result) == AOP_CRY){
8289 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8290 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8292 continueIfTrue(ifx);
8295 pic16_emitcode("setb","c");
8299 // lit == 0, result = left
8300 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8302 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8304 // lit == 1, result = not(left)
8305 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8306 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8307 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8308 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8311 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8312 pic16_emitcode("cpl","c");
8319 symbol *tlbl = newiTempLabel(NULL);
8320 if (AOP_TYPE(right) == AOP_CRY){
8322 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8325 int sizer = AOP_SIZE(right);
8327 // if val>>1 != 0, result = 1
8328 pic16_emitcode("setb","c");
8330 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8332 // test the msb of the lsb
8333 pic16_emitcode("anl","a,#0xfe");
8334 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8338 pic16_emitcode("rrc","a");
8340 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8341 pic16_emitcode("cpl","c");
8342 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8347 pic16_outBitC(result);
8349 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8350 genIfxJump(ifx, "c");
8354 if(pic16_sameRegs(AOP(result),AOP(left))){
8355 /* if left is same as result */
8356 for(;size--; offset++) {
8357 if(AOP_TYPE(right) == AOP_LIT){
8358 int t = (lit >> (offset*8)) & 0x0FFL;
8362 if (IS_AOP_PREG(left)) {
8363 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8364 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8365 pic16_aopPut(AOP(result),"a",offset);
8367 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8368 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8369 pic16_emitcode("xrl","%s,%s",
8370 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8371 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8374 if (AOP_TYPE(left) == AOP_ACC)
8375 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8377 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8378 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8380 if (IS_AOP_PREG(left)) {
8381 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8382 pic16_aopPut(AOP(result),"a",offset);
8384 pic16_emitcode("xrl","%s,a",
8385 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8391 // left & result in different registers
8392 if(AOP_TYPE(result) == AOP_CRY){
8394 // if(size), result in bit
8395 // if(!size && ifx), conditional oper: if(left ^ right)
8396 symbol *tlbl = newiTempLabel(NULL);
8397 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8399 pic16_emitcode("setb","c");
8401 if((AOP_TYPE(right) == AOP_LIT) &&
8402 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8403 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8405 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8406 pic16_emitcode("xrl","a,%s",
8407 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8409 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8414 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8415 pic16_outBitC(result);
8417 jmpTrueOrFalse(ifx, tlbl);
8418 } else for(;(size--);offset++){
8420 // result = left & right
8421 if(AOP_TYPE(right) == AOP_LIT){
8422 int t = (lit >> (offset*8)) & 0x0FFL;
8425 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8426 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8427 pic16_emitcode("movf","%s,w",
8428 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8429 pic16_emitcode("movwf","%s",
8430 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8433 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8434 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8435 pic16_emitcode("comf","%s,w",
8436 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8437 pic16_emitcode("movwf","%s",
8438 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8442 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8443 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8444 pic16_emitcode("movlw","0x%x",t);
8445 pic16_emitcode("xorwf","%s,w",
8446 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8447 pic16_emitcode("movwf","%s",
8448 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8454 // faster than result <- left, anl result,right
8455 // and better if result is SFR
8456 if (AOP_TYPE(left) == AOP_ACC) {
8457 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8458 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8460 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8461 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8462 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8463 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8465 if ( AOP_TYPE(result) != AOP_ACC){
8466 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8467 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8473 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8474 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8475 pic16_freeAsmop(result,NULL,ic,TRUE);
8478 /*-----------------------------------------------------------------*/
8479 /* genInline - write the inline code out */
8480 /*-----------------------------------------------------------------*/
8481 static void genInline (iCode *ic)
8483 char *buffer, *bp, *bp1;
8485 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8487 _G.inLine += (!options.asmpeep);
8489 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8490 strcpy(buffer,IC_INLINE(ic));
8492 while((bp1=strstr(bp, "\\n"))) {
8500 /* This is an experimental code for #pragma inline
8501 and is temporarily disabled for 2.5.0 release */
8509 cbuf = Safe_strdup(buffer);
8510 cblen = strlen(buffer)+1;
8511 memset(cbuf, 0, cblen);
8516 if(*bp != '%')*bp1++ = *bp++;
8522 if(i>elementsInSet(asmInlineMap))break;
8525 s = indexSet(asmInlineMap, i);
8526 DEBUGpc("searching symbol s = `%s'", s);
8527 sym = findSym(SymbolTab, NULL, s);
8530 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8532 strcat(bp1, sym->rname);
8538 if(strlen(bp1) > cblen - 16) {
8539 int i = strlen(cbuf);
8541 cbuf = realloc(cbuf, cblen);
8542 memset(cbuf+i, 0, 50);
8548 buffer = Safe_strdup( cbuf );
8555 /* emit each line as a code */
8561 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8569 /* print label, use this special format with NULL directive
8570 * to denote that the argument should not be indented with tab */
8571 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8574 /* advance to end of line (prevent splitting of comments at ':' */
8575 while (*bp && *bp != '\n') {
8583 if ((bp1 != bp) && *bp1)
8584 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8589 _G.inLine -= (!options.asmpeep);
8592 /*-----------------------------------------------------------------*/
8593 /* genRRC - rotate right with carry */
8594 /*-----------------------------------------------------------------*/
8595 static void genRRC (iCode *ic)
8597 operand *left , *result ;
8598 int size, offset = 0, same;
8600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8602 /* rotate right with carry */
8604 result=IC_RESULT(ic);
8605 pic16_aopOp (left,ic,FALSE);
8606 pic16_aopOp (result,ic,TRUE);
8608 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8610 same = pic16_sameRegs(AOP(result),AOP(left));
8612 size = AOP_SIZE(result);
8614 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8616 /* get the lsb and put it into the carry */
8617 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8624 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8626 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8633 pic16_freeAsmop(left,NULL,ic,TRUE);
8634 pic16_freeAsmop(result,NULL,ic,TRUE);
8637 /*-----------------------------------------------------------------*/
8638 /* genRLC - generate code for rotate left with carry */
8639 /*-----------------------------------------------------------------*/
8640 static void genRLC (iCode *ic)
8642 operand *left , *result ;
8643 int size, offset = 0;
8646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8647 /* rotate right with carry */
8649 result=IC_RESULT(ic);
8650 pic16_aopOp (left,ic,FALSE);
8651 pic16_aopOp (result,ic,TRUE);
8653 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8655 same = pic16_sameRegs(AOP(result),AOP(left));
8657 /* move it to the result */
8658 size = AOP_SIZE(result);
8660 /* get the msb and put it into the carry */
8661 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8668 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8670 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8671 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8678 pic16_freeAsmop(left,NULL,ic,TRUE);
8679 pic16_freeAsmop(result,NULL,ic,TRUE);
8683 /* gpasm can get the highest order bit with HIGH/UPPER
8684 * so the following probably is not needed -- VR */
8686 /*-----------------------------------------------------------------*/
8687 /* genGetHbit - generates code get highest order bit */
8688 /*-----------------------------------------------------------------*/
8689 static void genGetHbit (iCode *ic)
8691 operand *left, *result;
8693 result=IC_RESULT(ic);
8694 pic16_aopOp (left,ic,FALSE);
8695 pic16_aopOp (result,ic,FALSE);
8697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8698 /* get the highest order byte into a */
8699 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8700 if(AOP_TYPE(result) == AOP_CRY){
8701 pic16_emitcode("rlc","a");
8702 pic16_outBitC(result);
8705 pic16_emitcode("rl","a");
8706 pic16_emitcode("anl","a,#0x01");
8707 pic16_outAcc(result);
8711 pic16_freeAsmop(left,NULL,ic,TRUE);
8712 pic16_freeAsmop(result,NULL,ic,TRUE);
8716 /*-----------------------------------------------------------------*/
8717 /* AccRol - rotate left accumulator by known count */
8718 /*-----------------------------------------------------------------*/
8719 static void AccRol (int shCount)
8721 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8722 shCount &= 0x0007; // shCount : 0..7
8727 pic16_emitcode("rl","a");
8730 pic16_emitcode("rl","a");
8731 pic16_emitcode("rl","a");
8734 pic16_emitcode("swap","a");
8735 pic16_emitcode("rr","a");
8738 pic16_emitcode("swap","a");
8741 pic16_emitcode("swap","a");
8742 pic16_emitcode("rl","a");
8745 pic16_emitcode("rr","a");
8746 pic16_emitcode("rr","a");
8749 pic16_emitcode("rr","a");
8755 /*-----------------------------------------------------------------*/
8756 /* AccLsh - left shift accumulator by known count */
8757 /*-----------------------------------------------------------------*/
8758 static void AccLsh (int shCount, int doMask)
8760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8766 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8770 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8773 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8774 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8777 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8780 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8781 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8784 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8785 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8788 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8792 /* no masking is required in genPackBits */
8793 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8797 /*-----------------------------------------------------------------*/
8798 /* AccRsh - right shift accumulator by known count */
8799 /*-----------------------------------------------------------------*/
8800 static void AccRsh (int shCount, int andmask)
8802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8807 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8810 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8811 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8814 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8815 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8818 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8821 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8822 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8825 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8826 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8829 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8834 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8836 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8840 /*-----------------------------------------------------------------*/
8841 /* AccSRsh - signed right shift accumulator by known count */
8842 /*-----------------------------------------------------------------*/
8843 static void AccSRsh (int shCount)
8846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8849 pic16_emitcode("mov","c,acc.7");
8850 pic16_emitcode("rrc","a");
8851 } else if(shCount == 2){
8852 pic16_emitcode("mov","c,acc.7");
8853 pic16_emitcode("rrc","a");
8854 pic16_emitcode("mov","c,acc.7");
8855 pic16_emitcode("rrc","a");
8857 tlbl = newiTempLabel(NULL);
8858 /* rotate right accumulator */
8859 AccRol(8 - shCount);
8860 /* and kill the higher order bits */
8861 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8862 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8863 pic16_emitcode("orl","a,#0x%02x",
8864 (unsigned char)~SRMask[shCount]);
8865 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8871 /*-----------------------------------------------------------------*/
8872 /* shiftR1Left2Result - shift right one byte from left to result */
8873 /*-----------------------------------------------------------------*/
8874 static void shiftR1Left2ResultSigned (operand *left, int offl,
8875 operand *result, int offr,
8880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8882 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8886 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8888 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8890 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8891 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8899 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8904 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8905 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8911 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8917 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8918 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8921 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8922 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8924 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8928 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8929 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8930 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8931 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8932 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8936 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8943 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8944 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8951 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8952 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8953 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8954 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8959 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8961 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8967 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8968 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8969 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8970 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8974 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8982 /*-----------------------------------------------------------------*/
8983 /* shiftR1Left2Result - shift right one byte from left to result */
8984 /*-----------------------------------------------------------------*/
8985 static void shiftR1Left2Result (operand *left, int offl,
8986 operand *result, int offr,
8987 int shCount, int sign)
8991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8993 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8995 /* Copy the msb into the carry if signed. */
8997 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9007 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9009 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9010 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9034 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9036 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9041 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
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(0x0e));
9048 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9050 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9056 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9058 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9064 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9065 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9066 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9075 /*-----------------------------------------------------------------*/
9076 /* shiftL1Left2Result - shift left one byte from left to result */
9077 /*-----------------------------------------------------------------*/
9078 static void shiftL1Left2Result (operand *left, int offl,
9079 operand *result, int offr, int shCount)
9084 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9086 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9087 DEBUGpic16_emitcode ("; ***","same = %d",same);
9088 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9090 /* shift left accumulator */
9091 //AccLsh(shCount, 1); // don't comment out just yet...
9092 // pic16_aopPut(AOP(result),"a",offr);
9096 /* Shift left 1 bit position */
9097 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9099 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9101 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9102 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9107 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9108 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9113 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9114 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9119 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9124 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9125 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9126 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9130 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9131 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9132 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9133 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9138 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9139 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9143 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9148 /*-----------------------------------------------------------------*/
9149 /* movLeft2Result - move byte from left to result */
9150 /*-----------------------------------------------------------------*/
9151 static void movLeft2Result (operand *left, int offl,
9152 operand *result, int offr)
9155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9156 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9157 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9159 if (*l == '@' && (IS_AOP_PREG(result))) {
9160 pic16_emitcode("mov","a,%s",l);
9161 pic16_aopPut(AOP(result),"a",offr);
9163 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9164 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9169 /*-----------------------------------------------------------------*/
9170 /* shiftL2Left2Result - shift left two bytes from left to result */
9171 /*-----------------------------------------------------------------*/
9172 static void shiftL2Left2Result (operand *left, int offl,
9173 operand *result, int offr, int shCount)
9175 int same = pic16_sameRegs(AOP(result), AOP(left));
9178 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9180 if (same && (offl != offr)) { // shift bytes
9183 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9184 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9186 } else { // just treat as different later on
9199 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9200 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9205 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9206 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9212 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9213 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9214 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9215 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9216 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9217 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9218 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9220 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9221 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9225 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9226 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9227 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9228 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9229 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9230 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9231 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9232 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9234 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9237 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9238 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9239 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9240 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9241 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9251 /* note, use a mov/add for the shift since the mov has a
9252 chance of getting optimized out */
9253 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9255 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9256 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9257 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9261 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9262 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9268 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9269 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9271 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9272 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9273 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9274 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9275 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9279 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9280 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9284 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9285 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9286 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9287 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9289 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9291 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9292 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9293 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9294 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9295 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9296 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9300 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9302 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9308 /*-----------------------------------------------------------------*/
9309 /* shiftR2Left2Result - shift right two bytes from left to result */
9310 /*-----------------------------------------------------------------*/
9311 static void shiftR2Left2Result (operand *left, int offl,
9312 operand *result, int offr,
9313 int shCount, int sign)
9315 int same = pic16_sameRegs(AOP(result), AOP(left));
9317 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9319 if (same && (offl != offr)) { // shift right bytes
9322 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9323 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9325 } else { // just treat as different later on
9336 /* obtain sign from left operand */
9338 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9343 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9344 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9346 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9347 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9348 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9349 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9354 /* now get sign from already assigned result (avoid BANKSEL) */
9355 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9358 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9359 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9366 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9367 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9368 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9370 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9371 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9372 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9373 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9375 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9376 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9377 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9379 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9380 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9381 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9382 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9383 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9387 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9388 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9392 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9393 pic16_emitpcode(POC_BTFSC,
9394 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9395 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9403 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9404 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9406 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9407 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9408 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9409 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9411 pic16_emitpcode(POC_BTFSC,
9412 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9413 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9415 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9416 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9417 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9418 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9420 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9421 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9422 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9423 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9424 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9425 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9426 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9427 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9429 pic16_emitpcode(POC_BTFSC,
9430 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9431 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9433 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9434 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9441 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9442 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9443 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9444 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9447 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9449 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9454 /*-----------------------------------------------------------------*/
9455 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9456 /*-----------------------------------------------------------------*/
9457 static void shiftLLeftOrResult (operand *left, int offl,
9458 operand *result, int offr, int shCount)
9460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9462 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9463 /* shift left accumulator */
9465 /* or with result */
9466 /* back to result */
9467 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9470 /*-----------------------------------------------------------------*/
9471 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9472 /*-----------------------------------------------------------------*/
9473 static void shiftRLeftOrResult (operand *left, int offl,
9474 operand *result, int offr, int shCount)
9476 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9478 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9479 /* shift right accumulator */
9481 /* or with result */
9482 /* back to result */
9483 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9486 /*-----------------------------------------------------------------*/
9487 /* genlshOne - left shift a one byte quantity by known count */
9488 /*-----------------------------------------------------------------*/
9489 static void genlshOne (operand *result, operand *left, int shCount)
9491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9492 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9495 /*-----------------------------------------------------------------*/
9496 /* genlshTwo - left shift two bytes by known amount != 0 */
9497 /*-----------------------------------------------------------------*/
9498 static void genlshTwo (operand *result,operand *left, int shCount)
9502 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9503 size = pic16_getDataSize(result);
9505 /* if shCount >= 8 */
9511 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9513 movLeft2Result(left, LSB, result, MSB16);
9515 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9518 /* 1 <= shCount <= 7 */
9521 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9523 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9527 /*-----------------------------------------------------------------*/
9528 /* shiftLLong - shift left one long from left to result */
9529 /* offr = LSB or MSB16 */
9530 /*-----------------------------------------------------------------*/
9531 static void shiftLLong (operand *left, operand *result, int offr )
9533 int size = AOP_SIZE(result);
9534 int same = pic16_sameRegs(AOP(left),AOP(result));
9537 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9539 if (same && (offr == MSB16)) { //shift one byte
9540 for(i=size-1;i>=MSB16;i--) {
9541 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9542 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9548 if (size > LSB+offr ){
9550 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9552 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9553 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9557 if(size > MSB16+offr){
9559 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9561 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9562 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9566 if(size > MSB24+offr){
9568 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9570 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9571 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9575 if(size > MSB32+offr){
9577 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9579 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9580 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9584 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9588 /*-----------------------------------------------------------------*/
9589 /* genlshFour - shift four byte by a known amount != 0 */
9590 /*-----------------------------------------------------------------*/
9591 static void genlshFour (operand *result, operand *left, int shCount)
9595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9596 size = AOP_SIZE(result);
9598 /* if shifting more that 3 bytes */
9599 if (shCount >= 24 ) {
9602 /* lowest order of left goes to the highest
9603 order of the destination */
9604 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9606 movLeft2Result(left, LSB, result, MSB32);
9608 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9610 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9615 /* more than two bytes */
9616 else if ( shCount >= 16 ) {
9617 /* lower order two bytes goes to higher order two bytes */
9619 /* if some more remaining */
9621 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9623 movLeft2Result(left, MSB16, result, MSB32);
9624 movLeft2Result(left, LSB, result, MSB24);
9626 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9627 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9631 /* if more than 1 byte */
9632 else if ( shCount >= 8 ) {
9633 /* lower order three bytes goes to higher order three bytes */
9637 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9639 movLeft2Result(left, LSB, result, MSB16);
9641 else{ /* size = 4 */
9643 movLeft2Result(left, MSB24, result, MSB32);
9644 movLeft2Result(left, MSB16, result, MSB24);
9645 movLeft2Result(left, LSB, result, MSB16);
9646 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9648 else if(shCount == 1)
9649 shiftLLong(left, result, MSB16);
9651 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9652 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9653 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9654 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9659 /* 1 <= shCount <= 7 */
9660 else if(shCount <= 3)
9662 shiftLLong(left, result, LSB);
9663 while(--shCount >= 1)
9664 shiftLLong(result, result, LSB);
9666 /* 3 <= shCount <= 7, optimize */
9668 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9669 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9670 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9674 /*-----------------------------------------------------------------*/
9675 /* genLeftShiftLiteral - left shifting by known count */
9676 /*-----------------------------------------------------------------*/
9677 void pic16_genLeftShiftLiteral (operand *left,
9682 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9686 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9687 pic16_freeAsmop(right,NULL,ic,TRUE);
9689 pic16_aopOp(left,ic,FALSE);
9690 pic16_aopOp(result,ic,TRUE);
9692 size = getSize(operandType(result));
9695 pic16_emitcode("; shift left ","result %d, left %d",size,
9699 /* I suppose that the left size >= result size */
9702 movLeft2Result(left, size, result, size);
9706 else if(shCount >= (size * 8))
9708 pic16_aopPut(AOP(result),zero,size);
9712 genlshOne (result,left,shCount);
9717 genlshTwo (result,left,shCount);
9721 genlshFour (result,left,shCount);
9725 pic16_freeAsmop(left,NULL,ic,TRUE);
9726 pic16_freeAsmop(result,NULL,ic,TRUE);
9729 /*-----------------------------------------------------------------*
9730 * genMultiAsm - repeat assembly instruction for size of register.
9731 * if endian == 1, then the high byte (i.e base address + size of
9732 * register) is used first else the low byte is used first;
9733 *-----------------------------------------------------------------*/
9734 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9752 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9758 #if !(USE_GENERIC_SIGNED_SHIFT)
9759 /*-----------------------------------------------------------------*/
9760 /* genLeftShift - generates code for left shifting */
9761 /*-----------------------------------------------------------------*/
9762 static void genLeftShift (iCode *ic)
9764 operand *left,*right, *result;
9767 symbol *tlbl , *tlbl1;
9770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9772 right = IC_RIGHT(ic);
9774 result = IC_RESULT(ic);
9776 pic16_aopOp(right,ic,FALSE);
9778 /* if the shift count is known then do it
9779 as efficiently as possible */
9780 if (AOP_TYPE(right) == AOP_LIT) {
9781 pic16_genLeftShiftLiteral (left,right,result,ic);
9785 /* shift count is unknown then we have to form
9786 * a loop. Get the loop count in WREG : Note: we take
9787 * only the lower order byte since shifting
9788 * more than 32 bits make no sense anyway, ( the
9789 * largest size of an object can be only 32 bits ) */
9791 pic16_aopOp(left,ic,FALSE);
9792 pic16_aopOp(result,ic,FALSE);
9794 /* now move the left to the result if they are not the
9795 * same, and if size > 1,
9796 * and if right is not same to result (!!!) -- VR */
9797 if (!pic16_sameRegs(AOP(left),AOP(result))
9798 && (AOP_SIZE(result) > 1)) {
9800 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9802 size = AOP_SIZE(result);
9807 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9808 if (*l == '@' && (IS_AOP_PREG(result))) {
9810 pic16_emitcode("mov","a,%s",l);
9811 pic16_aopPut(AOP(result),"a",offset);
9815 /* we don't know if left is a literal or a register, take care -- VR */
9816 pic16_mov2f(AOP(result), AOP(left), offset);
9822 size = AOP_SIZE(result);
9824 /* if it is only one byte then */
9826 if(optimized_for_speed) {
9827 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9828 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9829 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9830 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9831 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9832 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9833 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9834 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9836 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9837 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9838 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9843 tlbl = newiTempLabel(NULL);
9846 /* this is already done, why change it? */
9847 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9848 pic16_mov2f(AOP(result), AOP(left), 0);
9852 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9853 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9854 pic16_emitpLabel(tlbl->key);
9855 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9856 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9858 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9863 if (pic16_sameRegs(AOP(left),AOP(result))) {
9865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9867 tlbl = newiTempLabel(NULL);
9868 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9869 genMultiAsm(POC_RRCF, result, size,1);
9870 pic16_emitpLabel(tlbl->key);
9871 genMultiAsm(POC_RLCF, result, size,0);
9872 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9874 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9878 //tlbl = newiTempLabel(NULL);
9880 //tlbl1 = newiTempLabel(NULL);
9882 //reAdjustPreg(AOP(result));
9884 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9885 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9886 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9888 //pic16_emitcode("add","a,acc");
9889 //pic16_aopPut(AOP(result),"a",offset++);
9891 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9893 // pic16_emitcode("rlc","a");
9894 // pic16_aopPut(AOP(result),"a",offset++);
9896 //reAdjustPreg(AOP(result));
9898 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9899 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9902 tlbl = newiTempLabel(NULL);
9903 tlbl1= newiTempLabel(NULL);
9905 size = AOP_SIZE(result);
9908 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9910 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9912 /* offset should be 0, 1 or 3 */
9914 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9916 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9918 pic16_emitpcode(POC_MOVWF, pctemp);
9921 pic16_emitpLabel(tlbl->key);
9924 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9926 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9928 pic16_emitpcode(POC_DECFSZ, pctemp);
9929 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9930 pic16_emitpLabel(tlbl1->key);
9932 pic16_popReleaseTempReg(pctemp,1);
9936 pic16_freeAsmop (right,NULL,ic,TRUE);
9937 pic16_freeAsmop(left,NULL,ic,TRUE);
9938 pic16_freeAsmop(result,NULL,ic,TRUE);
9944 #error old code (left here for reference)
9945 /*-----------------------------------------------------------------*/
9946 /* genLeftShift - generates code for left shifting */
9947 /*-----------------------------------------------------------------*/
9948 static void genLeftShift (iCode *ic)
9950 operand *left,*right, *result;
9953 symbol *tlbl , *tlbl1;
9956 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9958 right = IC_RIGHT(ic);
9960 result = IC_RESULT(ic);
9962 pic16_aopOp(right,ic,FALSE);
9964 /* if the shift count is known then do it
9965 as efficiently as possible */
9966 if (AOP_TYPE(right) == AOP_LIT) {
9967 pic16_genLeftShiftLiteral (left,right,result,ic);
9971 /* shift count is unknown then we have to form
9972 a loop get the loop count in B : Note: we take
9973 only the lower order byte since shifting
9974 more that 32 bits make no sense anyway, ( the
9975 largest size of an object can be only 32 bits ) */
9978 pic16_aopOp(left,ic,FALSE);
9979 pic16_aopOp(result,ic,FALSE);
9981 /* now move the left to the result if they are not the
9983 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9984 AOP_SIZE(result) > 1) {
9986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9988 size = AOP_SIZE(result);
9991 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9992 if (*l == '@' && (IS_AOP_PREG(result))) {
9994 pic16_emitcode("mov","a,%s",l);
9995 pic16_aopPut(AOP(result),"a",offset);
9998 /* we don't know if left is a literal or a register, take care -- VR */
9999 pic16_mov2f(AOP(result), AOP(left), offset);
10005 size = AOP_SIZE(result);
10007 /* if it is only one byte then */
10009 if(optimized_for_speed) {
10010 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10011 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10012 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10013 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10015 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10016 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10017 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10019 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10020 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10021 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10026 tlbl = newiTempLabel(NULL);
10027 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10028 pic16_mov2f(AOP(result), AOP(left), 0);
10030 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10031 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10034 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10035 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10036 pic16_emitpLabel(tlbl->key);
10037 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10038 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10040 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10045 if (pic16_sameRegs(AOP(left),AOP(result))) {
10047 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10049 tlbl = newiTempLabel(NULL);
10050 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10051 genMultiAsm(POC_RRCF, result, size,1);
10052 pic16_emitpLabel(tlbl->key);
10053 genMultiAsm(POC_RLCF, result, size,0);
10054 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10056 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10060 //tlbl = newiTempLabel(NULL);
10062 //tlbl1 = newiTempLabel(NULL);
10064 //reAdjustPreg(AOP(result));
10066 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10067 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10068 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10070 //pic16_emitcode("add","a,acc");
10071 //pic16_aopPut(AOP(result),"a",offset++);
10073 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10075 // pic16_emitcode("rlc","a");
10076 // pic16_aopPut(AOP(result),"a",offset++);
10078 //reAdjustPreg(AOP(result));
10080 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10081 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10084 tlbl = newiTempLabel(NULL);
10085 tlbl1= newiTempLabel(NULL);
10087 size = AOP_SIZE(result);
10090 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10092 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10094 /* offset should be 0, 1 or 3 */
10096 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10098 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10100 pic16_emitpcode(POC_MOVWF, pctemp);
10103 pic16_emitpLabel(tlbl->key);
10106 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10108 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10110 pic16_emitpcode(POC_DECFSZ, pctemp);
10111 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10112 pic16_emitpLabel(tlbl1->key);
10114 pic16_popReleaseTempReg(pctemp,1);
10118 pic16_freeAsmop (right,NULL,ic,TRUE);
10119 pic16_freeAsmop(left,NULL,ic,TRUE);
10120 pic16_freeAsmop(result,NULL,ic,TRUE);
10124 /*-----------------------------------------------------------------*/
10125 /* genrshOne - right shift a one byte quantity by known count */
10126 /*-----------------------------------------------------------------*/
10127 static void genrshOne (operand *result, operand *left,
10128 int shCount, int sign)
10130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10131 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10134 /*-----------------------------------------------------------------*/
10135 /* genrshTwo - right shift two bytes by known amount != 0 */
10136 /*-----------------------------------------------------------------*/
10137 static void genrshTwo (operand *result,operand *left,
10138 int shCount, int sign)
10140 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10141 /* if shCount >= 8 */
10142 if (shCount >= 8) {
10145 shiftR1Left2Result(left, MSB16, result, LSB,
10148 movLeft2Result(left, MSB16, result, LSB);
10150 pic16_addSign (result, 1, sign);
10153 /* 1 <= shCount <= 7 */
10155 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10158 /*-----------------------------------------------------------------*/
10159 /* shiftRLong - shift right one long from left to result */
10160 /* offl = LSB or MSB16 */
10161 /*-----------------------------------------------------------------*/
10162 static void shiftRLong (operand *left, int offl,
10163 operand *result, int sign)
10165 int size = AOP_SIZE(result);
10166 int same = pic16_sameRegs(AOP(left),AOP(result));
10168 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10170 if (same && (offl == MSB16)) { //shift one byte right
10171 for(i=MSB16;i<size;i++) {
10172 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10178 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10184 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10186 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10190 if(offl == MSB16) {
10191 /* add sign of "a" */
10192 pic16_addSign(result, MSB32, sign);
10196 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10198 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10199 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10203 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10205 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10206 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10210 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10213 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10214 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10219 /*-----------------------------------------------------------------*/
10220 /* genrshFour - shift four byte by a known amount != 0 */
10221 /*-----------------------------------------------------------------*/
10222 static void genrshFour (operand *result, operand *left,
10223 int shCount, int sign)
10225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10226 /* if shifting more that 3 bytes */
10227 if(shCount >= 24 ) {
10230 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10232 movLeft2Result(left, MSB32, result, LSB);
10234 pic16_addSign(result, MSB16, sign);
10236 else if(shCount >= 16){
10239 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10241 movLeft2Result(left, MSB24, result, LSB);
10242 movLeft2Result(left, MSB32, result, MSB16);
10244 pic16_addSign(result, MSB24, sign);
10246 else if(shCount >= 8){
10249 shiftRLong(left, MSB16, result, sign);
10250 else if(shCount == 0){
10251 movLeft2Result(left, MSB16, result, LSB);
10252 movLeft2Result(left, MSB24, result, MSB16);
10253 movLeft2Result(left, MSB32, result, MSB24);
10254 pic16_addSign(result, MSB32, sign);
10256 else{ //shcount >= 2
10257 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10258 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10259 /* the last shift is signed */
10260 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10261 pic16_addSign(result, MSB32, sign);
10264 else{ /* 1 <= shCount <= 7 */
10266 shiftRLong(left, LSB, result, sign);
10268 shiftRLong(result, LSB, result, sign);
10271 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10272 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10273 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10278 /*-----------------------------------------------------------------*/
10279 /* genRightShiftLiteral - right shifting by known count */
10280 /*-----------------------------------------------------------------*/
10281 static void genRightShiftLiteral (operand *left,
10287 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10288 int lsize,res_size;
10290 pic16_freeAsmop(right,NULL,ic,TRUE);
10292 pic16_aopOp(left,ic,FALSE);
10293 pic16_aopOp(result,ic,TRUE);
10295 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10298 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10302 lsize = pic16_getDataSize(left);
10303 res_size = pic16_getDataSize(result);
10304 /* test the LEFT size !!! */
10306 /* I suppose that the left size >= result size */
10308 assert (res_size <= lsize);
10309 while (res_size--) {
10310 pic16_mov2f (AOP(result), AOP(left), res_size);
10314 else if(shCount >= (lsize * 8)){
10316 if(res_size == 1) {
10317 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10319 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10320 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10325 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10326 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10327 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10329 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10334 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10339 switch (res_size) {
10341 genrshOne (result,left,shCount,sign);
10345 genrshTwo (result,left,shCount,sign);
10349 genrshFour (result,left,shCount,sign);
10357 pic16_freeAsmop(left,NULL,ic,TRUE);
10358 pic16_freeAsmop(result,NULL,ic,TRUE);
10361 #if !(USE_GENERIC_SIGNED_SHIFT)
10362 /*-----------------------------------------------------------------*/
10363 /* genSignedRightShift - right shift of signed number */
10364 /*-----------------------------------------------------------------*/
10365 static void genSignedRightShift (iCode *ic)
10367 operand *right, *left, *result;
10370 symbol *tlbl, *tlbl1 ;
10373 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10375 /* we do it the hard way put the shift count in b
10376 and loop thru preserving the sign */
10377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10379 right = IC_RIGHT(ic);
10380 left = IC_LEFT(ic);
10381 result = IC_RESULT(ic);
10383 pic16_aopOp(right,ic,FALSE);
10384 pic16_aopOp(left,ic,FALSE);
10385 pic16_aopOp(result,ic,FALSE);
10388 if ( AOP_TYPE(right) == AOP_LIT) {
10389 genRightShiftLiteral (left,right,result,ic,1);
10392 /* shift count is unknown then we have to form
10393 a loop get the loop count in B : Note: we take
10394 only the lower order byte since shifting
10395 more that 32 bits make no sense anyway, ( the
10396 largest size of an object can be only 32 bits ) */
10398 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10399 //pic16_emitcode("inc","b");
10400 //pic16_freeAsmop (right,NULL,ic,TRUE);
10401 //pic16_aopOp(left,ic,FALSE);
10402 //pic16_aopOp(result,ic,FALSE);
10404 /* now move the left to the result if they are not the
10406 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10407 AOP_SIZE(result) > 1) {
10409 size = AOP_SIZE(result);
10413 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10414 if (*l == '@' && IS_AOP_PREG(result)) {
10416 pic16_emitcode("mov","a,%s",l);
10417 pic16_aopPut(AOP(result),"a",offset);
10419 pic16_aopPut(AOP(result),l,offset);
10421 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10422 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10428 /* mov the highest order bit to OVR */
10429 tlbl = newiTempLabel(NULL);
10430 tlbl1= newiTempLabel(NULL);
10432 size = AOP_SIZE(result);
10435 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10439 /* offset should be 0, 1 or 3 */
10440 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10442 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10444 pic16_emitpcode(POC_MOVWF, pctemp);
10447 pic16_emitpLabel(tlbl->key);
10449 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10450 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10453 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10456 pic16_emitpcode(POC_DECFSZ, pctemp);
10457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10458 pic16_emitpLabel(tlbl1->key);
10460 pic16_popReleaseTempReg(pctemp,1);
10462 size = AOP_SIZE(result);
10464 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10465 pic16_emitcode("rlc","a");
10466 pic16_emitcode("mov","ov,c");
10467 /* if it is only one byte then */
10469 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10471 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10472 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10473 pic16_emitcode("mov","c,ov");
10474 pic16_emitcode("rrc","a");
10475 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10476 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10477 pic16_aopPut(AOP(result),"a",0);
10481 reAdjustPreg(AOP(result));
10482 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10483 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10484 pic16_emitcode("mov","c,ov");
10486 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10488 pic16_emitcode("rrc","a");
10489 pic16_aopPut(AOP(result),"a",offset--);
10491 reAdjustPreg(AOP(result));
10492 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10493 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10498 pic16_freeAsmop(left,NULL,ic,TRUE);
10499 pic16_freeAsmop(result,NULL,ic,TRUE);
10500 pic16_freeAsmop(right,NULL,ic,TRUE);
10504 #if !(USE_GENERIC_SIGNED_SHIFT)
10505 #warning This implementation of genRightShift() is incomplete!
10506 /*-----------------------------------------------------------------*/
10507 /* genRightShift - generate code for right shifting */
10508 /*-----------------------------------------------------------------*/
10509 static void genRightShift (iCode *ic)
10511 operand *right, *left, *result;
10515 symbol *tlbl, *tlbl1 ;
10517 /* if signed then we do it the hard way preserve the
10518 sign bit moving it inwards */
10519 letype = getSpec(operandType(IC_LEFT(ic)));
10520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10522 if (!SPEC_USIGN(letype)) {
10523 genSignedRightShift (ic);
10527 /* signed & unsigned types are treated the same : i.e. the
10528 signed is NOT propagated inwards : quoting from the
10529 ANSI - standard : "for E1 >> E2, is equivalent to division
10530 by 2**E2 if unsigned or if it has a non-negative value,
10531 otherwise the result is implementation defined ", MY definition
10532 is that the sign does not get propagated */
10534 right = IC_RIGHT(ic);
10535 left = IC_LEFT(ic);
10536 result = IC_RESULT(ic);
10538 pic16_aopOp(right,ic,FALSE);
10540 /* if the shift count is known then do it
10541 as efficiently as possible */
10542 if (AOP_TYPE(right) == AOP_LIT) {
10543 genRightShiftLiteral (left,right,result,ic, 0);
10547 /* shift count is unknown then we have to form
10548 a loop get the loop count in B : Note: we take
10549 only the lower order byte since shifting
10550 more that 32 bits make no sense anyway, ( the
10551 largest size of an object can be only 32 bits ) */
10553 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10554 pic16_emitcode("inc","b");
10555 pic16_aopOp(left,ic,FALSE);
10556 pic16_aopOp(result,ic,FALSE);
10558 /* now move the left to the result if they are not the
10560 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10561 AOP_SIZE(result) > 1) {
10563 size = AOP_SIZE(result);
10566 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10567 if (*l == '@' && IS_AOP_PREG(result)) {
10569 pic16_emitcode("mov","a,%s",l);
10570 pic16_aopPut(AOP(result),"a",offset);
10572 pic16_aopPut(AOP(result),l,offset);
10577 tlbl = newiTempLabel(NULL);
10578 tlbl1= newiTempLabel(NULL);
10579 size = AOP_SIZE(result);
10582 /* if it is only one byte then */
10585 tlbl = newiTempLabel(NULL);
10586 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10587 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10588 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10591 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10592 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10593 pic16_emitpLabel(tlbl->key);
10594 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10602 reAdjustPreg(AOP(result));
10603 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10604 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10607 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10609 pic16_emitcode("rrc","a");
10610 pic16_aopPut(AOP(result),"a",offset--);
10612 reAdjustPreg(AOP(result));
10614 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10615 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10618 pic16_freeAsmop(left,NULL,ic,TRUE);
10619 pic16_freeAsmop (right,NULL,ic,TRUE);
10620 pic16_freeAsmop(result,NULL,ic,TRUE);
10624 #if (USE_GENERIC_SIGNED_SHIFT)
10625 /*-----------------------------------------------------------------*/
10626 /* genGenericShift - generates code for left or right shifting */
10627 /*-----------------------------------------------------------------*/
10628 static void genGenericShift (iCode *ic, int isShiftLeft) {
10629 operand *left,*right, *result;
10631 int sign, signedCount;
10632 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10633 PIC_OPCODE pos_shift, neg_shift;
10637 right = IC_RIGHT(ic);
10638 left = IC_LEFT(ic);
10639 result = IC_RESULT(ic);
10641 pic16_aopOp(right,ic,FALSE);
10642 pic16_aopOp(left,ic,FALSE);
10643 pic16_aopOp(result,ic,TRUE);
10645 sign = !SPEC_USIGN(operandType (left));
10646 signedCount = !SPEC_USIGN(operandType (right));
10648 /* if the shift count is known then do it
10649 as efficiently as possible */
10650 if (AOP_TYPE(right) == AOP_LIT) {
10651 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10652 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10653 // we should modify right->aopu.aop_lit here!
10654 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10655 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10657 pic16_genLeftShiftLiteral (left,right,result,ic);
10659 genRightShiftLiteral (left,right,result,ic, sign);
10662 } // if (right is literal)
10664 /* shift count is unknown then we have to form a loop.
10665 * Note: we take only the lower order byte since shifting
10666 * more than 32 bits make no sense anyway, ( the
10667 * largest size of an object can be only 32 bits )
10668 * Note: we perform arithmetic shifts if the left operand is
10669 * signed and we do an (effective) right shift, i. e. we
10670 * shift in the sign bit from the left. */
10672 label_complete = newiTempLabel ( NULL );
10673 label_loop_pos = newiTempLabel ( NULL );
10674 label_loop_neg = NULL;
10675 label_negative = NULL;
10676 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10677 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10680 // additional labels needed
10681 label_loop_neg = newiTempLabel ( NULL );
10682 label_negative = newiTempLabel ( NULL );
10685 // copy source to result -- this will effectively truncate the left operand to the size of result!
10686 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10687 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10688 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10689 pic16_mov2f (AOP(result),AOP(left), offset);
10692 // if result is longer than left, fill with zeros (or sign)
10693 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10694 if (sign && AOP_SIZE(left) > 0) {
10695 // shift signed operand -- fill with sign
10696 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10697 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10698 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10699 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10700 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10703 // shift unsigned operand -- fill result with zeros
10704 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10705 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10708 } // if (size mismatch)
10710 pic16_mov2w (AOP(right), 0);
10711 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10712 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10715 // perform a shift by one (shift count is positive)
10716 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10717 // 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])
10718 pic16_emitpLabel (label_loop_pos->key);
10720 if (sign && (pos_shift == POC_RRCF)) {
10721 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10724 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10725 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10726 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10728 // perform a shift by one (shift count is positive)
10729 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10730 // 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])
10731 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10732 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10734 pic16_emitpLabel (label_loop_pos->key);
10735 if (sign && (pos_shift == POC_RRCF)) {
10736 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10739 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10740 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10741 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10742 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10746 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10748 pic16_emitpLabel (label_negative->key);
10749 // perform a shift by -1 (shift count is negative)
10750 // 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)
10752 pic16_emitpLabel (label_loop_neg->key);
10753 if (sign && (neg_shift == POC_RRCF)) {
10754 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10757 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10758 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10759 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10760 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10761 } // if (signedCount)
10763 pic16_emitpLabel (label_complete->key);
10766 pic16_freeAsmop (right,NULL,ic,TRUE);
10767 pic16_freeAsmop(left,NULL,ic,TRUE);
10768 pic16_freeAsmop(result,NULL,ic,TRUE);
10771 static void genLeftShift (iCode *ic) {
10772 genGenericShift (ic, 1);
10775 static void genRightShift (iCode *ic) {
10776 genGenericShift (ic, 0);
10781 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10782 void pic16_loadFSR0(operand *op, int lit)
10784 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10785 if (AOP_TYPE(op) == AOP_LIT) {
10786 /* handle 12 bit integers correctly */
10787 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10788 if ((val & 0x0fff) != val) {
10789 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10790 val, (val & 0x0fff) );
10793 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10795 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10798 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10799 // set up FSR0 with address of result
10800 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10801 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10805 /*----------------------------------------------------------------*/
10806 /* pic16_derefPtr - move one byte from the location ptr points to */
10807 /* to WREG (doWrite == 0) or one byte from WREG */
10808 /* to the location ptr points to (doWrite != 0) */
10809 /*----------------------------------------------------------------*/
10810 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10812 if (!IS_PTR(operandType(ptr)))
10814 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10815 else pic16_mov2w (AOP(ptr), 0);
10819 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10820 /* We might determine pointer type right here: */
10821 p_type = DCL_TYPE(operandType(ptr));
10826 if (!fsr0_setup || !*fsr0_setup)
10828 pic16_loadFSR0( ptr, 0 );
10829 if (fsr0_setup) *fsr0_setup = 1;
10832 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10834 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10838 if (AOP(ptr)->aopu.aop_reg[2]) {
10839 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10840 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10841 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10842 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10843 pic16_mov2w(AOP(ptr), 2);
10844 pic16_callGenericPointerRW(doWrite, 1);
10846 // data pointer (just 2 byte given)
10847 if (!fsr0_setup || !*fsr0_setup)
10849 pic16_loadFSR0( ptr, 0 );
10850 if (fsr0_setup) *fsr0_setup = 1;
10853 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10855 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10860 assert (0 && "invalid pointer type specified");
10865 /*-----------------------------------------------------------------*/
10866 /* genUnpackBits - generates code for unpacking bits */
10867 /*-----------------------------------------------------------------*/
10868 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10871 sym_link *etype, *letype;
10872 int blen=0, bstr=0;
10877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10878 etype = getSpec(operandType(result));
10879 letype = getSpec(operandType(left));
10881 // if(IS_BITFIELD(etype)) {
10882 blen = SPEC_BLEN(etype);
10883 bstr = SPEC_BSTR(etype);
10886 lbstr = SPEC_BSTR( letype );
10888 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10889 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10892 if((blen == 1) && (bstr < 8)
10893 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10894 /* it is a single bit, so use the appropriate bit instructions */
10895 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10897 same = pic16_sameRegs(AOP(left),AOP(result));
10898 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10899 pic16_emitpcode(POC_CLRF, op);
10901 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10902 /* workaround to reduce the extra lfsr instruction */
10903 pic16_emitpcode(POC_BTFSC,
10904 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10906 assert (PIC_IS_DATA_PTR (operandType(left)));
10907 pic16_loadFSR0 (left, 0);
10908 pic16_emitpcode(POC_BTFSC,
10909 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10912 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10913 /* unsigned bitfields result in either 0 or 1 */
10914 pic16_emitpcode(POC_INCF, op);
10916 /* signed bitfields result in either 0 or -1 */
10917 pic16_emitpcode(POC_DECF, op);
10920 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10923 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10929 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10930 // access symbol directly
10931 pic16_mov2w (AOP(left), 0);
10933 pic16_derefPtr (left, ptype, 0, NULL);
10936 /* if we have bitdisplacement then it fits */
10937 /* into this byte completely or if length is */
10938 /* less than a byte */
10939 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10941 /* shift right acc */
10944 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10945 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10947 /* VR -- normally I would use the following, but since we use the hack,
10948 * to avoid the masking from AccRsh, why not mask it right now? */
10951 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10954 /* extend signed bitfields to 8 bits */
10955 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10957 assert (blen + bstr > 0);
10958 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10959 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10964 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10968 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10969 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10970 exit(EXIT_FAILURE);
10976 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10978 int size, offset = 0, leoffset=0 ;
10980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10981 pic16_aopOp(result, ic, TRUE);
10985 size = AOP_SIZE(result);
10986 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10990 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10991 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10992 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10997 if(AOP(left)->aopu.pcop->type == PO_DIR)
10998 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11000 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11003 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11005 // pic16_DumpOp("(result)",result);
11006 if(is_LitAOp(AOP(result))) {
11007 pic16_mov2w(AOP(left), offset); // patch 8
11008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11010 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11011 pic16_popGet(AOP(left), offset), //patch 8
11012 pic16_popGet(AOP(result), offset)));
11020 pic16_freeAsmop(result,NULL,ic,TRUE);
11025 /*-----------------------------------------------------------------*/
11026 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11027 /*-----------------------------------------------------------------*/
11028 static void genNearPointerGet (operand *left,
11032 // asmop *aop = NULL;
11033 //regs *preg = NULL ;
11034 sym_link *rtype, *retype;
11035 sym_link *ltype, *letype;
11039 rtype = operandType(result);
11040 retype= getSpec(rtype);
11041 ltype = operandType(left);
11042 letype= getSpec(ltype);
11044 pic16_aopOp(left,ic,FALSE);
11046 // pic16_DumpOp("(left)",left);
11047 // pic16_DumpOp("(result)",result);
11049 /* if left is rematerialisable and
11050 * result is not bit variable type and
11051 * the left is pointer to data space i.e
11052 * lower 128 bytes of space */
11054 if (AOP_TYPE(left) == AOP_PCODE
11055 && !IS_BITFIELD(retype)
11056 && DCL_TYPE(ltype) == POINTER) {
11058 genDataPointerGet (left,result,ic);
11059 pic16_freeAsmop(left, NULL, ic, TRUE);
11063 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11064 pic16_aopOp (result,ic,TRUE);
11066 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11069 if(IS_BITFIELD( retype )
11070 && (SPEC_BLEN(operandType(result))==1)
11074 int bitstrt, bytestrt;
11076 /* if this is bitfield of size 1, see if we are checking the value
11077 * of a single bit in an if-statement,
11078 * if yes, then don't generate usual code, but execute the
11079 * genIfx directly -- VR */
11083 /* CHECK: if next iCode is IFX
11084 * and current result operand is nextic's conditional operand
11085 * and current result operand live ranges ends at nextic's key number
11087 if((nextic->op == IFX)
11088 && (result == IC_COND(nextic))
11089 && (OP_LIVETO(result) == nextic->seq)
11090 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11092 /* everything is ok then */
11093 /* find a way to optimize the genIfx iCode */
11095 bytestrt = SPEC_BSTR(operandType(result))/8;
11096 bitstrt = SPEC_BSTR(operandType(result))%8;
11098 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11100 genIfxpCOpJump(nextic, jop);
11102 pic16_freeAsmop(left, NULL, ic, TRUE);
11103 pic16_freeAsmop(result, NULL, ic, TRUE);
11109 /* if bitfield then unpack the bits */
11110 if (IS_BITFIELD(letype))
11111 genUnpackBits (result, left, NULL, POINTER);
11113 /* we have can just get the values */
11114 int size = AOP_SIZE(result);
11117 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11119 pic16_loadFSR0( left, 0 );
11123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11124 pic16_popGet(AOP(result), offset++)));
11126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11127 pic16_popGet(AOP(result), offset++)));
11133 /* now some housekeeping stuff */
11135 /* we had to allocate for this iCode */
11136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11137 pic16_freeAsmop(NULL,aop,ic,TRUE);
11139 /* we did not allocate which means left
11140 * already in a pointer register, then
11141 * if size > 0 && this could be used again
11142 * we have to point it back to where it
11144 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11145 if (AOP_SIZE(result) > 1
11146 && !OP_SYMBOL(left)->remat
11147 && ( OP_SYMBOL(left)->liveTo > ic->seq
11149 // int size = AOP_SIZE(result) - 1;
11151 // pic16_emitcode("dec","%s",rname);
11157 pic16_freeAsmop(left,NULL,ic,TRUE);
11158 pic16_freeAsmop(result,NULL,ic,TRUE);
11161 /*-----------------------------------------------------------------*/
11162 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11163 /*-----------------------------------------------------------------*/
11164 static void genPagedPointerGet (operand *left,
11169 regs *preg = NULL ;
11171 sym_link *rtype, *retype;
11173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11175 rtype = operandType(result);
11176 retype= getSpec(rtype);
11178 pic16_aopOp(left,ic,FALSE);
11180 /* if the value is already in a pointer register
11181 then don't need anything more */
11182 if (!AOP_INPREG(AOP(left))) {
11183 /* otherwise get a free pointer register */
11185 preg = getFreePtr(ic,&aop,FALSE);
11186 pic16_emitcode("mov","%s,%s",
11188 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11189 rname = preg->name ;
11191 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11193 pic16_freeAsmop(left,NULL,ic,TRUE);
11194 pic16_aopOp (result,ic,TRUE);
11196 /* if bitfield then unpack the bits */
11197 if (IS_BITFIELD(retype))
11198 genUnpackBits (result,left,rname,PPOINTER);
11200 /* we have can just get the values */
11201 int size = AOP_SIZE(result);
11206 pic16_emitcode("movx","a,@%s",rname);
11207 pic16_aopPut(AOP(result),"a",offset);
11212 pic16_emitcode("inc","%s",rname);
11216 /* now some housekeeping stuff */
11218 /* we had to allocate for this iCode */
11219 pic16_freeAsmop(NULL,aop,ic,TRUE);
11221 /* we did not allocate which means left
11222 already in a pointer register, then
11223 if size > 0 && this could be used again
11224 we have to point it back to where it
11226 if (AOP_SIZE(result) > 1 &&
11227 !OP_SYMBOL(left)->remat &&
11228 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11230 int size = AOP_SIZE(result) - 1;
11232 pic16_emitcode("dec","%s",rname);
11237 pic16_freeAsmop(result,NULL,ic,TRUE);
11243 /* This code is not adjusted to PIC16 and fails utterly.
11244 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11246 /*-----------------------------------------------------------------*/
11247 /* genFarPointerGet - gget value from far space */
11248 /*-----------------------------------------------------------------*/
11249 static void genFarPointerGet (operand *left,
11250 operand *result, iCode *ic)
11253 sym_link *retype = getSpec(operandType(result));
11255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11257 pic16_aopOp(left,ic,FALSE);
11259 /* if the operand is already in dptr
11260 then we do nothing else we move the value to dptr */
11261 if (AOP_TYPE(left) != AOP_STR) {
11262 /* if this is remateriazable */
11263 if (AOP_TYPE(left) == AOP_IMMD)
11264 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11265 else { /* we need to get it byte by byte */
11266 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11267 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11268 if (options.model == MODEL_FLAT24)
11270 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11274 /* so dptr know contains the address */
11275 pic16_freeAsmop(left,NULL,ic,TRUE);
11276 pic16_aopOp(result,ic,TRUE);
11278 /* if bit then unpack */
11279 if (IS_BITFIELD(retype))
11280 genUnpackBits(result,left,"dptr",FPOINTER);
11282 size = AOP_SIZE(result);
11286 pic16_emitcode("movx","a,@dptr");
11287 pic16_aopPut(AOP(result),"a",offset++);
11289 pic16_emitcode("inc","dptr");
11293 pic16_freeAsmop(result,NULL,ic,TRUE);
11298 /*-----------------------------------------------------------------*/
11299 /* genCodePointerGet - get value from code space */
11300 /*-----------------------------------------------------------------*/
11301 static void genCodePointerGet (operand *left,
11302 operand *result, iCode *ic)
11305 sym_link *retype = getSpec(operandType(result));
11307 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11309 pic16_aopOp(left,ic,FALSE);
11311 /* if the operand is already in dptr
11312 then we do nothing else we move the value to dptr */
11313 if (AOP_TYPE(left) != AOP_STR) {
11314 /* if this is remateriazable */
11315 if (AOP_TYPE(left) == AOP_IMMD)
11316 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11317 else { /* we need to get it byte by byte */
11318 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11319 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11320 if (options.model == MODEL_FLAT24)
11322 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11326 /* so dptr know contains the address */
11327 pic16_freeAsmop(left,NULL,ic,TRUE);
11328 pic16_aopOp(result,ic,FALSE);
11330 /* if bit then unpack */
11331 if (IS_BITFIELD(retype))
11332 genUnpackBits(result,left,"dptr",CPOINTER);
11334 size = AOP_SIZE(result);
11338 pic16_emitcode("clr","a");
11339 pic16_emitcode("movc","a,@a+dptr");
11340 pic16_aopPut(AOP(result),"a",offset++);
11342 pic16_emitcode("inc","dptr");
11346 pic16_freeAsmop(result,NULL,ic,TRUE);
11351 /*-----------------------------------------------------------------*/
11352 /* genGenPointerGet - gget value from generic pointer space */
11353 /*-----------------------------------------------------------------*/
11354 static void genGenPointerGet (operand *left,
11355 operand *result, iCode *ic)
11357 int size, offset, lit;
11358 sym_link *retype = getSpec(operandType(result));
11360 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11361 pic16_aopOp(left,ic,FALSE);
11362 pic16_aopOp(result,ic,FALSE);
11363 size = AOP_SIZE(result);
11365 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11367 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11369 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11370 // load FSR0 from immediate
11371 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11373 // pic16_loadFSR0( left );
11378 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11380 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11387 else { /* we need to get it byte by byte */
11388 // set up FSR0 with address from left
11389 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11390 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11396 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11398 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11405 /* if bit then unpack */
11406 if (IS_BITFIELD(retype))
11407 genUnpackBits(result,left,"BAD",GPOINTER);
11410 pic16_freeAsmop(left,NULL,ic,TRUE);
11411 pic16_freeAsmop(result,NULL,ic,TRUE);
11417 /*-----------------------------------------------------------------*/
11418 /* genGenPointerGet - gget value from generic pointer space */
11419 /*-----------------------------------------------------------------*/
11420 static void genGenPointerGet (operand *left,
11421 operand *result, iCode *ic)
11423 int size, offset, lit;
11424 sym_link *letype = getSpec(operandType(left));
11426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11427 pic16_aopOp(left,ic,FALSE);
11428 pic16_aopOp(result,ic,TRUE);
11429 size = AOP_SIZE(result);
11431 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11433 /* if bit then unpack */
11434 if (IS_BITFIELD(letype)) {
11435 genUnpackBits(result,left,"BAD",GPOINTER);
11439 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11441 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11442 // load FSR0 from immediate
11443 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11445 werror(W_POSSBUG2, __FILE__, __LINE__);
11450 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11452 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11459 } else { /* we need to get it byte by byte */
11461 /* set up WREG:PRODL:FSR0L with address from left */
11462 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11463 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11464 pic16_mov2w(AOP(left), 2);
11465 pic16_callGenericPointerRW(0, size);
11467 assignResultValue(result, size, 1);
11473 pic16_freeAsmop(left,NULL,ic,TRUE);
11474 pic16_freeAsmop(result,NULL,ic,TRUE);
11477 /*-----------------------------------------------------------------*/
11478 /* genConstPointerGet - get value from const generic pointer space */
11479 /*-----------------------------------------------------------------*/
11480 static void genConstPointerGet (operand *left,
11481 operand *result, iCode *ic)
11483 //sym_link *retype = getSpec(operandType(result));
11484 // symbol *albl = newiTempLabel(NULL); // patch 15
11485 // symbol *blbl = newiTempLabel(NULL); //
11486 // PIC_OPCODE poc; // patch 15
11490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11491 pic16_aopOp(left,ic,FALSE);
11492 pic16_aopOp(result,ic,TRUE);
11493 size = AOP_SIZE(result);
11495 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11497 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11499 // set up table pointer
11500 if( (AOP_TYPE(left) == AOP_PCODE)
11501 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11502 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11504 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11505 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11506 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11507 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11508 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11509 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11511 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11512 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11513 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11517 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11518 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11522 pic16_freeAsmop(left,NULL,ic,TRUE);
11523 pic16_freeAsmop(result,NULL,ic,TRUE);
11527 /*-----------------------------------------------------------------*/
11528 /* genPointerGet - generate code for pointer get */
11529 /*-----------------------------------------------------------------*/
11530 static void genPointerGet (iCode *ic)
11532 operand *left, *result ;
11533 sym_link *type, *etype;
11538 left = IC_LEFT(ic);
11539 result = IC_RESULT(ic) ;
11541 /* depending on the type of pointer we need to
11542 move it to the correct pointer register */
11543 type = operandType(left);
11544 etype = getSpec(type);
11547 if (IS_PTR_CONST(type))
11549 if (IS_CODEPTR(type))
11551 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11553 /* if left is of type of pointer then it is simple */
11554 if (IS_PTR(type) && !IS_FUNC(type->next))
11555 p_type = DCL_TYPE(type);
11557 /* we have to go by the storage class */
11558 p_type = PTR_TYPE(SPEC_OCLS(etype));
11560 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11562 if (SPEC_OCLS(etype)->codesp ) {
11563 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11564 //p_type = CPOINTER ;
11566 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11567 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11568 /*p_type = FPOINTER ;*/
11570 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11571 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11572 /* p_type = PPOINTER; */
11574 if (SPEC_OCLS(etype) == idata ) {
11575 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11576 /* p_type = IPOINTER; */
11578 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11579 /* p_type = POINTER ; */
11583 /* now that we have the pointer type we assign
11584 the pointer values */
11589 genNearPointerGet (left,result,ic);
11593 genPagedPointerGet(left,result,ic);
11597 /* PICs do not support FAR pointers... */
11598 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11600 genFarPointerGet (left,result,ic);
11605 genConstPointerGet (left,result,ic);
11606 //pic16_emitcodePointerGet (left,result,ic);
11611 if (IS_PTR_CONST(type))
11612 genConstPointerGet (left,result,ic);
11615 genGenPointerGet (left,result,ic);
11619 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11620 "genPointerGet: illegal pointer type");
11625 /*-----------------------------------------------------------------*/
11626 /* genPackBits - generates code for packed bit storage */
11627 /*-----------------------------------------------------------------*/
11628 static void genPackBits (sym_link *etype , operand *result,
11630 char *rname, int p_type)
11636 int shifted_and_masked = 0;
11637 unsigned long lit = (unsigned long)-1;
11640 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11641 blen = SPEC_BLEN(etype);
11642 bstr = SPEC_BSTR(etype);
11644 retype = getSpec(operandType(right));
11646 if(AOP_TYPE(right) == AOP_LIT) {
11647 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11649 if((blen == 1) && (bstr < 8)) {
11650 /* it is a single bit, so use the appropriate bit instructions */
11652 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11654 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11655 /* workaround to reduce the extra lfsr instruction */
11657 pic16_emitpcode(POC_BSF,
11658 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11660 pic16_emitpcode(POC_BCF,
11661 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11664 if (PIC_IS_DATA_PTR(operandType(result))) {
11665 pic16_loadFSR0(result, 0);
11666 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11667 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11669 /* get old value */
11670 pic16_derefPtr (result, p_type, 0, NULL);
11671 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11672 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11673 /* write back new value */
11674 pic16_derefPtr (result, p_type, 1, NULL);
11680 /* IORLW below is more efficient */
11681 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11682 lit = (lit & ((1UL << blen) - 1)) << bstr;
11683 shifted_and_masked = 1;
11686 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11687 && IS_BITFIELD(retype)
11688 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11692 rblen = SPEC_BLEN( retype );
11693 rbstr = SPEC_BSTR( retype );
11695 if(IS_BITFIELD(etype)) {
11696 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11697 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11699 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11702 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11704 if(IS_BITFIELD(etype)) {
11705 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11707 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11710 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11714 /* move right to W */
11715 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11718 /* if the bit length is less than or */
11719 /* it exactly fits a byte then */
11720 if((shCnt=SPEC_BSTR(etype))
11721 || SPEC_BLEN(etype) <= 8 ) {
11722 int fsr0_setup = 0;
11724 if (blen != 8 || (bstr % 8) != 0) {
11725 // we need to combine the value with the old value
11726 if(!shifted_and_masked)
11728 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11730 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11731 SPEC_BSTR(etype), SPEC_BLEN(etype));
11733 /* shift left acc, do NOT mask the result again */
11736 /* using PRODH as a temporary register here */
11737 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11740 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11741 || IS_DIRECT(result)) {
11742 /* access symbol directly */
11743 pic16_mov2w (AOP(result), 0);
11745 /* get old value */
11746 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11749 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11750 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11751 (unsigned char)(0xff >> (8-bstr))) ));
11752 if (!shifted_and_masked) {
11753 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11755 /* We have the shifted and masked (literal) right value in `lit' */
11757 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11759 } else { // if (blen == 8 && (bstr % 8) == 0)
11760 if (shifted_and_masked) {
11761 // move right (literal) to WREG (only case where right is not yet in WREG)
11762 pic16_mov2w(AOP(right), (bstr / 8));
11766 /* write new value back */
11767 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11768 || IS_DIRECT(result)) {
11769 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11771 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11780 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11781 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11782 exit(EXIT_FAILURE);
11786 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11787 rLen = SPEC_BLEN(etype)-8;
11789 /* now generate for lengths greater than one byte */
11793 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11799 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11805 pic16_emitcode("movx","@dptr,a");
11810 DEBUGpic16_emitcode(";lcall","__gptrput");
11818 pic16_mov2w(AOP(right), offset++);
11821 /* last last was not complete */
11823 /* save the byte & read byte */
11826 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11827 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11832 pic16_emitcode ("mov","b,a");
11833 pic16_emitcode("movx","a,@dptr");
11837 pic16_emitcode ("push","b");
11838 pic16_emitcode ("push","acc");
11839 pic16_emitcode ("lcall","__gptrget");
11840 pic16_emitcode ("pop","b");
11846 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11847 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11848 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11849 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11850 // pic16_emitcode ("orl","a,b");
11853 // if (p_type == GPOINTER)
11854 // pic16_emitcode("pop","b");
11859 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11860 // pic16_emitcode("mov","@%s,a",rname);
11864 pic16_emitcode("movx","@dptr,a");
11868 DEBUGpic16_emitcode(";lcall","__gptrput");
11875 // pic16_freeAsmop(right, NULL, ic, TRUE);
11878 /*-----------------------------------------------------------------*/
11879 /* genDataPointerSet - remat pointer to data space */
11880 /*-----------------------------------------------------------------*/
11881 static void genDataPointerSet(operand *right,
11885 int size, offset = 0, resoffset=0 ;
11887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11888 pic16_aopOp(right,ic,FALSE);
11890 size = AOP_SIZE(right);
11892 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11895 if ( AOP_TYPE(result) == AOP_PCODE) {
11896 fprintf(stderr,"genDataPointerSet %s, %d\n",
11897 AOP(result)->aopu.pcop->name,
11898 (AOP(result)->aopu.pcop->type == PO_DIR)?
11899 PCOR(AOP(result)->aopu.pcop)->instance:
11900 PCOI(AOP(result)->aopu.pcop)->offset);
11904 if(AOP(result)->aopu.pcop->type == PO_DIR)
11905 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11908 if (AOP_TYPE(right) == AOP_LIT) {
11909 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11910 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11912 pic16_mov2w(AOP(right), offset);
11913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11919 pic16_freeAsmop(right,NULL,ic,TRUE);
11924 /*-----------------------------------------------------------------*/
11925 /* genNearPointerSet - pic16_emitcode for near pointer put */
11926 /*-----------------------------------------------------------------*/
11927 static void genNearPointerSet (operand *right,
11933 sym_link *ptype = operandType(result);
11934 sym_link *resetype;
11936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11937 retype= getSpec(operandType(right));
11938 resetype = getSpec(operandType(result));
11940 pic16_aopOp(result,ic,FALSE);
11942 /* if the result is rematerializable &
11943 * in data space & not a bit variable */
11945 /* and result is not a bit variable */
11946 if (AOP_TYPE(result) == AOP_PCODE
11947 // && AOP_TYPE(result) == AOP_IMMD
11948 && DCL_TYPE(ptype) == POINTER
11949 && !IS_BITFIELD(retype)
11950 && !IS_BITFIELD(resetype)) {
11952 genDataPointerSet (right,result,ic);
11953 pic16_freeAsmop(result,NULL,ic,TRUE);
11957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11958 pic16_aopOp(right,ic,FALSE);
11959 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11961 /* if bitfield then unpack the bits */
11962 if (IS_BITFIELD(resetype)) {
11963 genPackBits (resetype, result, right, NULL, POINTER);
11965 /* we have can just get the values */
11966 int size = AOP_SIZE(right);
11969 pic16_loadFSR0(result, 0);
11971 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11973 if (AOP_TYPE(right) == AOP_LIT) {
11974 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11976 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11978 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11980 } else { // no literal
11982 pic16_emitpcode(POC_MOVFF,
11983 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11984 pic16_popCopyReg(&pic16_pc_postinc0)));
11986 pic16_emitpcode(POC_MOVFF,
11987 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11988 pic16_popCopyReg(&pic16_pc_indf0)));
11996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11997 /* now some housekeeping stuff */
11999 /* we had to allocate for this iCode */
12000 pic16_freeAsmop(NULL,aop,ic,TRUE);
12002 /* we did not allocate which means left
12003 * already in a pointer register, then
12004 * if size > 0 && this could be used again
12005 * we have to point it back to where it
12007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12008 if (AOP_SIZE(right) > 1
12009 && !OP_SYMBOL(result)->remat
12010 && ( OP_SYMBOL(result)->liveTo > ic->seq
12013 int size = AOP_SIZE(right) - 1;
12016 pic16_emitcode("decf","fsr0,f");
12017 //pic16_emitcode("dec","%s",rname);
12021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12024 pic16_freeAsmop(right,NULL,ic,TRUE);
12025 pic16_freeAsmop(result,NULL,ic,TRUE);
12028 /*-----------------------------------------------------------------*/
12029 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12030 /*-----------------------------------------------------------------*/
12031 static void genPagedPointerSet (operand *right,
12036 regs *preg = NULL ;
12040 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12042 retype= getSpec(operandType(right));
12044 pic16_aopOp(result,ic,FALSE);
12046 /* if the value is already in a pointer register
12047 then don't need anything more */
12048 if (!AOP_INPREG(AOP(result))) {
12049 /* otherwise get a free pointer register */
12051 preg = getFreePtr(ic,&aop,FALSE);
12052 pic16_emitcode("mov","%s,%s",
12054 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12055 rname = preg->name ;
12057 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12059 pic16_freeAsmop(result,NULL,ic,TRUE);
12060 pic16_aopOp (right,ic,FALSE);
12062 /* if bitfield then unpack the bits */
12063 if (IS_BITFIELD(retype))
12064 genPackBits (retype,result,right,rname,PPOINTER);
12066 /* we have can just get the values */
12067 int size = AOP_SIZE(right);
12071 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12074 pic16_emitcode("movx","@%s,a",rname);
12077 pic16_emitcode("inc","%s",rname);
12083 /* now some housekeeping stuff */
12085 /* we had to allocate for this iCode */
12086 pic16_freeAsmop(NULL,aop,ic,TRUE);
12088 /* we did not allocate which means left
12089 already in a pointer register, then
12090 if size > 0 && this could be used again
12091 we have to point it back to where it
12093 if (AOP_SIZE(right) > 1 &&
12094 !OP_SYMBOL(result)->remat &&
12095 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12097 int size = AOP_SIZE(right) - 1;
12099 pic16_emitcode("dec","%s",rname);
12104 pic16_freeAsmop(right,NULL,ic,TRUE);
12110 /* This code is not adjusted to PIC16 and fails utterly...
12111 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12113 /*-----------------------------------------------------------------*/
12114 /* genFarPointerSet - set value from far space */
12115 /*-----------------------------------------------------------------*/
12116 static void genFarPointerSet (operand *right,
12117 operand *result, iCode *ic)
12120 sym_link *retype = getSpec(operandType(right));
12122 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12123 pic16_aopOp(result,ic,FALSE);
12125 /* if the operand is already in dptr
12126 then we do nothing else we move the value to dptr */
12127 if (AOP_TYPE(result) != AOP_STR) {
12128 /* if this is remateriazable */
12129 if (AOP_TYPE(result) == AOP_IMMD)
12130 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12131 else { /* we need to get it byte by byte */
12132 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12133 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12134 if (options.model == MODEL_FLAT24)
12136 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12140 /* so dptr know contains the address */
12141 pic16_freeAsmop(result,NULL,ic,TRUE);
12142 pic16_aopOp(right,ic,FALSE);
12144 /* if bit then unpack */
12145 if (IS_BITFIELD(retype))
12146 genPackBits(retype,result,right,"dptr",FPOINTER);
12148 size = AOP_SIZE(right);
12152 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12154 pic16_emitcode("movx","@dptr,a");
12156 pic16_emitcode("inc","dptr");
12160 pic16_freeAsmop(right,NULL,ic,TRUE);
12164 /*-----------------------------------------------------------------*/
12165 /* genGenPointerSet - set value from generic pointer space */
12166 /*-----------------------------------------------------------------*/
12168 static void genGenPointerSet (operand *right,
12169 operand *result, iCode *ic)
12171 int i, size, offset, lit;
12172 sym_link *retype = getSpec(operandType(right));
12174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12176 pic16_aopOp(result,ic,FALSE);
12177 pic16_aopOp(right,ic,FALSE);
12178 size = AOP_SIZE(right);
12181 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12183 /* if the operand is already in dptr
12184 then we do nothing else we move the value to dptr */
12185 if (AOP_TYPE(result) != AOP_STR) {
12186 /* if this is remateriazable */
12187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12188 // WARNING: anythig until "else" is untested!
12189 if (AOP_TYPE(result) == AOP_IMMD) {
12190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12191 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12192 // load FSR0 from immediate
12193 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12197 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12199 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12205 else { /* we need to get it byte by byte */
12206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12207 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12209 // set up FSR0 with address of result
12210 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12211 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12213 /* hack hack! see if this the FSR. If so don't load W */
12214 if(AOP_TYPE(right) != AOP_ACC) {
12216 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12218 if(AOP_TYPE(right) == AOP_LIT)
12221 // note: pic16_popGet handles sign extension
12222 for(i=0;i<size;i++) {
12223 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12225 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12227 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12232 for(i=0;i<size;i++) {
12234 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12235 pic16_popCopyReg(&pic16_pc_postinc0)));
12237 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12238 pic16_popCopyReg(&pic16_pc_indf0)));
12244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12245 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12247 } // if (AOP_TYPE(result) != AOP_IMMD)
12249 } // if (AOP_TYPE(result) != AOP_STR)
12250 /* so dptr know contains the address */
12253 /* if bit then unpack */
12254 if (IS_BITFIELD(retype))
12255 genPackBits(retype,result,right,"dptr",GPOINTER);
12257 size = AOP_SIZE(right);
12260 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12262 // set up FSR0 with address of result
12263 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12267 if (AOP_TYPE(right) == AOP_LIT) {
12268 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12270 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12272 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12274 } else { // no literal
12276 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12278 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12286 pic16_freeAsmop(right,NULL,ic,TRUE);
12287 pic16_freeAsmop(result,NULL,ic,TRUE);
12291 static void genGenPointerSet (operand *right,
12292 operand *result, iCode *ic)
12295 sym_link *retype = getSpec(operandType(result));
12297 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12299 pic16_aopOp(result,ic,FALSE);
12300 pic16_aopOp(right,ic,FALSE);
12301 size = AOP_SIZE(right);
12303 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12306 /* if bit then unpack */
12307 if (IS_BITFIELD(retype)) {
12308 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12309 genPackBits(retype,result,right,"dptr",GPOINTER);
12313 size = AOP_SIZE(right);
12315 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12318 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12320 /* value of right+0 is placed on stack, which will be retrieved
12321 * by the support function thus restoring the stack. The important
12322 * thing is that there is no need to manually restore stack pointer
12324 pushaop(AOP(right), 0);
12325 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12326 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12327 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12328 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12330 /* load address to write to in WREG:FSR0H:FSR0L */
12331 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12332 pic16_popCopyReg(&pic16_pc_fsr0l)));
12333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12334 pic16_popCopyReg(&pic16_pc_prodl)));
12335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12337 pic16_callGenericPointerRW(1, size);
12340 pic16_freeAsmop(right,NULL,ic,TRUE);
12341 pic16_freeAsmop(result,NULL,ic,TRUE);
12344 /*-----------------------------------------------------------------*/
12345 /* genPointerSet - stores the value into a pointer location */
12346 /*-----------------------------------------------------------------*/
12347 static void genPointerSet (iCode *ic)
12349 operand *right, *result ;
12350 sym_link *type, *etype;
12355 right = IC_RIGHT(ic);
12356 result = IC_RESULT(ic) ;
12358 /* depending on the type of pointer we need to
12359 move it to the correct pointer register */
12360 type = operandType(result);
12361 etype = getSpec(type);
12363 /* if left is of type of pointer then it is simple */
12364 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12365 p_type = DCL_TYPE(type);
12368 /* we have to go by the storage class */
12369 p_type = PTR_TYPE(SPEC_OCLS(etype));
12371 /* if (SPEC_OCLS(etype)->codesp ) { */
12372 /* p_type = CPOINTER ; */
12375 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12376 /* p_type = FPOINTER ; */
12378 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12379 /* p_type = PPOINTER ; */
12381 /* if (SPEC_OCLS(etype) == idata ) */
12382 /* p_type = IPOINTER ; */
12384 /* p_type = POINTER ; */
12387 /* now that we have the pointer type we assign
12388 the pointer values */
12393 genNearPointerSet (right,result,ic);
12397 genPagedPointerSet (right,result,ic);
12401 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12403 genFarPointerSet (right,result,ic);
12408 genGenPointerSet (right,result,ic);
12412 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12413 "genPointerSet: illegal pointer type");
12417 /*-----------------------------------------------------------------*/
12418 /* genIfx - generate code for Ifx statement */
12419 /*-----------------------------------------------------------------*/
12420 static void genIfx (iCode *ic, iCode *popIc)
12422 operand *cond = IC_COND(ic);
12427 pic16_aopOp(cond,ic,FALSE);
12429 /* get the value into acc */
12430 if (AOP_TYPE(cond) != AOP_CRY)
12431 pic16_toBoolean(cond);
12434 /* the result is now in the accumulator */
12435 pic16_freeAsmop(cond,NULL,ic,TRUE);
12437 /* if there was something to be popped then do it */
12441 /* if the condition is a bit variable */
12442 if (isbit && IS_ITEMP(cond) &&
12444 genIfxJump(ic,"c");
12445 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12447 if (isbit && !IS_ITEMP(cond))
12448 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12450 genIfxJump(ic,"a");
12455 /*-----------------------------------------------------------------*/
12456 /* genAddrOf - generates code for address of */
12457 /*-----------------------------------------------------------------*/
12458 static void genAddrOf (iCode *ic)
12460 operand *result, *left;
12462 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12463 pCodeOp *pcop0, *pcop1, *pcop2;
12467 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12469 sym = OP_SYMBOL( IC_LEFT(ic) );
12472 /* get address of symbol on stack */
12473 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12475 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12476 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12479 // operands on stack are accessible via "FSR2 + index" with index
12480 // starting at 2 for arguments and growing from 0 downwards for
12481 // local variables (index == 0 is not assigned so we add one here)
12483 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12486 assert (soffs < 0);
12490 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12491 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12492 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12493 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12494 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12495 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12496 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12502 // if(pic16_debug_verbose) {
12503 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12504 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12507 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12508 size = AOP_SIZE(IC_RESULT(ic));
12510 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12511 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12515 pic16_emitpcode(POC_MOVLW, pcop0);
12516 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12517 pic16_emitpcode(POC_MOVLW, pcop1);
12518 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12519 pic16_emitpcode(POC_MOVLW, pcop2);
12520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12523 pic16_emitpcode(POC_MOVLW, pcop0);
12524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12525 pic16_emitpcode(POC_MOVLW, pcop1);
12526 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12528 pic16_emitpcode(POC_MOVLW, pcop0);
12529 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12532 pic16_freeAsmop(left, NULL, ic, FALSE);
12534 pic16_freeAsmop(result,NULL,ic,TRUE);
12539 /*-----------------------------------------------------------------*/
12540 /* genFarFarAssign - assignment when both are in far space */
12541 /*-----------------------------------------------------------------*/
12542 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12544 int size = AOP_SIZE(right);
12547 /* first push the right side on to the stack */
12549 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12551 pic16_emitcode ("push","acc");
12554 pic16_freeAsmop(right,NULL,ic,FALSE);
12555 /* now assign DPTR to result */
12556 pic16_aopOp(result,ic,FALSE);
12557 size = AOP_SIZE(result);
12559 pic16_emitcode ("pop","acc");
12560 pic16_aopPut(AOP(result),"a",--offset);
12562 pic16_freeAsmop(result,NULL,ic,FALSE);
12567 /*-----------------------------------------------------------------*/
12568 /* genAssign - generate code for assignment */
12569 /*-----------------------------------------------------------------*/
12570 static void genAssign (iCode *ic)
12572 operand *result, *right;
12573 sym_link *restype, *rtype;
12574 int size, offset,know_W;
12575 unsigned long lit = 0L;
12577 result = IC_RESULT(ic);
12578 right = IC_RIGHT(ic) ;
12582 /* if they are the same */
12583 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12586 /* reversed order operands are aopOp'ed so that result operand
12587 * is effective in case right is a stack symbol. This maneauver
12588 * allows to use the _G.resDirect flag later */
12589 pic16_aopOp(result,ic,TRUE);
12590 pic16_aopOp(right,ic,FALSE);
12592 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12594 /* if they are the same registers */
12595 if (pic16_sameRegs(AOP(right),AOP(result)))
12598 /* if the result is a bit */
12599 if (AOP_TYPE(result) == AOP_CRY) {
12600 /* if the right size is a literal then
12601 we know what the value is */
12602 if (AOP_TYPE(right) == AOP_LIT) {
12604 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12605 pic16_popGet(AOP(result),0));
12607 if (((int) operandLitValue(right)))
12608 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12609 AOP(result)->aopu.aop_dir,
12610 AOP(result)->aopu.aop_dir);
12612 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12613 AOP(result)->aopu.aop_dir,
12614 AOP(result)->aopu.aop_dir);
12619 /* the right is also a bit variable */
12620 if (AOP_TYPE(right) == AOP_CRY) {
12621 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12622 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12623 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12628 /* we need to or */
12629 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12630 pic16_toBoolean(right);
12632 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12633 //pic16_aopPut(AOP(result),"a",0);
12637 /* bit variables done */
12639 size = AOP_SIZE(result);
12642 /* bit variables done */
12644 size = AOP_SIZE(result);
12645 restype = operandType(result);
12646 rtype = operandType(right);
12649 if(AOP_TYPE(right) == AOP_LIT) {
12650 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12652 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12654 /* patch tag for literals that are cast to pointers */
12655 if (IS_CODEPTR(restype)) {
12656 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12657 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12659 if (IS_GENPTR(restype))
12661 if (IS_CODEPTR(rtype)) {
12662 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12663 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12664 } else if (PIC_IS_DATA_PTR(rtype)) {
12665 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12666 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12667 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12668 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12669 } else if (IS_PTR(rtype)) {
12670 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12671 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12677 unsigned long lit_int;
12682 if(IS_FIXED16X16(operandType(right))) {
12683 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12685 /* take care if literal is a float */
12686 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12687 lit = info.lit_int;
12692 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12693 // sizeof(unsigned long int), sizeof(float));
12696 if (AOP_TYPE(right) == AOP_REG) {
12697 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12699 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12704 /* when do we have to read the program memory?
12705 * - if right itself is a symbol in code space
12706 * (we don't care what it points to if it's a pointer)
12707 * - AND right is not a function (we would want its address)
12709 if(AOP_TYPE(right) != AOP_LIT
12710 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12711 && !IS_FUNC(OP_SYM_TYPE(right))
12712 && !IS_ITEMP(right)) {
12714 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12715 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12717 // set up table pointer
12718 if(is_LitOp(right)) {
12719 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12720 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12721 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12722 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12723 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12724 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12725 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12727 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12728 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12729 pic16_popCopyReg(&pic16_pc_tblptrl)));
12730 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12731 pic16_popCopyReg(&pic16_pc_tblptrh)));
12732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12733 pic16_popCopyReg(&pic16_pc_tblptru)));
12736 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12737 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12739 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12740 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12741 pic16_popGet(AOP(result),offset)));
12745 /* FIXME: for pointers we need to extend differently (according
12746 * to pointer type DATA/CODE/EEPROM/... :*/
12747 size = getSize(OP_SYM_TYPE(right));
12748 if(AOP_SIZE(result) > size) {
12749 size = AOP_SIZE(result) - size;
12751 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12759 /* VR - What is this?! */
12760 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12763 if(aopIdx(AOP(result),0) == 4) {
12764 /* this is a workaround to save value of right into wreg too,
12765 * value of wreg is going to be used later */
12766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12772 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12776 size = AOP_SIZE(right);
12777 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12780 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12781 if(AOP_TYPE(right) == AOP_LIT) {
12783 if(know_W != (lit&0xff))
12784 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12788 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12792 } else if (AOP_TYPE(right) == AOP_CRY) {
12793 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12795 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12796 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12797 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12799 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12800 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12801 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12805 if(!_G.resDirect) { /* use this aopForSym feature */
12806 if(AOP_TYPE(result) == AOP_ACC) {
12807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12809 if(AOP_TYPE(right) == AOP_ACC) {
12810 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12812 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12819 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12822 pic16_freeAsmop (right,NULL,ic,FALSE);
12823 pic16_freeAsmop (result,NULL,ic,TRUE);
12826 /*-----------------------------------------------------------------*/
12827 /* genJumpTab - generates code for jump table */
12828 /*-----------------------------------------------------------------*/
12829 static void genJumpTab (iCode *ic)
12834 pCodeOp *jt_offs_hi;
12839 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12840 /* get the condition into accumulator */
12841 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12843 /* multiply by three */
12844 pic16_emitcode("add","a,acc");
12845 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12847 jtab = newiTempLabel(NULL);
12848 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12849 pic16_emitcode("jmp","@a+dptr");
12850 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12853 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12854 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12856 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12857 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12858 pic16_emitpLabel(jtab->key);
12862 jt_offs = pic16_popGetTempReg(0);
12863 jt_offs_hi = pic16_popGetTempReg(1);
12864 jt_label = pic16_popGetLabel (jtab->key);
12865 //fprintf (stderr, "Creating jump table...\n");
12867 // calculate offset into jump table (idx * sizeof (GOTO))
12868 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12869 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12870 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12871 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12872 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12873 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12874 pic16_emitpcode(POC_MOVWF , jt_offs);
12876 // prepare PCLATx (set to first entry in jump table)
12877 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12878 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12879 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12880 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12881 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12883 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12884 pic16_emitpcode(POC_ADDWF , jt_offs);
12885 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12886 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12888 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12890 // release temporaries and prepare jump into table (new PCL --> WREG)
12891 pic16_emitpcode(POC_MOVFW , jt_offs);
12892 pic16_popReleaseTempReg (jt_offs_hi, 1);
12893 pic16_popReleaseTempReg (jt_offs, 0);
12895 // jump into the table
12896 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12898 pic16_emitpLabelFORCE(jtab->key);
12901 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12902 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12904 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12905 /* now generate the jump labels */
12906 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12907 jtab = setNextItem(IC_JTLABELS(ic))) {
12908 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12912 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12916 /*-----------------------------------------------------------------*/
12917 /* genMixedOperation - gen code for operators between mixed types */
12918 /*-----------------------------------------------------------------*/
12920 TSD - Written for the PIC port - but this unfortunately is buggy.
12921 This routine is good in that it is able to efficiently promote
12922 types to different (larger) sizes. Unfortunately, the temporary
12923 variables that are optimized out by this routine are sometimes
12924 used in other places. So until I know how to really parse the
12925 iCode tree, I'm going to not be using this routine :(.
12927 static int genMixedOperation (iCode *ic)
12930 operand *result = IC_RESULT(ic);
12931 sym_link *ctype = operandType(IC_LEFT(ic));
12932 operand *right = IC_RIGHT(ic);
12938 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12940 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12946 nextright = IC_RIGHT(nextic);
12947 nextleft = IC_LEFT(nextic);
12948 nextresult = IC_RESULT(nextic);
12950 pic16_aopOp(right,ic,FALSE);
12951 pic16_aopOp(result,ic,FALSE);
12952 pic16_aopOp(nextright, nextic, FALSE);
12953 pic16_aopOp(nextleft, nextic, FALSE);
12954 pic16_aopOp(nextresult, nextic, FALSE);
12956 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12958 operand *t = right;
12962 pic16_emitcode(";remove right +","");
12964 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12966 operand *t = right;
12970 pic16_emitcode(";remove left +","");
12974 big = AOP_SIZE(nextleft);
12975 small = AOP_SIZE(nextright);
12977 switch(nextic->op) {
12980 pic16_emitcode(";optimize a +","");
12981 /* if unsigned or not an integral type */
12982 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12983 pic16_emitcode(";add a bit to something","");
12986 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12988 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12989 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12990 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12992 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13000 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13001 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13002 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13005 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13007 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13008 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13009 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13010 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13011 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13014 pic16_emitcode("rlf","known_zero,w");
13021 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13022 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13023 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13025 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13035 pic16_freeAsmop(right,NULL,ic,TRUE);
13036 pic16_freeAsmop(result,NULL,ic,TRUE);
13037 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13038 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13040 nextic->generated = 1;
13047 /*-----------------------------------------------------------------*/
13048 /* genCast - gen code for casting */
13049 /*-----------------------------------------------------------------*/
13050 static void genCast (iCode *ic)
13052 operand *result = IC_RESULT(ic);
13053 sym_link *ctype = operandType(IC_LEFT(ic));
13054 sym_link *rtype = operandType(IC_RIGHT(ic));
13055 sym_link *restype = operandType(IC_RESULT(ic));
13056 operand *right = IC_RIGHT(ic);
13062 /* if they are equivalent then do nothing */
13063 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13066 pic16_aopOp(result,ic,FALSE);
13067 pic16_aopOp(right,ic,FALSE) ;
13069 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13072 /* if the result is a bit */
13073 if (AOP_TYPE(result) == AOP_CRY) {
13075 /* if the right size is a literal then
13076 * we know what the value is */
13077 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13079 if (AOP_TYPE(right) == AOP_LIT) {
13080 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13081 pic16_popGet(AOP(result),0));
13083 if (((int) operandLitValue(right)))
13084 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13085 AOP(result)->aopu.aop_dir,
13086 AOP(result)->aopu.aop_dir);
13088 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13089 AOP(result)->aopu.aop_dir,
13090 AOP(result)->aopu.aop_dir);
13094 /* the right is also a bit variable */
13095 if (AOP_TYPE(right) == AOP_CRY) {
13097 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13099 pic16_emitcode("clrc","");
13100 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13101 AOP(right)->aopu.aop_dir,
13102 AOP(right)->aopu.aop_dir);
13103 pic16_aopPut(AOP(result),"c",0);
13107 /* we need to or */
13108 if (AOP_TYPE(right) == AOP_REG) {
13109 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13110 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13111 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13113 pic16_toBoolean(right);
13114 pic16_aopPut(AOP(result),"a",0);
13118 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13121 size = AOP_SIZE(result);
13123 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13125 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13126 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13127 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13130 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13135 if(IS_BITFIELD(getSpec(restype))
13136 && IS_BITFIELD(getSpec(rtype))) {
13137 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13140 /* port from pic14 to cope with generic pointers */
13141 if (PIC_IS_TAGGED(restype))
13143 operand *result = IC_RESULT(ic);
13144 //operand *left = IC_LEFT(ic);
13145 operand *right = IC_RIGHT(ic);
13148 /* copy common part */
13149 int max, size = AOP_SIZE(result);
13150 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13151 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13156 pic16_mov2w (AOP(right), size);
13157 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13160 /* upcast into generic pointer type? */
13161 if (IS_GENPTR(restype)
13162 && !PIC_IS_TAGGED(rtype)
13163 && (AOP_SIZE(result) > max))
13165 /* determine appropriate tag for right */
13166 if (PIC_IS_DATA_PTR(rtype))
13167 tag = GPTR_TAG_DATA;
13168 else if (IS_CODEPTR(rtype))
13169 tag = GPTR_TAG_CODE;
13170 else if (PIC_IS_DATA_PTR(ctype)) {
13171 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13172 tag = GPTR_TAG_DATA;
13173 } else if (IS_CODEPTR(ctype)) {
13174 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13175 tag = GPTR_TAG_CODE;
13176 } else if (IS_PTR(rtype)) {
13177 PERFORM_ONCE(weirdcast,
13178 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13180 tag = GPTR_TAG_DATA;
13182 PERFORM_ONCE(weirdcast,
13183 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13185 tag = GPTR_TAG_DATA;
13188 assert (AOP_SIZE(result) == 3);
13189 /* zero-extend address... */
13190 for (size = max; size < AOP_SIZE(result)-1; size++)
13191 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13192 /* ...and add tag */
13193 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13194 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13195 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13196 for (size = max; size < AOP_SIZE(result)-1; size++)
13197 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13198 /* add __code tag */
13199 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13200 } else if (AOP_SIZE(result) > max) {
13201 /* extend non-pointers */
13202 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13203 pic16_addSign(result, max, 0);
13208 /* if they are the same size : or less */
13209 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13211 /* if they are in the same place */
13212 if (pic16_sameRegs(AOP(right),AOP(result)))
13215 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13217 if (IS_PTR_CONST(rtype))
13219 if (IS_CODEPTR(rtype))
13221 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13224 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13226 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13228 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13231 if(AOP_TYPE(right) == AOP_IMMD) {
13232 pCodeOp *pcop0, *pcop1, *pcop2;
13233 symbol *sym = OP_SYMBOL( right );
13235 size = AOP_SIZE(result);
13237 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13239 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13241 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13244 pic16_emitpcode(POC_MOVLW, pcop0);
13245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13246 pic16_emitpcode(POC_MOVLW, pcop1);
13247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13248 pic16_emitpcode(POC_MOVLW, pcop2);
13249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13252 pic16_emitpcode(POC_MOVLW, pcop0);
13253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13254 pic16_emitpcode(POC_MOVLW, pcop1);
13255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13257 pic16_emitpcode(POC_MOVLW, pcop0);
13258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13262 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13263 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13266 if(AOP_SIZE(result) < 2) {
13267 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13269 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13273 /* if they in different places then copy */
13274 size = AOP_SIZE(result);
13277 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13285 /* if the result is of type pointer */
13286 if (IS_PTR(ctype)) {
13288 sym_link *type = operandType(right);
13289 sym_link *etype = getSpec(type);
13291 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13293 /* pointer to generic pointer */
13294 if (IS_GENPTR(ctype)) {
13298 p_type = DCL_TYPE(type);
13300 /* we have to go by the storage class */
13301 p_type = PTR_TYPE(SPEC_OCLS(etype));
13303 /* if (SPEC_OCLS(etype)->codesp ) */
13304 /* p_type = CPOINTER ; */
13306 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13307 /* p_type = FPOINTER ; */
13309 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13310 /* p_type = PPOINTER; */
13312 /* if (SPEC_OCLS(etype) == idata ) */
13313 /* p_type = IPOINTER ; */
13315 /* p_type = POINTER ; */
13318 /* the first two bytes are known */
13319 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13320 size = GPTRSIZE - 1;
13323 if(offset < AOP_SIZE(right)) {
13324 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13325 pic16_mov2f(AOP(result), AOP(right), offset);
13327 if ((AOP_TYPE(right) == AOP_PCODE) &&
13328 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13329 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13333 pic16_aopPut(AOP(result),
13334 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13339 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13342 /* the last byte depending on type */
13347 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13351 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13355 pic16_emitcode(";BUG!? ","%d",__LINE__);
13360 if (GPTRSIZE > AOP_SIZE(right)) {
13361 // assume __data pointer... THIS MIGHT BE WRONG!
13362 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13364 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13369 /* this should never happen */
13370 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13371 "got unknown pointer type");
13374 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13380 /* just copy the pointers */
13381 size = AOP_SIZE(result);
13384 pic16_aopPut(AOP(result),
13385 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13394 /* so we now know that the size of destination is greater
13395 than the size of the source.
13396 Now, if the next iCode is an operator then we might be
13397 able to optimize the operation without performing a cast.
13399 if(genMixedOperation(ic))
13402 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13404 /* we move to result for the size of source */
13405 size = AOP_SIZE(right);
13410 pic16_mov2f(AOP(result), AOP(right), offset);
13414 /* now depending on the sign of the destination */
13415 size = AOP_SIZE(result) - AOP_SIZE(right);
13416 /* if unsigned or not an integral type */
13417 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13419 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13421 /* we need to extend the sign :( */
13424 /* Save one instruction of casting char to int */
13425 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13426 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13427 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13429 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13432 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13434 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13444 pic16_freeAsmop(right,NULL,ic,TRUE);
13445 pic16_freeAsmop(result,NULL,ic,TRUE);
13449 /*-----------------------------------------------------------------*/
13450 /* genDjnz - generate decrement & jump if not zero instrucion */
13451 /*-----------------------------------------------------------------*/
13452 static int genDjnz (iCode *ic, iCode *ifx)
13454 symbol *lbl, *lbl1;
13455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13460 /* if the if condition has a false label
13461 then we cannot save */
13465 /* if the minus is not of the form
13467 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13468 !IS_OP_LITERAL(IC_RIGHT(ic)))
13471 if (operandLitValue(IC_RIGHT(ic)) != 1)
13474 /* if the size of this greater than one then no
13476 if (getSize(operandType(IC_RESULT(ic))) > 1)
13479 /* otherwise we can save BIG */
13480 lbl = newiTempLabel(NULL);
13481 lbl1= newiTempLabel(NULL);
13483 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13485 if (IS_AOP_PREG(IC_RESULT(ic))) {
13486 pic16_emitcode("dec","%s",
13487 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13488 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13489 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13493 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13494 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13496 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13497 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13501 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13502 ifx->generated = 1;
13506 /*-----------------------------------------------------------------*/
13507 /* genReceive - generate code for a receive iCode */
13508 /*-----------------------------------------------------------------*/
13509 static void genReceive (iCode *ic)
13515 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13516 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13518 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13520 if (isOperandInFarSpace(IC_RESULT(ic))
13521 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13522 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13524 int size = getSize(operandType(IC_RESULT(ic)));
13525 int offset = pic16_fReturnSizePic - size;
13529 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13530 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13534 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13536 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13537 size = AOP_SIZE(IC_RESULT(ic));
13540 pic16_emitcode ("pop","acc");
13541 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13544 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13546 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13549 /* set pseudo stack pointer to where it should be - dw*/
13550 GpsuedoStkPtr = ic->parmBytes;
13552 /* setting GpsuedoStkPtr has side effects here: */
13553 /* FIXME: What's the correct size of the return(ed) value?
13554 * For now, assuming '4' as before... */
13555 assignResultValue(IC_RESULT(ic), 4, 0);
13558 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13561 /*-----------------------------------------------------------------*/
13562 /* genDummyRead - generate code for dummy read of volatiles */
13563 /*-----------------------------------------------------------------*/
13565 genDummyRead (iCode * ic)
13571 if (op && IS_SYMOP(op)) {
13572 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13573 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13576 pic16_aopOp (op, ic, FALSE);
13577 for (i=0; i < AOP_SIZE(op); i++) {
13578 // may need to protect this from the peepholer -- this is not nice but works...
13579 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13580 pic16_mov2w (AOP(op),i);
13581 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13583 pic16_freeAsmop (op, NULL, ic, TRUE);
13585 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13589 /*-----------------------------------------------------------------*/
13590 /* genpic16Code - generate code for pic16 based controllers */
13591 /*-----------------------------------------------------------------*/
13593 * At this point, ralloc.c has gone through the iCode and attempted
13594 * to optimize in a way suitable for a PIC. Now we've got to generate
13595 * PIC instructions that correspond to the iCode.
13597 * Once the instructions are generated, we'll pass through both the
13598 * peep hole optimizer and the pCode optimizer.
13599 *-----------------------------------------------------------------*/
13601 void genpic16Code (iCode *lic)
13606 lineHead = lineCurr = NULL;
13608 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13609 pic16_addpBlock(pb);
13612 /* if debug information required */
13613 if (options.debug && currFunc) {
13615 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13620 for (ic = lic ; ic ; ic = ic->next ) {
13622 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13623 if ( cln != ic->lineno ) {
13624 if ( options.debug ) {
13625 debugFile->writeCLine (ic);
13628 if(!options.noCcodeInAsm) {
13629 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13630 printCLine(ic->filename, ic->lineno)));
13636 if(options.iCodeInAsm) {
13639 /* insert here code to print iCode as comment */
13640 iLine = printILine(ic);
13641 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13645 /* if the result is marked as
13646 * spilt and rematerializable or code for
13647 * this has already been generated then
13649 if (resultRemat(ic) || ic->generated )
13652 /* depending on the operation */
13671 /* IPOP happens only when trying to restore a
13672 * spilt live range, if there is an ifx statement
13673 * following this pop then the if statement might
13674 * be using some of the registers being popped which
13675 * would destroy the contents of the register so
13676 * we need to check for this condition and handle it */
13678 && ic->next->op == IFX
13679 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13680 genIfx (ic->next,ic);
13698 genEndFunction (ic);
13714 pic16_genPlus (ic) ;
13718 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13719 pic16_genMinus (ic);
13735 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13739 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13745 /* note these two are xlated by algebraic equivalence
13746 * during parsing SDCC.y */
13747 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13748 "got '>=' or '<=' shouldn't have come here");
13752 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13764 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13768 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13772 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13796 genRightShift (ic);
13799 case GET_VALUE_AT_ADDRESS:
13804 if (POINTER_SET(ic))
13831 addSet(&_G.sendSet,ic);
13834 case DUMMY_READ_VOLATILE:
13844 /* now we are ready to call the
13845 peep hole optimizer */
13846 if (!options.nopeep)
13847 peepHole (&lineHead);
13849 /* now do the actual printing */
13850 printLine (lineHead, codeOutBuf);
13853 DFPRINTF((stderr,"printing pBlock\n\n"));
13854 pic16_printpBlock(stdout,pb);