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;
8484 bool inComment = FALSE;
8486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8488 _G.inLine += (!options.asmpeep);
8490 buffer = bp = bp1 = Safe_strdup (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 */
8569 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8574 /* Add \n for labels, not dirs such as c:\mydir */
8575 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8580 /* print label, use this special format with NULL directive
8581 * to denote that the argument should not be indented with tab */
8582 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8591 if ((bp1 != bp) && *bp1)
8592 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8596 _G.inLine -= (!options.asmpeep);
8599 /*-----------------------------------------------------------------*/
8600 /* genRRC - rotate right with carry */
8601 /*-----------------------------------------------------------------*/
8602 static void genRRC (iCode *ic)
8604 operand *left , *result ;
8605 int size, offset = 0, same;
8607 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8609 /* rotate right with carry */
8611 result=IC_RESULT(ic);
8612 pic16_aopOp (left,ic,FALSE);
8613 pic16_aopOp (result,ic,TRUE);
8615 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8617 same = pic16_sameRegs(AOP(result),AOP(left));
8619 size = AOP_SIZE(result);
8621 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8623 /* get the lsb and put it into the carry */
8624 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8631 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8633 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8634 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8640 pic16_freeAsmop(left,NULL,ic,TRUE);
8641 pic16_freeAsmop(result,NULL,ic,TRUE);
8644 /*-----------------------------------------------------------------*/
8645 /* genRLC - generate code for rotate left with carry */
8646 /*-----------------------------------------------------------------*/
8647 static void genRLC (iCode *ic)
8649 operand *left , *result ;
8650 int size, offset = 0;
8653 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8654 /* rotate right with carry */
8656 result=IC_RESULT(ic);
8657 pic16_aopOp (left,ic,FALSE);
8658 pic16_aopOp (result,ic,TRUE);
8660 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8662 same = pic16_sameRegs(AOP(result),AOP(left));
8664 /* move it to the result */
8665 size = AOP_SIZE(result);
8667 /* get the msb and put it into the carry */
8668 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8675 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8677 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8685 pic16_freeAsmop(left,NULL,ic,TRUE);
8686 pic16_freeAsmop(result,NULL,ic,TRUE);
8690 /* gpasm can get the highest order bit with HIGH/UPPER
8691 * so the following probably is not needed -- VR */
8693 /*-----------------------------------------------------------------*/
8694 /* genGetHbit - generates code get highest order bit */
8695 /*-----------------------------------------------------------------*/
8696 static void genGetHbit (iCode *ic)
8698 operand *left, *result;
8700 result=IC_RESULT(ic);
8701 pic16_aopOp (left,ic,FALSE);
8702 pic16_aopOp (result,ic,FALSE);
8704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8705 /* get the highest order byte into a */
8706 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8707 if(AOP_TYPE(result) == AOP_CRY){
8708 pic16_emitcode("rlc","a");
8709 pic16_outBitC(result);
8712 pic16_emitcode("rl","a");
8713 pic16_emitcode("anl","a,#0x01");
8714 pic16_outAcc(result);
8718 pic16_freeAsmop(left,NULL,ic,TRUE);
8719 pic16_freeAsmop(result,NULL,ic,TRUE);
8723 /*-----------------------------------------------------------------*/
8724 /* AccRol - rotate left accumulator by known count */
8725 /*-----------------------------------------------------------------*/
8726 static void AccRol (int shCount)
8728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8729 shCount &= 0x0007; // shCount : 0..7
8734 pic16_emitcode("rl","a");
8737 pic16_emitcode("rl","a");
8738 pic16_emitcode("rl","a");
8741 pic16_emitcode("swap","a");
8742 pic16_emitcode("rr","a");
8745 pic16_emitcode("swap","a");
8748 pic16_emitcode("swap","a");
8749 pic16_emitcode("rl","a");
8752 pic16_emitcode("rr","a");
8753 pic16_emitcode("rr","a");
8756 pic16_emitcode("rr","a");
8762 /*-----------------------------------------------------------------*/
8763 /* AccLsh - left shift accumulator by known count */
8764 /*-----------------------------------------------------------------*/
8765 static void AccLsh (int shCount, int doMask)
8767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8773 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8776 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8777 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8780 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8781 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8784 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8787 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8788 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8791 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8792 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8795 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8799 /* no masking is required in genPackBits */
8800 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8804 /*-----------------------------------------------------------------*/
8805 /* AccRsh - right shift accumulator by known count */
8806 /*-----------------------------------------------------------------*/
8807 static void AccRsh (int shCount, int andmask)
8809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8814 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8817 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8818 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8821 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8822 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8825 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8828 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8829 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8832 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8836 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8841 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8843 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8847 /*-----------------------------------------------------------------*/
8848 /* AccSRsh - signed right shift accumulator by known count */
8849 /*-----------------------------------------------------------------*/
8850 static void AccSRsh (int shCount)
8853 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8856 pic16_emitcode("mov","c,acc.7");
8857 pic16_emitcode("rrc","a");
8858 } else if(shCount == 2){
8859 pic16_emitcode("mov","c,acc.7");
8860 pic16_emitcode("rrc","a");
8861 pic16_emitcode("mov","c,acc.7");
8862 pic16_emitcode("rrc","a");
8864 tlbl = newiTempLabel(NULL);
8865 /* rotate right accumulator */
8866 AccRol(8 - shCount);
8867 /* and kill the higher order bits */
8868 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8869 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8870 pic16_emitcode("orl","a,#0x%02x",
8871 (unsigned char)~SRMask[shCount]);
8872 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8878 /*-----------------------------------------------------------------*/
8879 /* shiftR1Left2Result - shift right one byte from left to result */
8880 /*-----------------------------------------------------------------*/
8881 static void shiftR1Left2ResultSigned (operand *left, int offl,
8882 operand *result, int offr,
8887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8889 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8893 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8895 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8898 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8904 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8906 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8911 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8912 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8918 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8920 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8921 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8924 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8925 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8926 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8928 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8929 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8936 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8937 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8938 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8943 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8945 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8950 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8951 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8958 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8959 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8960 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8961 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8966 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8968 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8974 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8975 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8976 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8981 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8989 /*-----------------------------------------------------------------*/
8990 /* shiftR1Left2Result - shift right one byte from left to result */
8991 /*-----------------------------------------------------------------*/
8992 static void shiftR1Left2Result (operand *left, int offl,
8993 operand *result, int offr,
8994 int shCount, int sign)
8998 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9000 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9002 /* Copy the msb into the carry if signed. */
9004 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9014 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9041 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9043 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9048 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9053 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9054 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9057 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9063 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9065 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9066 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9071 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9072 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9073 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9082 /*-----------------------------------------------------------------*/
9083 /* shiftL1Left2Result - shift left one byte from left to result */
9084 /*-----------------------------------------------------------------*/
9085 static void shiftL1Left2Result (operand *left, int offl,
9086 operand *result, int offr, int shCount)
9091 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9093 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9094 DEBUGpic16_emitcode ("; ***","same = %d",same);
9095 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9097 /* shift left accumulator */
9098 //AccLsh(shCount, 1); // don't comment out just yet...
9099 // pic16_aopPut(AOP(result),"a",offr);
9103 /* Shift left 1 bit position */
9104 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9106 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9108 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9109 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9114 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9119 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9120 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9121 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9123 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9126 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9127 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9128 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9132 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9133 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9138 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9139 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9145 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9150 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9155 /*-----------------------------------------------------------------*/
9156 /* movLeft2Result - move byte from left to result */
9157 /*-----------------------------------------------------------------*/
9158 static void movLeft2Result (operand *left, int offl,
9159 operand *result, int offr)
9162 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9163 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9164 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9166 if (*l == '@' && (IS_AOP_PREG(result))) {
9167 pic16_emitcode("mov","a,%s",l);
9168 pic16_aopPut(AOP(result),"a",offr);
9170 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9171 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9176 /*-----------------------------------------------------------------*/
9177 /* shiftL2Left2Result - shift left two bytes from left to result */
9178 /*-----------------------------------------------------------------*/
9179 static void shiftL2Left2Result (operand *left, int offl,
9180 operand *result, int offr, int shCount)
9182 int same = pic16_sameRegs(AOP(result), AOP(left));
9185 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9187 if (same && (offl != offr)) { // shift bytes
9190 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9191 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9193 } else { // just treat as different later on
9206 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9207 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9208 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9212 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9213 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9219 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9220 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9221 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9222 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9223 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9224 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9225 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9227 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9228 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9232 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9233 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9234 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9235 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9236 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9237 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9238 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9239 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9240 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9241 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9244 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9245 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9246 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9247 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9248 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9258 /* note, use a mov/add for the shift since the mov has a
9259 chance of getting optimized out */
9260 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9262 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9263 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9268 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9269 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9275 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9276 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9277 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9278 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9279 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9280 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9281 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9282 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9286 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9287 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9291 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9293 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9294 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9296 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9297 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9298 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9300 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9301 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9302 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9306 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9307 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9308 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9309 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9310 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9315 /*-----------------------------------------------------------------*/
9316 /* shiftR2Left2Result - shift right two bytes from left to result */
9317 /*-----------------------------------------------------------------*/
9318 static void shiftR2Left2Result (operand *left, int offl,
9319 operand *result, int offr,
9320 int shCount, int sign)
9322 int same = pic16_sameRegs(AOP(result), AOP(left));
9324 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9326 if (same && (offl != offr)) { // shift right bytes
9329 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9330 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9332 } else { // just treat as different later on
9343 /* obtain sign from left operand */
9345 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9350 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9351 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9353 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9354 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9355 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9356 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9361 /* now get sign from already assigned result (avoid BANKSEL) */
9362 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9365 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9366 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9373 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9374 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9375 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9377 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9378 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9379 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9380 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9382 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9383 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9384 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9386 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9387 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9388 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9389 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9390 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9394 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9395 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9399 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9400 pic16_emitpcode(POC_BTFSC,
9401 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9402 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9410 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9411 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9413 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9414 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9415 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9416 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9418 pic16_emitpcode(POC_BTFSC,
9419 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9420 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9422 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9424 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9425 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9427 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9428 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9429 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9430 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9431 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9432 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9433 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9434 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9436 pic16_emitpcode(POC_BTFSC,
9437 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9438 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9440 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9441 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9448 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9449 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9450 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9451 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9454 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9456 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9461 /*-----------------------------------------------------------------*/
9462 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9463 /*-----------------------------------------------------------------*/
9464 static void shiftLLeftOrResult (operand *left, int offl,
9465 operand *result, int offr, int shCount)
9467 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9469 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9470 /* shift left accumulator */
9472 /* or with result */
9473 /* back to result */
9474 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9477 /*-----------------------------------------------------------------*/
9478 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9479 /*-----------------------------------------------------------------*/
9480 static void shiftRLeftOrResult (operand *left, int offl,
9481 operand *result, int offr, int shCount)
9483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9485 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9486 /* shift right accumulator */
9488 /* or with result */
9489 /* back to result */
9490 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9493 /*-----------------------------------------------------------------*/
9494 /* genlshOne - left shift a one byte quantity by known count */
9495 /*-----------------------------------------------------------------*/
9496 static void genlshOne (operand *result, operand *left, int shCount)
9498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9499 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9502 /*-----------------------------------------------------------------*/
9503 /* genlshTwo - left shift two bytes by known amount != 0 */
9504 /*-----------------------------------------------------------------*/
9505 static void genlshTwo (operand *result,operand *left, int shCount)
9509 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9510 size = pic16_getDataSize(result);
9512 /* if shCount >= 8 */
9518 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9520 movLeft2Result(left, LSB, result, MSB16);
9522 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9525 /* 1 <= shCount <= 7 */
9528 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9530 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9534 /*-----------------------------------------------------------------*/
9535 /* shiftLLong - shift left one long from left to result */
9536 /* offr = LSB or MSB16 */
9537 /*-----------------------------------------------------------------*/
9538 static void shiftLLong (operand *left, operand *result, int offr )
9540 int size = AOP_SIZE(result);
9541 int same = pic16_sameRegs(AOP(left),AOP(result));
9544 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9546 if (same && (offr == MSB16)) { //shift one byte
9547 for(i=size-1;i>=MSB16;i--) {
9548 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9549 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9552 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9555 if (size > LSB+offr ){
9557 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9559 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9560 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9564 if(size > MSB16+offr){
9566 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9568 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9569 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9573 if(size > MSB24+offr){
9575 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9577 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9578 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9582 if(size > MSB32+offr){
9584 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9586 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9587 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9591 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9595 /*-----------------------------------------------------------------*/
9596 /* genlshFour - shift four byte by a known amount != 0 */
9597 /*-----------------------------------------------------------------*/
9598 static void genlshFour (operand *result, operand *left, int shCount)
9602 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9603 size = AOP_SIZE(result);
9605 /* if shifting more that 3 bytes */
9606 if (shCount >= 24 ) {
9609 /* lowest order of left goes to the highest
9610 order of the destination */
9611 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9613 movLeft2Result(left, LSB, result, MSB32);
9615 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9616 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9617 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9622 /* more than two bytes */
9623 else if ( shCount >= 16 ) {
9624 /* lower order two bytes goes to higher order two bytes */
9626 /* if some more remaining */
9628 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9630 movLeft2Result(left, MSB16, result, MSB32);
9631 movLeft2Result(left, LSB, result, MSB24);
9633 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9634 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9638 /* if more than 1 byte */
9639 else if ( shCount >= 8 ) {
9640 /* lower order three bytes goes to higher order three bytes */
9644 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9646 movLeft2Result(left, LSB, result, MSB16);
9648 else{ /* size = 4 */
9650 movLeft2Result(left, MSB24, result, MSB32);
9651 movLeft2Result(left, MSB16, result, MSB24);
9652 movLeft2Result(left, LSB, result, MSB16);
9653 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9655 else if(shCount == 1)
9656 shiftLLong(left, result, MSB16);
9658 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9659 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9660 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9661 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9666 /* 1 <= shCount <= 7 */
9667 else if(shCount <= 3)
9669 shiftLLong(left, result, LSB);
9670 while(--shCount >= 1)
9671 shiftLLong(result, result, LSB);
9673 /* 3 <= shCount <= 7, optimize */
9675 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9676 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9677 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9681 /*-----------------------------------------------------------------*/
9682 /* genLeftShiftLiteral - left shifting by known count */
9683 /*-----------------------------------------------------------------*/
9684 void pic16_genLeftShiftLiteral (operand *left,
9689 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9693 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9694 pic16_freeAsmop(right,NULL,ic,TRUE);
9696 pic16_aopOp(left,ic,FALSE);
9697 pic16_aopOp(result,ic,TRUE);
9699 size = getSize(operandType(result));
9702 pic16_emitcode("; shift left ","result %d, left %d",size,
9706 /* I suppose that the left size >= result size */
9709 movLeft2Result(left, size, result, size);
9713 else if(shCount >= (size * 8))
9715 pic16_aopPut(AOP(result),zero,size);
9719 genlshOne (result,left,shCount);
9724 genlshTwo (result,left,shCount);
9728 genlshFour (result,left,shCount);
9732 pic16_freeAsmop(left,NULL,ic,TRUE);
9733 pic16_freeAsmop(result,NULL,ic,TRUE);
9736 /*-----------------------------------------------------------------*
9737 * genMultiAsm - repeat assembly instruction for size of register.
9738 * if endian == 1, then the high byte (i.e base address + size of
9739 * register) is used first else the low byte is used first;
9740 *-----------------------------------------------------------------*/
9741 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9746 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9759 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9765 #if !(USE_GENERIC_SIGNED_SHIFT)
9766 /*-----------------------------------------------------------------*/
9767 /* genLeftShift - generates code for left shifting */
9768 /*-----------------------------------------------------------------*/
9769 static void genLeftShift (iCode *ic)
9771 operand *left,*right, *result;
9774 symbol *tlbl , *tlbl1;
9777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9779 right = IC_RIGHT(ic);
9781 result = IC_RESULT(ic);
9783 pic16_aopOp(right,ic,FALSE);
9785 /* if the shift count is known then do it
9786 as efficiently as possible */
9787 if (AOP_TYPE(right) == AOP_LIT) {
9788 pic16_genLeftShiftLiteral (left,right,result,ic);
9792 /* shift count is unknown then we have to form
9793 * a loop. Get the loop count in WREG : Note: we take
9794 * only the lower order byte since shifting
9795 * more than 32 bits make no sense anyway, ( the
9796 * largest size of an object can be only 32 bits ) */
9798 pic16_aopOp(left,ic,FALSE);
9799 pic16_aopOp(result,ic,FALSE);
9801 /* now move the left to the result if they are not the
9802 * same, and if size > 1,
9803 * and if right is not same to result (!!!) -- VR */
9804 if (!pic16_sameRegs(AOP(left),AOP(result))
9805 && (AOP_SIZE(result) > 1)) {
9807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9809 size = AOP_SIZE(result);
9814 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9815 if (*l == '@' && (IS_AOP_PREG(result))) {
9817 pic16_emitcode("mov","a,%s",l);
9818 pic16_aopPut(AOP(result),"a",offset);
9822 /* we don't know if left is a literal or a register, take care -- VR */
9823 pic16_mov2f(AOP(result), AOP(left), offset);
9829 size = AOP_SIZE(result);
9831 /* if it is only one byte then */
9833 if(optimized_for_speed) {
9834 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9836 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9837 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9839 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9840 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9841 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9842 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9843 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9844 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9845 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9848 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9850 tlbl = newiTempLabel(NULL);
9853 /* this is already done, why change it? */
9854 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9855 pic16_mov2f(AOP(result), AOP(left), 0);
9859 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9860 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9861 pic16_emitpLabel(tlbl->key);
9862 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9863 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9865 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9870 if (pic16_sameRegs(AOP(left),AOP(result))) {
9872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9874 tlbl = newiTempLabel(NULL);
9875 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9876 genMultiAsm(POC_RRCF, result, size,1);
9877 pic16_emitpLabel(tlbl->key);
9878 genMultiAsm(POC_RLCF, result, size,0);
9879 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9881 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9885 //tlbl = newiTempLabel(NULL);
9887 //tlbl1 = newiTempLabel(NULL);
9889 //reAdjustPreg(AOP(result));
9891 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9892 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9893 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9895 //pic16_emitcode("add","a,acc");
9896 //pic16_aopPut(AOP(result),"a",offset++);
9898 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9900 // pic16_emitcode("rlc","a");
9901 // pic16_aopPut(AOP(result),"a",offset++);
9903 //reAdjustPreg(AOP(result));
9905 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9906 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9909 tlbl = newiTempLabel(NULL);
9910 tlbl1= newiTempLabel(NULL);
9912 size = AOP_SIZE(result);
9915 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9917 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9919 /* offset should be 0, 1 or 3 */
9921 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9923 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9925 pic16_emitpcode(POC_MOVWF, pctemp);
9928 pic16_emitpLabel(tlbl->key);
9931 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9933 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9935 pic16_emitpcode(POC_DECFSZ, pctemp);
9936 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9937 pic16_emitpLabel(tlbl1->key);
9939 pic16_popReleaseTempReg(pctemp,1);
9943 pic16_freeAsmop (right,NULL,ic,TRUE);
9944 pic16_freeAsmop(left,NULL,ic,TRUE);
9945 pic16_freeAsmop(result,NULL,ic,TRUE);
9951 #error old code (left here for reference)
9952 /*-----------------------------------------------------------------*/
9953 /* genLeftShift - generates code for left shifting */
9954 /*-----------------------------------------------------------------*/
9955 static void genLeftShift (iCode *ic)
9957 operand *left,*right, *result;
9960 symbol *tlbl , *tlbl1;
9963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9965 right = IC_RIGHT(ic);
9967 result = IC_RESULT(ic);
9969 pic16_aopOp(right,ic,FALSE);
9971 /* if the shift count is known then do it
9972 as efficiently as possible */
9973 if (AOP_TYPE(right) == AOP_LIT) {
9974 pic16_genLeftShiftLiteral (left,right,result,ic);
9978 /* shift count is unknown then we have to form
9979 a loop get the loop count in B : Note: we take
9980 only the lower order byte since shifting
9981 more that 32 bits make no sense anyway, ( the
9982 largest size of an object can be only 32 bits ) */
9985 pic16_aopOp(left,ic,FALSE);
9986 pic16_aopOp(result,ic,FALSE);
9988 /* now move the left to the result if they are not the
9990 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9991 AOP_SIZE(result) > 1) {
9993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9995 size = AOP_SIZE(result);
9998 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9999 if (*l == '@' && (IS_AOP_PREG(result))) {
10001 pic16_emitcode("mov","a,%s",l);
10002 pic16_aopPut(AOP(result),"a",offset);
10005 /* we don't know if left is a literal or a register, take care -- VR */
10006 pic16_mov2f(AOP(result), AOP(left), offset);
10012 size = AOP_SIZE(result);
10014 /* if it is only one byte then */
10016 if(optimized_for_speed) {
10017 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10019 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10020 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10022 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10023 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10024 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10025 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10026 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10027 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10028 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10033 tlbl = newiTempLabel(NULL);
10034 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10035 pic16_mov2f(AOP(result), AOP(left), 0);
10037 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10038 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10041 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10042 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10043 pic16_emitpLabel(tlbl->key);
10044 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10045 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10047 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10052 if (pic16_sameRegs(AOP(left),AOP(result))) {
10054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10056 tlbl = newiTempLabel(NULL);
10057 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10058 genMultiAsm(POC_RRCF, result, size,1);
10059 pic16_emitpLabel(tlbl->key);
10060 genMultiAsm(POC_RLCF, result, size,0);
10061 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10063 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10067 //tlbl = newiTempLabel(NULL);
10069 //tlbl1 = newiTempLabel(NULL);
10071 //reAdjustPreg(AOP(result));
10073 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10074 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10075 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10077 //pic16_emitcode("add","a,acc");
10078 //pic16_aopPut(AOP(result),"a",offset++);
10080 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10082 // pic16_emitcode("rlc","a");
10083 // pic16_aopPut(AOP(result),"a",offset++);
10085 //reAdjustPreg(AOP(result));
10087 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10088 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10091 tlbl = newiTempLabel(NULL);
10092 tlbl1= newiTempLabel(NULL);
10094 size = AOP_SIZE(result);
10097 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10099 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10101 /* offset should be 0, 1 or 3 */
10103 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10105 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10107 pic16_emitpcode(POC_MOVWF, pctemp);
10110 pic16_emitpLabel(tlbl->key);
10113 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10115 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10117 pic16_emitpcode(POC_DECFSZ, pctemp);
10118 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10119 pic16_emitpLabel(tlbl1->key);
10121 pic16_popReleaseTempReg(pctemp,1);
10125 pic16_freeAsmop (right,NULL,ic,TRUE);
10126 pic16_freeAsmop(left,NULL,ic,TRUE);
10127 pic16_freeAsmop(result,NULL,ic,TRUE);
10131 /*-----------------------------------------------------------------*/
10132 /* genrshOne - right shift a one byte quantity by known count */
10133 /*-----------------------------------------------------------------*/
10134 static void genrshOne (operand *result, operand *left,
10135 int shCount, int sign)
10137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10138 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10141 /*-----------------------------------------------------------------*/
10142 /* genrshTwo - right shift two bytes by known amount != 0 */
10143 /*-----------------------------------------------------------------*/
10144 static void genrshTwo (operand *result,operand *left,
10145 int shCount, int sign)
10147 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10148 /* if shCount >= 8 */
10149 if (shCount >= 8) {
10152 shiftR1Left2Result(left, MSB16, result, LSB,
10155 movLeft2Result(left, MSB16, result, LSB);
10157 pic16_addSign (result, 1, sign);
10160 /* 1 <= shCount <= 7 */
10162 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10165 /*-----------------------------------------------------------------*/
10166 /* shiftRLong - shift right one long from left to result */
10167 /* offl = LSB or MSB16 */
10168 /*-----------------------------------------------------------------*/
10169 static void shiftRLong (operand *left, int offl,
10170 operand *result, int sign)
10172 int size = AOP_SIZE(result);
10173 int same = pic16_sameRegs(AOP(left),AOP(result));
10175 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10177 if (same && (offl == MSB16)) { //shift one byte right
10178 for(i=MSB16;i<size;i++) {
10179 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10185 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10191 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10193 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10197 if(offl == MSB16) {
10198 /* add sign of "a" */
10199 pic16_addSign(result, MSB32, sign);
10203 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10205 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10206 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10210 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10212 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10213 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10217 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10220 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10221 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10226 /*-----------------------------------------------------------------*/
10227 /* genrshFour - shift four byte by a known amount != 0 */
10228 /*-----------------------------------------------------------------*/
10229 static void genrshFour (operand *result, operand *left,
10230 int shCount, int sign)
10232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10233 /* if shifting more that 3 bytes */
10234 if(shCount >= 24 ) {
10237 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10239 movLeft2Result(left, MSB32, result, LSB);
10241 pic16_addSign(result, MSB16, sign);
10243 else if(shCount >= 16){
10246 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10248 movLeft2Result(left, MSB24, result, LSB);
10249 movLeft2Result(left, MSB32, result, MSB16);
10251 pic16_addSign(result, MSB24, sign);
10253 else if(shCount >= 8){
10256 shiftRLong(left, MSB16, result, sign);
10257 else if(shCount == 0){
10258 movLeft2Result(left, MSB16, result, LSB);
10259 movLeft2Result(left, MSB24, result, MSB16);
10260 movLeft2Result(left, MSB32, result, MSB24);
10261 pic16_addSign(result, MSB32, sign);
10263 else{ //shcount >= 2
10264 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10265 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10266 /* the last shift is signed */
10267 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10268 pic16_addSign(result, MSB32, sign);
10271 else{ /* 1 <= shCount <= 7 */
10273 shiftRLong(left, LSB, result, sign);
10275 shiftRLong(result, LSB, result, sign);
10278 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10279 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10280 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10285 /*-----------------------------------------------------------------*/
10286 /* genRightShiftLiteral - right shifting by known count */
10287 /*-----------------------------------------------------------------*/
10288 static void genRightShiftLiteral (operand *left,
10294 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10295 int lsize,res_size;
10297 pic16_freeAsmop(right,NULL,ic,TRUE);
10299 pic16_aopOp(left,ic,FALSE);
10300 pic16_aopOp(result,ic,TRUE);
10302 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10305 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10309 lsize = pic16_getDataSize(left);
10310 res_size = pic16_getDataSize(result);
10311 /* test the LEFT size !!! */
10313 /* I suppose that the left size >= result size */
10315 assert (res_size <= lsize);
10316 while (res_size--) {
10317 pic16_mov2f (AOP(result), AOP(left), res_size);
10321 else if(shCount >= (lsize * 8)){
10323 if(res_size == 1) {
10324 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10326 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10327 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10332 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10333 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10334 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10341 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10346 switch (res_size) {
10348 genrshOne (result,left,shCount,sign);
10352 genrshTwo (result,left,shCount,sign);
10356 genrshFour (result,left,shCount,sign);
10364 pic16_freeAsmop(left,NULL,ic,TRUE);
10365 pic16_freeAsmop(result,NULL,ic,TRUE);
10368 #if !(USE_GENERIC_SIGNED_SHIFT)
10369 /*-----------------------------------------------------------------*/
10370 /* genSignedRightShift - right shift of signed number */
10371 /*-----------------------------------------------------------------*/
10372 static void genSignedRightShift (iCode *ic)
10374 operand *right, *left, *result;
10377 symbol *tlbl, *tlbl1 ;
10380 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10382 /* we do it the hard way put the shift count in b
10383 and loop thru preserving the sign */
10384 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10386 right = IC_RIGHT(ic);
10387 left = IC_LEFT(ic);
10388 result = IC_RESULT(ic);
10390 pic16_aopOp(right,ic,FALSE);
10391 pic16_aopOp(left,ic,FALSE);
10392 pic16_aopOp(result,ic,FALSE);
10395 if ( AOP_TYPE(right) == AOP_LIT) {
10396 genRightShiftLiteral (left,right,result,ic,1);
10399 /* shift count is unknown then we have to form
10400 a loop get the loop count in B : Note: we take
10401 only the lower order byte since shifting
10402 more that 32 bits make no sense anyway, ( the
10403 largest size of an object can be only 32 bits ) */
10405 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10406 //pic16_emitcode("inc","b");
10407 //pic16_freeAsmop (right,NULL,ic,TRUE);
10408 //pic16_aopOp(left,ic,FALSE);
10409 //pic16_aopOp(result,ic,FALSE);
10411 /* now move the left to the result if they are not the
10413 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10414 AOP_SIZE(result) > 1) {
10416 size = AOP_SIZE(result);
10420 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10421 if (*l == '@' && IS_AOP_PREG(result)) {
10423 pic16_emitcode("mov","a,%s",l);
10424 pic16_aopPut(AOP(result),"a",offset);
10426 pic16_aopPut(AOP(result),l,offset);
10428 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10429 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10435 /* mov the highest order bit to OVR */
10436 tlbl = newiTempLabel(NULL);
10437 tlbl1= newiTempLabel(NULL);
10439 size = AOP_SIZE(result);
10442 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10446 /* offset should be 0, 1 or 3 */
10447 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10449 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10451 pic16_emitpcode(POC_MOVWF, pctemp);
10454 pic16_emitpLabel(tlbl->key);
10456 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10457 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10460 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10463 pic16_emitpcode(POC_DECFSZ, pctemp);
10464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10465 pic16_emitpLabel(tlbl1->key);
10467 pic16_popReleaseTempReg(pctemp,1);
10469 size = AOP_SIZE(result);
10471 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10472 pic16_emitcode("rlc","a");
10473 pic16_emitcode("mov","ov,c");
10474 /* if it is only one byte then */
10476 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10478 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10479 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10480 pic16_emitcode("mov","c,ov");
10481 pic16_emitcode("rrc","a");
10482 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10483 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10484 pic16_aopPut(AOP(result),"a",0);
10488 reAdjustPreg(AOP(result));
10489 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10490 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10491 pic16_emitcode("mov","c,ov");
10493 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10495 pic16_emitcode("rrc","a");
10496 pic16_aopPut(AOP(result),"a",offset--);
10498 reAdjustPreg(AOP(result));
10499 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10500 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10505 pic16_freeAsmop(left,NULL,ic,TRUE);
10506 pic16_freeAsmop(result,NULL,ic,TRUE);
10507 pic16_freeAsmop(right,NULL,ic,TRUE);
10511 #if !(USE_GENERIC_SIGNED_SHIFT)
10512 #warning This implementation of genRightShift() is incomplete!
10513 /*-----------------------------------------------------------------*/
10514 /* genRightShift - generate code for right shifting */
10515 /*-----------------------------------------------------------------*/
10516 static void genRightShift (iCode *ic)
10518 operand *right, *left, *result;
10522 symbol *tlbl, *tlbl1 ;
10524 /* if signed then we do it the hard way preserve the
10525 sign bit moving it inwards */
10526 letype = getSpec(operandType(IC_LEFT(ic)));
10527 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10529 if (!SPEC_USIGN(letype)) {
10530 genSignedRightShift (ic);
10534 /* signed & unsigned types are treated the same : i.e. the
10535 signed is NOT propagated inwards : quoting from the
10536 ANSI - standard : "for E1 >> E2, is equivalent to division
10537 by 2**E2 if unsigned or if it has a non-negative value,
10538 otherwise the result is implementation defined ", MY definition
10539 is that the sign does not get propagated */
10541 right = IC_RIGHT(ic);
10542 left = IC_LEFT(ic);
10543 result = IC_RESULT(ic);
10545 pic16_aopOp(right,ic,FALSE);
10547 /* if the shift count is known then do it
10548 as efficiently as possible */
10549 if (AOP_TYPE(right) == AOP_LIT) {
10550 genRightShiftLiteral (left,right,result,ic, 0);
10554 /* shift count is unknown then we have to form
10555 a loop get the loop count in B : Note: we take
10556 only the lower order byte since shifting
10557 more that 32 bits make no sense anyway, ( the
10558 largest size of an object can be only 32 bits ) */
10560 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10561 pic16_emitcode("inc","b");
10562 pic16_aopOp(left,ic,FALSE);
10563 pic16_aopOp(result,ic,FALSE);
10565 /* now move the left to the result if they are not the
10567 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10568 AOP_SIZE(result) > 1) {
10570 size = AOP_SIZE(result);
10573 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10574 if (*l == '@' && IS_AOP_PREG(result)) {
10576 pic16_emitcode("mov","a,%s",l);
10577 pic16_aopPut(AOP(result),"a",offset);
10579 pic16_aopPut(AOP(result),l,offset);
10584 tlbl = newiTempLabel(NULL);
10585 tlbl1= newiTempLabel(NULL);
10586 size = AOP_SIZE(result);
10589 /* if it is only one byte then */
10592 tlbl = newiTempLabel(NULL);
10593 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10594 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10595 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10598 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10599 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10600 pic16_emitpLabel(tlbl->key);
10601 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10602 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10604 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10609 reAdjustPreg(AOP(result));
10610 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10611 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10614 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10616 pic16_emitcode("rrc","a");
10617 pic16_aopPut(AOP(result),"a",offset--);
10619 reAdjustPreg(AOP(result));
10621 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10622 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10625 pic16_freeAsmop(left,NULL,ic,TRUE);
10626 pic16_freeAsmop (right,NULL,ic,TRUE);
10627 pic16_freeAsmop(result,NULL,ic,TRUE);
10631 #if (USE_GENERIC_SIGNED_SHIFT)
10632 /*-----------------------------------------------------------------*/
10633 /* genGenericShift - generates code for left or right shifting */
10634 /*-----------------------------------------------------------------*/
10635 static void genGenericShift (iCode *ic, int isShiftLeft) {
10636 operand *left,*right, *result;
10638 int sign, signedCount;
10639 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10640 PIC_OPCODE pos_shift, neg_shift;
10644 right = IC_RIGHT(ic);
10645 left = IC_LEFT(ic);
10646 result = IC_RESULT(ic);
10648 pic16_aopOp(right,ic,FALSE);
10649 pic16_aopOp(left,ic,FALSE);
10650 pic16_aopOp(result,ic,TRUE);
10652 sign = !SPEC_USIGN(operandType (left));
10653 signedCount = !SPEC_USIGN(operandType (right));
10655 /* if the shift count is known then do it
10656 as efficiently as possible */
10657 if (AOP_TYPE(right) == AOP_LIT) {
10658 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10659 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10660 // we should modify right->aopu.aop_lit here!
10661 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10662 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10664 pic16_genLeftShiftLiteral (left,right,result,ic);
10666 genRightShiftLiteral (left,right,result,ic, sign);
10669 } // if (right is literal)
10671 /* shift count is unknown then we have to form a loop.
10672 * Note: we take only the lower order byte since shifting
10673 * more than 32 bits make no sense anyway, ( the
10674 * largest size of an object can be only 32 bits )
10675 * Note: we perform arithmetic shifts if the left operand is
10676 * signed and we do an (effective) right shift, i. e. we
10677 * shift in the sign bit from the left. */
10679 label_complete = newiTempLabel ( NULL );
10680 label_loop_pos = newiTempLabel ( NULL );
10681 label_loop_neg = NULL;
10682 label_negative = NULL;
10683 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10684 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10687 // additional labels needed
10688 label_loop_neg = newiTempLabel ( NULL );
10689 label_negative = newiTempLabel ( NULL );
10692 // copy source to result -- this will effectively truncate the left operand to the size of result!
10693 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10694 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10695 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10696 pic16_mov2f (AOP(result),AOP(left), offset);
10699 // if result is longer than left, fill with zeros (or sign)
10700 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10701 if (sign && AOP_SIZE(left) > 0) {
10702 // shift signed operand -- fill with sign
10703 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10704 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10705 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10706 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10707 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10710 // shift unsigned operand -- fill result with zeros
10711 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10712 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10715 } // if (size mismatch)
10717 pic16_mov2w (AOP(right), 0);
10718 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10719 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10722 // perform a shift by one (shift count is positive)
10723 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10724 // 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])
10725 pic16_emitpLabel (label_loop_pos->key);
10727 if (sign && (pos_shift == POC_RRCF)) {
10728 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10731 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10732 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10733 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10735 // perform a shift by one (shift count is positive)
10736 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10737 // 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])
10738 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10739 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10741 pic16_emitpLabel (label_loop_pos->key);
10742 if (sign && (pos_shift == POC_RRCF)) {
10743 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10746 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10747 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10748 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10749 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10753 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10755 pic16_emitpLabel (label_negative->key);
10756 // perform a shift by -1 (shift count is negative)
10757 // 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)
10759 pic16_emitpLabel (label_loop_neg->key);
10760 if (sign && (neg_shift == POC_RRCF)) {
10761 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10764 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10765 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10766 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10767 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10768 } // if (signedCount)
10770 pic16_emitpLabel (label_complete->key);
10773 pic16_freeAsmop (right,NULL,ic,TRUE);
10774 pic16_freeAsmop(left,NULL,ic,TRUE);
10775 pic16_freeAsmop(result,NULL,ic,TRUE);
10778 static void genLeftShift (iCode *ic) {
10779 genGenericShift (ic, 1);
10782 static void genRightShift (iCode *ic) {
10783 genGenericShift (ic, 0);
10788 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10789 void pic16_loadFSR0(operand *op, int lit)
10791 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10792 if (AOP_TYPE(op) == AOP_LIT) {
10793 /* handle 12 bit integers correctly */
10794 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10795 if ((val & 0x0fff) != val) {
10796 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10797 val, (val & 0x0fff) );
10800 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10802 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10805 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10806 // set up FSR0 with address of result
10807 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10808 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10812 /*----------------------------------------------------------------*/
10813 /* pic16_derefPtr - move one byte from the location ptr points to */
10814 /* to WREG (doWrite == 0) or one byte from WREG */
10815 /* to the location ptr points to (doWrite != 0) */
10816 /*----------------------------------------------------------------*/
10817 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10819 if (!IS_PTR(operandType(ptr)))
10821 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10822 else pic16_mov2w (AOP(ptr), 0);
10826 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10827 /* We might determine pointer type right here: */
10828 p_type = DCL_TYPE(operandType(ptr));
10833 if (!fsr0_setup || !*fsr0_setup)
10835 pic16_loadFSR0( ptr, 0 );
10836 if (fsr0_setup) *fsr0_setup = 1;
10839 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10841 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10845 if (AOP(ptr)->aopu.aop_reg[2]) {
10846 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10847 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10848 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10849 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10850 pic16_mov2w(AOP(ptr), 2);
10851 pic16_callGenericPointerRW(doWrite, 1);
10853 // data pointer (just 2 byte given)
10854 if (!fsr0_setup || !*fsr0_setup)
10856 pic16_loadFSR0( ptr, 0 );
10857 if (fsr0_setup) *fsr0_setup = 1;
10860 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10862 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10867 assert (0 && "invalid pointer type specified");
10872 /*-----------------------------------------------------------------*/
10873 /* genUnpackBits - generates code for unpacking bits */
10874 /*-----------------------------------------------------------------*/
10875 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10878 sym_link *etype, *letype;
10879 int blen=0, bstr=0;
10884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10885 etype = getSpec(operandType(result));
10886 letype = getSpec(operandType(left));
10888 // if(IS_BITFIELD(etype)) {
10889 blen = SPEC_BLEN(etype);
10890 bstr = SPEC_BSTR(etype);
10893 lbstr = SPEC_BSTR( letype );
10895 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10896 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10899 if((blen == 1) && (bstr < 8)
10900 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10901 /* it is a single bit, so use the appropriate bit instructions */
10902 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10904 same = pic16_sameRegs(AOP(left),AOP(result));
10905 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10906 pic16_emitpcode(POC_CLRF, op);
10908 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10909 /* workaround to reduce the extra lfsr instruction */
10910 pic16_emitpcode(POC_BTFSC,
10911 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10913 assert (PIC_IS_DATA_PTR (operandType(left)));
10914 pic16_loadFSR0 (left, 0);
10915 pic16_emitpcode(POC_BTFSC,
10916 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10919 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10920 /* unsigned bitfields result in either 0 or 1 */
10921 pic16_emitpcode(POC_INCF, op);
10923 /* signed bitfields result in either 0 or -1 */
10924 pic16_emitpcode(POC_DECF, op);
10927 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10930 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10936 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10937 // access symbol directly
10938 pic16_mov2w (AOP(left), 0);
10940 pic16_derefPtr (left, ptype, 0, NULL);
10943 /* if we have bitdisplacement then it fits */
10944 /* into this byte completely or if length is */
10945 /* less than a byte */
10946 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10948 /* shift right acc */
10951 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10952 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10954 /* VR -- normally I would use the following, but since we use the hack,
10955 * to avoid the masking from AccRsh, why not mask it right now? */
10958 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10961 /* extend signed bitfields to 8 bits */
10962 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10964 assert (blen + bstr > 0);
10965 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10966 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10969 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10971 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10975 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10976 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10977 exit(EXIT_FAILURE);
10983 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10985 int size, offset = 0, leoffset=0 ;
10987 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10988 pic16_aopOp(result, ic, TRUE);
10992 size = AOP_SIZE(result);
10993 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10997 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10998 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10999 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11004 if(AOP(left)->aopu.pcop->type == PO_DIR)
11005 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11007 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11010 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11012 // pic16_DumpOp("(result)",result);
11013 if(is_LitAOp(AOP(result))) {
11014 pic16_mov2w(AOP(left), offset); // patch 8
11015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11017 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11018 pic16_popGet(AOP(left), offset), //patch 8
11019 pic16_popGet(AOP(result), offset)));
11027 pic16_freeAsmop(result,NULL,ic,TRUE);
11032 /*-----------------------------------------------------------------*/
11033 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11034 /*-----------------------------------------------------------------*/
11035 static void genNearPointerGet (operand *left,
11039 // asmop *aop = NULL;
11040 //regs *preg = NULL ;
11041 sym_link *rtype, *retype;
11042 sym_link *ltype, *letype;
11046 rtype = operandType(result);
11047 retype= getSpec(rtype);
11048 ltype = operandType(left);
11049 letype= getSpec(ltype);
11051 pic16_aopOp(left,ic,FALSE);
11053 // pic16_DumpOp("(left)",left);
11054 // pic16_DumpOp("(result)",result);
11056 /* if left is rematerialisable and
11057 * result is not bit variable type and
11058 * the left is pointer to data space i.e
11059 * lower 128 bytes of space */
11061 if (AOP_TYPE(left) == AOP_PCODE
11062 && !IS_BITFIELD(retype)
11063 && DCL_TYPE(ltype) == POINTER) {
11065 genDataPointerGet (left,result,ic);
11066 pic16_freeAsmop(left, NULL, ic, TRUE);
11070 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11071 pic16_aopOp (result,ic,TRUE);
11073 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11076 if(IS_BITFIELD( retype )
11077 && (SPEC_BLEN(operandType(result))==1)
11081 int bitstrt, bytestrt;
11083 /* if this is bitfield of size 1, see if we are checking the value
11084 * of a single bit in an if-statement,
11085 * if yes, then don't generate usual code, but execute the
11086 * genIfx directly -- VR */
11090 /* CHECK: if next iCode is IFX
11091 * and current result operand is nextic's conditional operand
11092 * and current result operand live ranges ends at nextic's key number
11094 if((nextic->op == IFX)
11095 && (result == IC_COND(nextic))
11096 && (OP_LIVETO(result) == nextic->seq)
11097 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11099 /* everything is ok then */
11100 /* find a way to optimize the genIfx iCode */
11102 bytestrt = SPEC_BSTR(operandType(result))/8;
11103 bitstrt = SPEC_BSTR(operandType(result))%8;
11105 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11107 genIfxpCOpJump(nextic, jop);
11109 pic16_freeAsmop(left, NULL, ic, TRUE);
11110 pic16_freeAsmop(result, NULL, ic, TRUE);
11116 /* if bitfield then unpack the bits */
11117 if (IS_BITFIELD(letype))
11118 genUnpackBits (result, left, NULL, POINTER);
11120 /* we have can just get the values */
11121 int size = AOP_SIZE(result);
11124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11126 pic16_loadFSR0( left, 0 );
11130 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11131 pic16_popGet(AOP(result), offset++)));
11133 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11134 pic16_popGet(AOP(result), offset++)));
11140 /* now some housekeeping stuff */
11142 /* we had to allocate for this iCode */
11143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11144 pic16_freeAsmop(NULL,aop,ic,TRUE);
11146 /* we did not allocate which means left
11147 * already in a pointer register, then
11148 * if size > 0 && this could be used again
11149 * we have to point it back to where it
11151 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11152 if (AOP_SIZE(result) > 1
11153 && !OP_SYMBOL(left)->remat
11154 && ( OP_SYMBOL(left)->liveTo > ic->seq
11156 // int size = AOP_SIZE(result) - 1;
11158 // pic16_emitcode("dec","%s",rname);
11164 pic16_freeAsmop(left,NULL,ic,TRUE);
11165 pic16_freeAsmop(result,NULL,ic,TRUE);
11168 /*-----------------------------------------------------------------*/
11169 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11170 /*-----------------------------------------------------------------*/
11171 static void genPagedPointerGet (operand *left,
11176 regs *preg = NULL ;
11178 sym_link *rtype, *retype;
11180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11182 rtype = operandType(result);
11183 retype= getSpec(rtype);
11185 pic16_aopOp(left,ic,FALSE);
11187 /* if the value is already in a pointer register
11188 then don't need anything more */
11189 if (!AOP_INPREG(AOP(left))) {
11190 /* otherwise get a free pointer register */
11192 preg = getFreePtr(ic,&aop,FALSE);
11193 pic16_emitcode("mov","%s,%s",
11195 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11196 rname = preg->name ;
11198 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11200 pic16_freeAsmop(left,NULL,ic,TRUE);
11201 pic16_aopOp (result,ic,TRUE);
11203 /* if bitfield then unpack the bits */
11204 if (IS_BITFIELD(retype))
11205 genUnpackBits (result,left,rname,PPOINTER);
11207 /* we have can just get the values */
11208 int size = AOP_SIZE(result);
11213 pic16_emitcode("movx","a,@%s",rname);
11214 pic16_aopPut(AOP(result),"a",offset);
11219 pic16_emitcode("inc","%s",rname);
11223 /* now some housekeeping stuff */
11225 /* we had to allocate for this iCode */
11226 pic16_freeAsmop(NULL,aop,ic,TRUE);
11228 /* we did not allocate which means left
11229 already in a pointer register, then
11230 if size > 0 && this could be used again
11231 we have to point it back to where it
11233 if (AOP_SIZE(result) > 1 &&
11234 !OP_SYMBOL(left)->remat &&
11235 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11237 int size = AOP_SIZE(result) - 1;
11239 pic16_emitcode("dec","%s",rname);
11244 pic16_freeAsmop(result,NULL,ic,TRUE);
11250 /* This code is not adjusted to PIC16 and fails utterly.
11251 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11253 /*-----------------------------------------------------------------*/
11254 /* genFarPointerGet - gget value from far space */
11255 /*-----------------------------------------------------------------*/
11256 static void genFarPointerGet (operand *left,
11257 operand *result, iCode *ic)
11260 sym_link *retype = getSpec(operandType(result));
11262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11264 pic16_aopOp(left,ic,FALSE);
11266 /* if the operand is already in dptr
11267 then we do nothing else we move the value to dptr */
11268 if (AOP_TYPE(left) != AOP_STR) {
11269 /* if this is remateriazable */
11270 if (AOP_TYPE(left) == AOP_IMMD)
11271 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11272 else { /* we need to get it byte by byte */
11273 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11274 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11275 if (options.model == MODEL_FLAT24)
11277 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11281 /* so dptr know contains the address */
11282 pic16_freeAsmop(left,NULL,ic,TRUE);
11283 pic16_aopOp(result,ic,TRUE);
11285 /* if bit then unpack */
11286 if (IS_BITFIELD(retype))
11287 genUnpackBits(result,left,"dptr",FPOINTER);
11289 size = AOP_SIZE(result);
11293 pic16_emitcode("movx","a,@dptr");
11294 pic16_aopPut(AOP(result),"a",offset++);
11296 pic16_emitcode("inc","dptr");
11300 pic16_freeAsmop(result,NULL,ic,TRUE);
11305 /*-----------------------------------------------------------------*/
11306 /* genCodePointerGet - get value from code space */
11307 /*-----------------------------------------------------------------*/
11308 static void genCodePointerGet (operand *left,
11309 operand *result, iCode *ic)
11312 sym_link *retype = getSpec(operandType(result));
11314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11316 pic16_aopOp(left,ic,FALSE);
11318 /* if the operand is already in dptr
11319 then we do nothing else we move the value to dptr */
11320 if (AOP_TYPE(left) != AOP_STR) {
11321 /* if this is remateriazable */
11322 if (AOP_TYPE(left) == AOP_IMMD)
11323 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11324 else { /* we need to get it byte by byte */
11325 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11326 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11327 if (options.model == MODEL_FLAT24)
11329 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11333 /* so dptr know contains the address */
11334 pic16_freeAsmop(left,NULL,ic,TRUE);
11335 pic16_aopOp(result,ic,FALSE);
11337 /* if bit then unpack */
11338 if (IS_BITFIELD(retype))
11339 genUnpackBits(result,left,"dptr",CPOINTER);
11341 size = AOP_SIZE(result);
11345 pic16_emitcode("clr","a");
11346 pic16_emitcode("movc","a,@a+dptr");
11347 pic16_aopPut(AOP(result),"a",offset++);
11349 pic16_emitcode("inc","dptr");
11353 pic16_freeAsmop(result,NULL,ic,TRUE);
11358 /*-----------------------------------------------------------------*/
11359 /* genGenPointerGet - gget value from generic pointer space */
11360 /*-----------------------------------------------------------------*/
11361 static void genGenPointerGet (operand *left,
11362 operand *result, iCode *ic)
11364 int size, offset, lit;
11365 sym_link *retype = getSpec(operandType(result));
11367 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11368 pic16_aopOp(left,ic,FALSE);
11369 pic16_aopOp(result,ic,FALSE);
11370 size = AOP_SIZE(result);
11372 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11374 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11376 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11377 // load FSR0 from immediate
11378 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11380 // pic16_loadFSR0( left );
11385 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11387 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11394 else { /* we need to get it byte by byte */
11395 // set up FSR0 with address from left
11396 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11397 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11405 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11412 /* if bit then unpack */
11413 if (IS_BITFIELD(retype))
11414 genUnpackBits(result,left,"BAD",GPOINTER);
11417 pic16_freeAsmop(left,NULL,ic,TRUE);
11418 pic16_freeAsmop(result,NULL,ic,TRUE);
11424 /*-----------------------------------------------------------------*/
11425 /* genGenPointerGet - gget value from generic pointer space */
11426 /*-----------------------------------------------------------------*/
11427 static void genGenPointerGet (operand *left,
11428 operand *result, iCode *ic)
11430 int size, offset, lit;
11431 sym_link *letype = getSpec(operandType(left));
11433 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11434 pic16_aopOp(left,ic,FALSE);
11435 pic16_aopOp(result,ic,TRUE);
11436 size = AOP_SIZE(result);
11438 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11440 /* if bit then unpack */
11441 if (IS_BITFIELD(letype)) {
11442 genUnpackBits(result,left,"BAD",GPOINTER);
11446 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11448 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11449 // load FSR0 from immediate
11450 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11452 werror(W_POSSBUG2, __FILE__, __LINE__);
11457 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11466 } else { /* we need to get it byte by byte */
11468 /* set up WREG:PRODL:FSR0L with address from left */
11469 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11470 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11471 pic16_mov2w(AOP(left), 2);
11472 pic16_callGenericPointerRW(0, size);
11474 assignResultValue(result, size, 1);
11480 pic16_freeAsmop(left,NULL,ic,TRUE);
11481 pic16_freeAsmop(result,NULL,ic,TRUE);
11484 /*-----------------------------------------------------------------*/
11485 /* genConstPointerGet - get value from const generic pointer space */
11486 /*-----------------------------------------------------------------*/
11487 static void genConstPointerGet (operand *left,
11488 operand *result, iCode *ic)
11490 //sym_link *retype = getSpec(operandType(result));
11491 // symbol *albl = newiTempLabel(NULL); // patch 15
11492 // symbol *blbl = newiTempLabel(NULL); //
11493 // PIC_OPCODE poc; // patch 15
11497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11498 pic16_aopOp(left,ic,FALSE);
11499 pic16_aopOp(result,ic,TRUE);
11500 size = AOP_SIZE(result);
11502 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11504 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11506 // set up table pointer
11507 if( (AOP_TYPE(left) == AOP_PCODE)
11508 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11509 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11511 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11512 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11513 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11514 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11515 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11516 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11518 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11519 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11520 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11524 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11525 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11529 pic16_freeAsmop(left,NULL,ic,TRUE);
11530 pic16_freeAsmop(result,NULL,ic,TRUE);
11534 /*-----------------------------------------------------------------*/
11535 /* genPointerGet - generate code for pointer get */
11536 /*-----------------------------------------------------------------*/
11537 static void genPointerGet (iCode *ic)
11539 operand *left, *result ;
11540 sym_link *type, *etype;
11545 left = IC_LEFT(ic);
11546 result = IC_RESULT(ic) ;
11548 /* depending on the type of pointer we need to
11549 move it to the correct pointer register */
11550 type = operandType(left);
11551 etype = getSpec(type);
11554 if (IS_PTR_CONST(type))
11556 if (IS_CODEPTR(type))
11558 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11560 /* if left is of type of pointer then it is simple */
11561 if (IS_PTR(type) && !IS_FUNC(type->next))
11562 p_type = DCL_TYPE(type);
11564 /* we have to go by the storage class */
11565 p_type = PTR_TYPE(SPEC_OCLS(etype));
11567 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11569 if (SPEC_OCLS(etype)->codesp ) {
11570 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11571 //p_type = CPOINTER ;
11573 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11574 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11575 /*p_type = FPOINTER ;*/
11577 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11578 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11579 /* p_type = PPOINTER; */
11581 if (SPEC_OCLS(etype) == idata ) {
11582 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11583 /* p_type = IPOINTER; */
11585 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11586 /* p_type = POINTER ; */
11590 /* now that we have the pointer type we assign
11591 the pointer values */
11596 genNearPointerGet (left,result,ic);
11600 genPagedPointerGet(left,result,ic);
11604 /* PICs do not support FAR pointers... */
11605 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11607 genFarPointerGet (left,result,ic);
11612 genConstPointerGet (left,result,ic);
11613 //pic16_emitcodePointerGet (left,result,ic);
11618 if (IS_PTR_CONST(type))
11619 genConstPointerGet (left,result,ic);
11622 genGenPointerGet (left,result,ic);
11626 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11627 "genPointerGet: illegal pointer type");
11632 /*-----------------------------------------------------------------*/
11633 /* genPackBits - generates code for packed bit storage */
11634 /*-----------------------------------------------------------------*/
11635 static void genPackBits (sym_link *etype , operand *result,
11637 char *rname, int p_type)
11643 int shifted_and_masked = 0;
11644 unsigned long lit = (unsigned long)-1;
11647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11648 blen = SPEC_BLEN(etype);
11649 bstr = SPEC_BSTR(etype);
11651 retype = getSpec(operandType(right));
11653 if(AOP_TYPE(right) == AOP_LIT) {
11654 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11656 if((blen == 1) && (bstr < 8)) {
11657 /* it is a single bit, so use the appropriate bit instructions */
11659 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11661 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11662 /* workaround to reduce the extra lfsr instruction */
11664 pic16_emitpcode(POC_BSF,
11665 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11667 pic16_emitpcode(POC_BCF,
11668 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11671 if (PIC_IS_DATA_PTR(operandType(result))) {
11672 pic16_loadFSR0(result, 0);
11673 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11674 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11676 /* get old value */
11677 pic16_derefPtr (result, p_type, 0, NULL);
11678 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11679 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11680 /* write back new value */
11681 pic16_derefPtr (result, p_type, 1, NULL);
11687 /* IORLW below is more efficient */
11688 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11689 lit = (lit & ((1UL << blen) - 1)) << bstr;
11690 shifted_and_masked = 1;
11693 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11694 && IS_BITFIELD(retype)
11695 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11699 rblen = SPEC_BLEN( retype );
11700 rbstr = SPEC_BSTR( retype );
11702 if(IS_BITFIELD(etype)) {
11703 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11704 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11706 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11709 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11711 if(IS_BITFIELD(etype)) {
11712 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11714 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11717 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11721 /* move right to W */
11722 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11725 /* if the bit length is less than or */
11726 /* it exactly fits a byte then */
11727 if((shCnt=SPEC_BSTR(etype))
11728 || SPEC_BLEN(etype) <= 8 ) {
11729 int fsr0_setup = 0;
11731 if (blen != 8 || (bstr % 8) != 0) {
11732 // we need to combine the value with the old value
11733 if(!shifted_and_masked)
11735 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11737 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11738 SPEC_BSTR(etype), SPEC_BLEN(etype));
11740 /* shift left acc, do NOT mask the result again */
11743 /* using PRODH as a temporary register here */
11744 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11747 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11748 || IS_DIRECT(result)) {
11749 /* access symbol directly */
11750 pic16_mov2w (AOP(result), 0);
11752 /* get old value */
11753 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11756 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11757 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11758 (unsigned char)(0xff >> (8-bstr))) ));
11759 if (!shifted_and_masked) {
11760 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11762 /* We have the shifted and masked (literal) right value in `lit' */
11764 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11766 } else { // if (blen == 8 && (bstr % 8) == 0)
11767 if (shifted_and_masked) {
11768 // move right (literal) to WREG (only case where right is not yet in WREG)
11769 pic16_mov2w(AOP(right), (bstr / 8));
11773 /* write new value back */
11774 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11775 || IS_DIRECT(result)) {
11776 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11778 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11787 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11788 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11789 exit(EXIT_FAILURE);
11793 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11794 rLen = SPEC_BLEN(etype)-8;
11796 /* now generate for lengths greater than one byte */
11800 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11806 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11812 pic16_emitcode("movx","@dptr,a");
11817 DEBUGpic16_emitcode(";lcall","__gptrput");
11825 pic16_mov2w(AOP(right), offset++);
11828 /* last last was not complete */
11830 /* save the byte & read byte */
11833 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11834 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11839 pic16_emitcode ("mov","b,a");
11840 pic16_emitcode("movx","a,@dptr");
11844 pic16_emitcode ("push","b");
11845 pic16_emitcode ("push","acc");
11846 pic16_emitcode ("lcall","__gptrget");
11847 pic16_emitcode ("pop","b");
11853 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11854 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11855 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11856 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11857 // pic16_emitcode ("orl","a,b");
11860 // if (p_type == GPOINTER)
11861 // pic16_emitcode("pop","b");
11866 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11867 // pic16_emitcode("mov","@%s,a",rname);
11871 pic16_emitcode("movx","@dptr,a");
11875 DEBUGpic16_emitcode(";lcall","__gptrput");
11882 // pic16_freeAsmop(right, NULL, ic, TRUE);
11885 /*-----------------------------------------------------------------*/
11886 /* genDataPointerSet - remat pointer to data space */
11887 /*-----------------------------------------------------------------*/
11888 static void genDataPointerSet(operand *right,
11892 int size, offset = 0, resoffset=0 ;
11894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11895 pic16_aopOp(right,ic,FALSE);
11897 size = AOP_SIZE(right);
11899 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11902 if ( AOP_TYPE(result) == AOP_PCODE) {
11903 fprintf(stderr,"genDataPointerSet %s, %d\n",
11904 AOP(result)->aopu.pcop->name,
11905 (AOP(result)->aopu.pcop->type == PO_DIR)?
11906 PCOR(AOP(result)->aopu.pcop)->instance:
11907 PCOI(AOP(result)->aopu.pcop)->offset);
11911 if(AOP(result)->aopu.pcop->type == PO_DIR)
11912 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11915 if (AOP_TYPE(right) == AOP_LIT) {
11916 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11917 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11919 pic16_mov2w(AOP(right), offset);
11920 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11926 pic16_freeAsmop(right,NULL,ic,TRUE);
11931 /*-----------------------------------------------------------------*/
11932 /* genNearPointerSet - pic16_emitcode for near pointer put */
11933 /*-----------------------------------------------------------------*/
11934 static void genNearPointerSet (operand *right,
11940 sym_link *ptype = operandType(result);
11941 sym_link *resetype;
11943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11944 retype= getSpec(operandType(right));
11945 resetype = getSpec(operandType(result));
11947 pic16_aopOp(result,ic,FALSE);
11949 /* if the result is rematerializable &
11950 * in data space & not a bit variable */
11952 /* and result is not a bit variable */
11953 if (AOP_TYPE(result) == AOP_PCODE
11954 // && AOP_TYPE(result) == AOP_IMMD
11955 && DCL_TYPE(ptype) == POINTER
11956 && !IS_BITFIELD(retype)
11957 && !IS_BITFIELD(resetype)) {
11959 genDataPointerSet (right,result,ic);
11960 pic16_freeAsmop(result,NULL,ic,TRUE);
11964 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11965 pic16_aopOp(right,ic,FALSE);
11966 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11968 /* if bitfield then unpack the bits */
11969 if (IS_BITFIELD(resetype)) {
11970 genPackBits (resetype, result, right, NULL, POINTER);
11972 /* we have can just get the values */
11973 int size = AOP_SIZE(right);
11976 pic16_loadFSR0(result, 0);
11978 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11980 if (is_LitOp(right)) {
11981 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11983 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11985 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11987 } else { // no literal
11989 pic16_emitpcode(POC_MOVFF,
11990 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11991 pic16_popCopyReg(&pic16_pc_postinc0)));
11993 pic16_emitpcode(POC_MOVFF,
11994 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11995 pic16_popCopyReg(&pic16_pc_indf0)));
12003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12004 /* now some housekeeping stuff */
12006 /* we had to allocate for this iCode */
12007 pic16_freeAsmop(NULL,aop,ic,TRUE);
12009 /* we did not allocate which means left
12010 * already in a pointer register, then
12011 * if size > 0 && this could be used again
12012 * we have to point it back to where it
12014 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12015 if (AOP_SIZE(right) > 1
12016 && !OP_SYMBOL(result)->remat
12017 && ( OP_SYMBOL(result)->liveTo > ic->seq
12020 int size = AOP_SIZE(right) - 1;
12023 pic16_emitcode("decf","fsr0,f");
12024 //pic16_emitcode("dec","%s",rname);
12028 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12031 pic16_freeAsmop(right,NULL,ic,TRUE);
12032 pic16_freeAsmop(result,NULL,ic,TRUE);
12035 /*-----------------------------------------------------------------*/
12036 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12037 /*-----------------------------------------------------------------*/
12038 static void genPagedPointerSet (operand *right,
12043 regs *preg = NULL ;
12047 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12049 retype= getSpec(operandType(right));
12051 pic16_aopOp(result,ic,FALSE);
12053 /* if the value is already in a pointer register
12054 then don't need anything more */
12055 if (!AOP_INPREG(AOP(result))) {
12056 /* otherwise get a free pointer register */
12058 preg = getFreePtr(ic,&aop,FALSE);
12059 pic16_emitcode("mov","%s,%s",
12061 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12062 rname = preg->name ;
12064 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12066 pic16_freeAsmop(result,NULL,ic,TRUE);
12067 pic16_aopOp (right,ic,FALSE);
12069 /* if bitfield then unpack the bits */
12070 if (IS_BITFIELD(retype))
12071 genPackBits (retype,result,right,rname,PPOINTER);
12073 /* we have can just get the values */
12074 int size = AOP_SIZE(right);
12078 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12081 pic16_emitcode("movx","@%s,a",rname);
12084 pic16_emitcode("inc","%s",rname);
12090 /* now some housekeeping stuff */
12092 /* we had to allocate for this iCode */
12093 pic16_freeAsmop(NULL,aop,ic,TRUE);
12095 /* we did not allocate which means left
12096 already in a pointer register, then
12097 if size > 0 && this could be used again
12098 we have to point it back to where it
12100 if (AOP_SIZE(right) > 1 &&
12101 !OP_SYMBOL(result)->remat &&
12102 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12104 int size = AOP_SIZE(right) - 1;
12106 pic16_emitcode("dec","%s",rname);
12111 pic16_freeAsmop(right,NULL,ic,TRUE);
12117 /* This code is not adjusted to PIC16 and fails utterly...
12118 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12120 /*-----------------------------------------------------------------*/
12121 /* genFarPointerSet - set value from far space */
12122 /*-----------------------------------------------------------------*/
12123 static void genFarPointerSet (operand *right,
12124 operand *result, iCode *ic)
12127 sym_link *retype = getSpec(operandType(right));
12129 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12130 pic16_aopOp(result,ic,FALSE);
12132 /* if the operand is already in dptr
12133 then we do nothing else we move the value to dptr */
12134 if (AOP_TYPE(result) != AOP_STR) {
12135 /* if this is remateriazable */
12136 if (AOP_TYPE(result) == AOP_IMMD)
12137 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12138 else { /* we need to get it byte by byte */
12139 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12140 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12141 if (options.model == MODEL_FLAT24)
12143 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12147 /* so dptr know contains the address */
12148 pic16_freeAsmop(result,NULL,ic,TRUE);
12149 pic16_aopOp(right,ic,FALSE);
12151 /* if bit then unpack */
12152 if (IS_BITFIELD(retype))
12153 genPackBits(retype,result,right,"dptr",FPOINTER);
12155 size = AOP_SIZE(right);
12159 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12161 pic16_emitcode("movx","@dptr,a");
12163 pic16_emitcode("inc","dptr");
12167 pic16_freeAsmop(right,NULL,ic,TRUE);
12171 /*-----------------------------------------------------------------*/
12172 /* genGenPointerSet - set value from generic pointer space */
12173 /*-----------------------------------------------------------------*/
12175 static void genGenPointerSet (operand *right,
12176 operand *result, iCode *ic)
12178 int i, size, offset, lit;
12179 sym_link *retype = getSpec(operandType(right));
12181 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12183 pic16_aopOp(result,ic,FALSE);
12184 pic16_aopOp(right,ic,FALSE);
12185 size = AOP_SIZE(right);
12188 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12190 /* if the operand is already in dptr
12191 then we do nothing else we move the value to dptr */
12192 if (AOP_TYPE(result) != AOP_STR) {
12193 /* if this is remateriazable */
12194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12195 // WARNING: anythig until "else" is untested!
12196 if (AOP_TYPE(result) == AOP_IMMD) {
12197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12198 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12199 // load FSR0 from immediate
12200 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12204 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12206 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12212 else { /* we need to get it byte by byte */
12213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12214 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12216 // set up FSR0 with address of result
12217 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12218 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12220 /* hack hack! see if this the FSR. If so don't load W */
12221 if(AOP_TYPE(right) != AOP_ACC) {
12223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12225 if(AOP_TYPE(right) == AOP_LIT)
12228 // note: pic16_popGet handles sign extension
12229 for(i=0;i<size;i++) {
12230 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12232 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12234 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12239 for(i=0;i<size;i++) {
12241 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12242 pic16_popCopyReg(&pic16_pc_postinc0)));
12244 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12245 pic16_popCopyReg(&pic16_pc_indf0)));
12251 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12252 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12254 } // if (AOP_TYPE(result) != AOP_IMMD)
12256 } // if (AOP_TYPE(result) != AOP_STR)
12257 /* so dptr know contains the address */
12260 /* if bit then unpack */
12261 if (IS_BITFIELD(retype))
12262 genPackBits(retype,result,right,"dptr",GPOINTER);
12264 size = AOP_SIZE(right);
12267 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12269 // set up FSR0 with address of result
12270 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12271 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12274 if (AOP_TYPE(right) == AOP_LIT) {
12275 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12277 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12279 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12281 } else { // no literal
12283 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12285 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12293 pic16_freeAsmop(right,NULL,ic,TRUE);
12294 pic16_freeAsmop(result,NULL,ic,TRUE);
12298 static void genGenPointerSet (operand *right,
12299 operand *result, iCode *ic)
12302 sym_link *retype = getSpec(operandType(result));
12304 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12306 pic16_aopOp(result,ic,FALSE);
12307 pic16_aopOp(right,ic,FALSE);
12308 size = AOP_SIZE(right);
12310 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12313 /* if bit then unpack */
12314 if (IS_BITFIELD(retype)) {
12315 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12316 genPackBits(retype,result,right,"dptr",GPOINTER);
12320 size = AOP_SIZE(right);
12322 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12325 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12327 /* value of right+0 is placed on stack, which will be retrieved
12328 * by the support function thus restoring the stack. The important
12329 * thing is that there is no need to manually restore stack pointer
12331 pushaop(AOP(right), 0);
12332 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12333 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12334 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12335 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12337 /* load address to write to in WREG:FSR0H:FSR0L */
12338 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12339 pic16_popCopyReg(&pic16_pc_fsr0l)));
12340 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12341 pic16_popCopyReg(&pic16_pc_prodl)));
12342 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12344 pic16_callGenericPointerRW(1, size);
12347 pic16_freeAsmop(right,NULL,ic,TRUE);
12348 pic16_freeAsmop(result,NULL,ic,TRUE);
12351 /*-----------------------------------------------------------------*/
12352 /* genPointerSet - stores the value into a pointer location */
12353 /*-----------------------------------------------------------------*/
12354 static void genPointerSet (iCode *ic)
12356 operand *right, *result ;
12357 sym_link *type, *etype;
12362 right = IC_RIGHT(ic);
12363 result = IC_RESULT(ic) ;
12365 /* depending on the type of pointer we need to
12366 move it to the correct pointer register */
12367 type = operandType(result);
12368 etype = getSpec(type);
12370 /* if left is of type of pointer then it is simple */
12371 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12372 p_type = DCL_TYPE(type);
12375 /* we have to go by the storage class */
12376 p_type = PTR_TYPE(SPEC_OCLS(etype));
12378 /* if (SPEC_OCLS(etype)->codesp ) { */
12379 /* p_type = CPOINTER ; */
12382 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12383 /* p_type = FPOINTER ; */
12385 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12386 /* p_type = PPOINTER ; */
12388 /* if (SPEC_OCLS(etype) == idata ) */
12389 /* p_type = IPOINTER ; */
12391 /* p_type = POINTER ; */
12394 /* now that we have the pointer type we assign
12395 the pointer values */
12400 genNearPointerSet (right,result,ic);
12404 genPagedPointerSet (right,result,ic);
12408 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12410 genFarPointerSet (right,result,ic);
12415 genGenPointerSet (right,result,ic);
12419 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12420 "genPointerSet: illegal pointer type");
12424 /*-----------------------------------------------------------------*/
12425 /* genIfx - generate code for Ifx statement */
12426 /*-----------------------------------------------------------------*/
12427 static void genIfx (iCode *ic, iCode *popIc)
12429 operand *cond = IC_COND(ic);
12434 pic16_aopOp(cond,ic,FALSE);
12436 /* get the value into acc */
12437 if (AOP_TYPE(cond) != AOP_CRY)
12438 pic16_toBoolean(cond);
12441 /* the result is now in the accumulator */
12442 pic16_freeAsmop(cond,NULL,ic,TRUE);
12444 /* if there was something to be popped then do it */
12448 /* if the condition is a bit variable */
12449 if (isbit && IS_ITEMP(cond) &&
12451 genIfxJump(ic,"c");
12452 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12454 if (isbit && !IS_ITEMP(cond))
12455 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12457 genIfxJump(ic,"a");
12462 /*-----------------------------------------------------------------*/
12463 /* genAddrOf - generates code for address of */
12464 /*-----------------------------------------------------------------*/
12465 static void genAddrOf (iCode *ic)
12467 operand *result, *left;
12469 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12470 pCodeOp *pcop0, *pcop1, *pcop2;
12474 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12476 sym = OP_SYMBOL( IC_LEFT(ic) );
12479 /* get address of symbol on stack */
12480 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12482 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12483 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12486 // operands on stack are accessible via "FSR2 + index" with index
12487 // starting at 2 for arguments and growing from 0 downwards for
12488 // local variables (index == 0 is not assigned so we add one here)
12490 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12493 assert (soffs < 0);
12497 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12498 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12499 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12500 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12501 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12502 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12503 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12509 // if(pic16_debug_verbose) {
12510 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12511 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12514 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12515 size = AOP_SIZE(IC_RESULT(ic));
12517 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12518 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12519 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12522 pic16_emitpcode(POC_MOVLW, pcop0);
12523 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12524 pic16_emitpcode(POC_MOVLW, pcop1);
12525 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12526 pic16_emitpcode(POC_MOVLW, pcop2);
12527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12530 pic16_emitpcode(POC_MOVLW, pcop0);
12531 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12532 pic16_emitpcode(POC_MOVLW, pcop1);
12533 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12535 pic16_emitpcode(POC_MOVLW, pcop0);
12536 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12539 pic16_freeAsmop(left, NULL, ic, FALSE);
12541 pic16_freeAsmop(result,NULL,ic,TRUE);
12546 /*-----------------------------------------------------------------*/
12547 /* genFarFarAssign - assignment when both are in far space */
12548 /*-----------------------------------------------------------------*/
12549 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12551 int size = AOP_SIZE(right);
12554 /* first push the right side on to the stack */
12556 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12558 pic16_emitcode ("push","acc");
12561 pic16_freeAsmop(right,NULL,ic,FALSE);
12562 /* now assign DPTR to result */
12563 pic16_aopOp(result,ic,FALSE);
12564 size = AOP_SIZE(result);
12566 pic16_emitcode ("pop","acc");
12567 pic16_aopPut(AOP(result),"a",--offset);
12569 pic16_freeAsmop(result,NULL,ic,FALSE);
12574 /*-----------------------------------------------------------------*/
12575 /* genAssign - generate code for assignment */
12576 /*-----------------------------------------------------------------*/
12577 static void genAssign (iCode *ic)
12579 operand *result, *right;
12580 sym_link *restype, *rtype;
12581 int size, offset,know_W;
12582 unsigned long lit = 0L;
12584 result = IC_RESULT(ic);
12585 right = IC_RIGHT(ic) ;
12589 /* if they are the same */
12590 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12593 /* reversed order operands are aopOp'ed so that result operand
12594 * is effective in case right is a stack symbol. This maneauver
12595 * allows to use the _G.resDirect flag later */
12596 pic16_aopOp(result,ic,TRUE);
12597 pic16_aopOp(right,ic,FALSE);
12599 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12601 /* if they are the same registers */
12602 if (pic16_sameRegs(AOP(right),AOP(result)))
12605 /* if the result is a bit */
12606 if (AOP_TYPE(result) == AOP_CRY) {
12607 /* if the right size is a literal then
12608 we know what the value is */
12609 if (AOP_TYPE(right) == AOP_LIT) {
12611 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12612 pic16_popGet(AOP(result),0));
12614 if (((int) operandLitValue(right)))
12615 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12616 AOP(result)->aopu.aop_dir,
12617 AOP(result)->aopu.aop_dir);
12619 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12620 AOP(result)->aopu.aop_dir,
12621 AOP(result)->aopu.aop_dir);
12626 /* the right is also a bit variable */
12627 if (AOP_TYPE(right) == AOP_CRY) {
12628 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12629 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12630 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12635 /* we need to or */
12636 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12637 pic16_toBoolean(right);
12639 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12640 //pic16_aopPut(AOP(result),"a",0);
12644 /* bit variables done */
12646 size = AOP_SIZE(result);
12649 /* bit variables done */
12651 size = AOP_SIZE(result);
12652 restype = operandType(result);
12653 rtype = operandType(right);
12656 if(AOP_TYPE(right) == AOP_LIT) {
12657 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12659 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12661 /* patch tag for literals that are cast to pointers */
12662 if (IS_CODEPTR(restype)) {
12663 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12664 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12666 if (IS_GENPTR(restype))
12668 if (IS_CODEPTR(rtype)) {
12669 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12670 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12671 } else if (PIC_IS_DATA_PTR(rtype)) {
12672 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12673 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12674 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12675 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12676 } else if (IS_PTR(rtype)) {
12677 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12678 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12684 unsigned long lit_int;
12689 if(IS_FIXED16X16(operandType(right))) {
12690 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12692 /* take care if literal is a float */
12693 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12694 lit = info.lit_int;
12699 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12700 // sizeof(unsigned long int), sizeof(float));
12703 if (AOP_TYPE(right) == AOP_REG) {
12704 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12706 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12711 /* when do we have to read the program memory?
12712 * - if right itself is a symbol in code space
12713 * (we don't care what it points to if it's a pointer)
12714 * - AND right is not a function (we would want its address)
12716 if(AOP_TYPE(right) != AOP_LIT
12717 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12718 && !IS_FUNC(OP_SYM_TYPE(right))
12719 && !IS_ITEMP(right)) {
12721 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12722 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12724 // set up table pointer
12725 if(is_LitOp(right)) {
12726 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12727 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12728 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12729 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12730 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12731 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12732 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12734 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12735 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12736 pic16_popCopyReg(&pic16_pc_tblptrl)));
12737 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12738 pic16_popCopyReg(&pic16_pc_tblptrh)));
12739 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12740 pic16_popCopyReg(&pic16_pc_tblptru)));
12743 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12744 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12746 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12747 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12748 pic16_popGet(AOP(result),offset)));
12752 /* FIXME: for pointers we need to extend differently (according
12753 * to pointer type DATA/CODE/EEPROM/... :*/
12754 size = getSize(OP_SYM_TYPE(right));
12755 if(AOP_SIZE(result) > size) {
12756 size = AOP_SIZE(result) - size;
12758 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12766 /* VR - What is this?! */
12767 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12770 if(aopIdx(AOP(result),0) == 4) {
12771 /* this is a workaround to save value of right into wreg too,
12772 * value of wreg is going to be used later */
12773 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12774 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12779 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12783 size = AOP_SIZE(right);
12784 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12787 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12788 if(AOP_TYPE(right) == AOP_LIT) {
12790 if(know_W != (lit&0xff))
12791 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12795 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12799 } else if (AOP_TYPE(right) == AOP_CRY) {
12800 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12802 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12803 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12804 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12806 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12807 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12808 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12812 if(!_G.resDirect) { /* use this aopForSym feature */
12813 if(AOP_TYPE(result) == AOP_ACC) {
12814 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12816 if(AOP_TYPE(right) == AOP_ACC) {
12817 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12819 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12826 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12829 pic16_freeAsmop (right,NULL,ic,FALSE);
12830 pic16_freeAsmop (result,NULL,ic,TRUE);
12833 /*-----------------------------------------------------------------*/
12834 /* genJumpTab - generates code for jump table */
12835 /*-----------------------------------------------------------------*/
12836 static void genJumpTab (iCode *ic)
12841 pCodeOp *jt_offs_hi;
12846 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12847 /* get the condition into accumulator */
12848 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12850 /* multiply by three */
12851 pic16_emitcode("add","a,acc");
12852 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12854 jtab = newiTempLabel(NULL);
12855 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12856 pic16_emitcode("jmp","@a+dptr");
12857 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12860 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12861 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12863 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12864 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12865 pic16_emitpLabel(jtab->key);
12869 jt_offs = pic16_popGetTempReg(0);
12870 jt_offs_hi = pic16_popGetTempReg(1);
12871 jt_label = pic16_popGetLabel (jtab->key);
12872 //fprintf (stderr, "Creating jump table...\n");
12874 // calculate offset into jump table (idx * sizeof (GOTO))
12875 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12876 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12877 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12878 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12879 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12880 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12881 pic16_emitpcode(POC_MOVWF , jt_offs);
12883 // prepare PCLATx (set to first entry in jump table)
12884 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12885 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12886 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12887 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12888 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12890 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12891 pic16_emitpcode(POC_ADDWF , jt_offs);
12892 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12893 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12895 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12897 // release temporaries and prepare jump into table (new PCL --> WREG)
12898 pic16_emitpcode(POC_MOVFW , jt_offs);
12899 pic16_popReleaseTempReg (jt_offs_hi, 1);
12900 pic16_popReleaseTempReg (jt_offs, 0);
12902 // jump into the table
12903 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12905 pic16_emitpLabelFORCE(jtab->key);
12908 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12909 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12911 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12912 /* now generate the jump labels */
12913 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12914 jtab = setNextItem(IC_JTLABELS(ic))) {
12915 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12916 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12919 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12923 /*-----------------------------------------------------------------*/
12924 /* genMixedOperation - gen code for operators between mixed types */
12925 /*-----------------------------------------------------------------*/
12927 TSD - Written for the PIC port - but this unfortunately is buggy.
12928 This routine is good in that it is able to efficiently promote
12929 types to different (larger) sizes. Unfortunately, the temporary
12930 variables that are optimized out by this routine are sometimes
12931 used in other places. So until I know how to really parse the
12932 iCode tree, I'm going to not be using this routine :(.
12934 static int genMixedOperation (iCode *ic)
12937 operand *result = IC_RESULT(ic);
12938 sym_link *ctype = operandType(IC_LEFT(ic));
12939 operand *right = IC_RIGHT(ic);
12945 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12947 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12953 nextright = IC_RIGHT(nextic);
12954 nextleft = IC_LEFT(nextic);
12955 nextresult = IC_RESULT(nextic);
12957 pic16_aopOp(right,ic,FALSE);
12958 pic16_aopOp(result,ic,FALSE);
12959 pic16_aopOp(nextright, nextic, FALSE);
12960 pic16_aopOp(nextleft, nextic, FALSE);
12961 pic16_aopOp(nextresult, nextic, FALSE);
12963 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12965 operand *t = right;
12969 pic16_emitcode(";remove right +","");
12971 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12973 operand *t = right;
12977 pic16_emitcode(";remove left +","");
12981 big = AOP_SIZE(nextleft);
12982 small = AOP_SIZE(nextright);
12984 switch(nextic->op) {
12987 pic16_emitcode(";optimize a +","");
12988 /* if unsigned or not an integral type */
12989 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12990 pic16_emitcode(";add a bit to something","");
12993 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12995 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12996 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12997 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12999 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13007 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13008 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13009 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13012 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13014 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13015 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13016 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13017 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13018 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13021 pic16_emitcode("rlf","known_zero,w");
13028 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13029 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13030 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13032 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13042 pic16_freeAsmop(right,NULL,ic,TRUE);
13043 pic16_freeAsmop(result,NULL,ic,TRUE);
13044 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13045 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13047 nextic->generated = 1;
13054 /*-----------------------------------------------------------------*/
13055 /* genCast - gen code for casting */
13056 /*-----------------------------------------------------------------*/
13057 static void genCast (iCode *ic)
13059 operand *result = IC_RESULT(ic);
13060 sym_link *ctype = operandType(IC_LEFT(ic));
13061 sym_link *rtype = operandType(IC_RIGHT(ic));
13062 sym_link *restype = operandType(IC_RESULT(ic));
13063 operand *right = IC_RIGHT(ic);
13069 /* if they are equivalent then do nothing */
13070 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13073 pic16_aopOp(result,ic,FALSE);
13074 pic16_aopOp(right,ic,FALSE) ;
13076 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13079 /* if the result is a bit */
13080 if (AOP_TYPE(result) == AOP_CRY) {
13082 /* if the right size is a literal then
13083 * we know what the value is */
13084 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13086 if (AOP_TYPE(right) == AOP_LIT) {
13087 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13088 pic16_popGet(AOP(result),0));
13090 if (((int) operandLitValue(right)))
13091 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13092 AOP(result)->aopu.aop_dir,
13093 AOP(result)->aopu.aop_dir);
13095 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13096 AOP(result)->aopu.aop_dir,
13097 AOP(result)->aopu.aop_dir);
13101 /* the right is also a bit variable */
13102 if (AOP_TYPE(right) == AOP_CRY) {
13104 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13106 pic16_emitcode("clrc","");
13107 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13108 AOP(right)->aopu.aop_dir,
13109 AOP(right)->aopu.aop_dir);
13110 pic16_aopPut(AOP(result),"c",0);
13114 /* we need to or */
13115 if (AOP_TYPE(right) == AOP_REG) {
13116 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13117 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13118 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13120 pic16_toBoolean(right);
13121 pic16_aopPut(AOP(result),"a",0);
13125 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13128 size = AOP_SIZE(result);
13130 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13132 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13133 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13134 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13137 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13142 if(IS_BITFIELD(getSpec(restype))
13143 && IS_BITFIELD(getSpec(rtype))) {
13144 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13147 /* port from pic14 to cope with generic pointers */
13148 if (PIC_IS_TAGGED(restype))
13150 operand *result = IC_RESULT(ic);
13151 //operand *left = IC_LEFT(ic);
13152 operand *right = IC_RIGHT(ic);
13155 /* copy common part */
13156 int max, size = AOP_SIZE(result);
13157 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13158 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13163 pic16_mov2w (AOP(right), size);
13164 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13167 /* upcast into generic pointer type? */
13168 if (IS_GENPTR(restype)
13169 && !PIC_IS_TAGGED(rtype)
13170 && (AOP_SIZE(result) > max))
13172 /* determine appropriate tag for right */
13173 if (PIC_IS_DATA_PTR(rtype))
13174 tag = GPTR_TAG_DATA;
13175 else if (IS_CODEPTR(rtype))
13176 tag = GPTR_TAG_CODE;
13177 else if (PIC_IS_DATA_PTR(ctype)) {
13178 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13179 tag = GPTR_TAG_DATA;
13180 } else if (IS_CODEPTR(ctype)) {
13181 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13182 tag = GPTR_TAG_CODE;
13183 } else if (IS_PTR(rtype)) {
13184 PERFORM_ONCE(weirdcast,
13185 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13187 tag = GPTR_TAG_DATA;
13189 PERFORM_ONCE(weirdcast,
13190 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13192 tag = GPTR_TAG_DATA;
13195 assert (AOP_SIZE(result) == 3);
13196 /* zero-extend address... */
13197 for (size = max; size < AOP_SIZE(result)-1; size++)
13198 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13199 /* ...and add tag */
13200 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13201 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13202 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13203 for (size = max; size < AOP_SIZE(result)-1; size++)
13204 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13205 /* add __code tag */
13206 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13207 } else if (AOP_SIZE(result) > max) {
13208 /* extend non-pointers */
13209 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13210 pic16_addSign(result, max, 0);
13215 /* if they are the same size : or less */
13216 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13218 /* if they are in the same place */
13219 if (pic16_sameRegs(AOP(right),AOP(result)))
13222 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13224 if (IS_PTR_CONST(rtype))
13226 if (IS_CODEPTR(rtype))
13228 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13231 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13233 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13235 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13238 if(AOP_TYPE(right) == AOP_IMMD) {
13239 pCodeOp *pcop0, *pcop1, *pcop2;
13240 symbol *sym = OP_SYMBOL( right );
13242 size = AOP_SIZE(result);
13244 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13246 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13248 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13251 pic16_emitpcode(POC_MOVLW, pcop0);
13252 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13253 pic16_emitpcode(POC_MOVLW, pcop1);
13254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13255 pic16_emitpcode(POC_MOVLW, pcop2);
13256 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13259 pic16_emitpcode(POC_MOVLW, pcop0);
13260 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13261 pic16_emitpcode(POC_MOVLW, pcop1);
13262 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13264 pic16_emitpcode(POC_MOVLW, pcop0);
13265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13269 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13270 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13271 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13273 if(AOP_SIZE(result) < 2) {
13274 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13276 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13277 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13280 /* if they in different places then copy */
13281 size = AOP_SIZE(result);
13284 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13285 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13292 /* if the result is of type pointer */
13293 if (IS_PTR(ctype)) {
13295 sym_link *type = operandType(right);
13296 sym_link *etype = getSpec(type);
13298 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13300 /* pointer to generic pointer */
13301 if (IS_GENPTR(ctype)) {
13305 p_type = DCL_TYPE(type);
13307 /* we have to go by the storage class */
13308 p_type = PTR_TYPE(SPEC_OCLS(etype));
13310 /* if (SPEC_OCLS(etype)->codesp ) */
13311 /* p_type = CPOINTER ; */
13313 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13314 /* p_type = FPOINTER ; */
13316 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13317 /* p_type = PPOINTER; */
13319 /* if (SPEC_OCLS(etype) == idata ) */
13320 /* p_type = IPOINTER ; */
13322 /* p_type = POINTER ; */
13325 /* the first two bytes are known */
13326 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13327 size = GPTRSIZE - 1;
13330 if(offset < AOP_SIZE(right)) {
13331 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13332 pic16_mov2f(AOP(result), AOP(right), offset);
13334 if ((AOP_TYPE(right) == AOP_PCODE) &&
13335 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13336 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13337 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13340 pic16_aopPut(AOP(result),
13341 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13346 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13349 /* the last byte depending on type */
13354 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13358 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13362 pic16_emitcode(";BUG!? ","%d",__LINE__);
13367 if (GPTRSIZE > AOP_SIZE(right)) {
13368 // assume __data pointer... THIS MIGHT BE WRONG!
13369 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13371 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13376 /* this should never happen */
13377 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13378 "got unknown pointer type");
13381 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13387 /* just copy the pointers */
13388 size = AOP_SIZE(result);
13391 pic16_aopPut(AOP(result),
13392 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13401 /* so we now know that the size of destination is greater
13402 than the size of the source.
13403 Now, if the next iCode is an operator then we might be
13404 able to optimize the operation without performing a cast.
13406 if(genMixedOperation(ic))
13409 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13411 /* we move to result for the size of source */
13412 size = AOP_SIZE(right);
13417 pic16_mov2f(AOP(result), AOP(right), offset);
13421 /* now depending on the sign of the destination */
13422 size = AOP_SIZE(result) - AOP_SIZE(right);
13423 /* if unsigned or not an integral type */
13424 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13426 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13428 /* we need to extend the sign :( */
13431 /* Save one instruction of casting char to int */
13432 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13433 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13434 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13436 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13439 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13441 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13443 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13446 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13451 pic16_freeAsmop(right,NULL,ic,TRUE);
13452 pic16_freeAsmop(result,NULL,ic,TRUE);
13456 /*-----------------------------------------------------------------*/
13457 /* genDjnz - generate decrement & jump if not zero instrucion */
13458 /*-----------------------------------------------------------------*/
13459 static int genDjnz (iCode *ic, iCode *ifx)
13461 symbol *lbl, *lbl1;
13462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13467 /* if the if condition has a false label
13468 then we cannot save */
13472 /* if the minus is not of the form
13474 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13475 !IS_OP_LITERAL(IC_RIGHT(ic)))
13478 if (operandLitValue(IC_RIGHT(ic)) != 1)
13481 /* if the size of this greater than one then no
13483 if (getSize(operandType(IC_RESULT(ic))) > 1)
13486 /* otherwise we can save BIG */
13487 lbl = newiTempLabel(NULL);
13488 lbl1= newiTempLabel(NULL);
13490 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13492 if (IS_AOP_PREG(IC_RESULT(ic))) {
13493 pic16_emitcode("dec","%s",
13494 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13495 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13496 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13500 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13501 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13503 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13504 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13508 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13509 ifx->generated = 1;
13513 /*-----------------------------------------------------------------*/
13514 /* genReceive - generate code for a receive iCode */
13515 /*-----------------------------------------------------------------*/
13516 static void genReceive (iCode *ic)
13522 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13523 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13525 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13527 if (isOperandInFarSpace(IC_RESULT(ic))
13528 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13529 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13531 int size = getSize(operandType(IC_RESULT(ic)));
13532 int offset = pic16_fReturnSizePic - size;
13536 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13537 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13541 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13543 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13544 size = AOP_SIZE(IC_RESULT(ic));
13547 pic16_emitcode ("pop","acc");
13548 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13551 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13553 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13556 /* set pseudo stack pointer to where it should be - dw*/
13557 GpsuedoStkPtr = ic->parmBytes;
13559 /* setting GpsuedoStkPtr has side effects here: */
13560 /* FIXME: What's the correct size of the return(ed) value?
13561 * For now, assuming '4' as before... */
13562 assignResultValue(IC_RESULT(ic), 4, 0);
13565 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13568 /*-----------------------------------------------------------------*/
13569 /* genDummyRead - generate code for dummy read of volatiles */
13570 /*-----------------------------------------------------------------*/
13572 genDummyRead (iCode * ic)
13578 if (op && IS_SYMOP(op)) {
13579 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13580 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13583 pic16_aopOp (op, ic, FALSE);
13584 for (i=0; i < AOP_SIZE(op); i++) {
13585 // may need to protect this from the peepholer -- this is not nice but works...
13586 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13587 pic16_mov2w (AOP(op),i);
13588 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13590 pic16_freeAsmop (op, NULL, ic, TRUE);
13592 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13596 /*-----------------------------------------------------------------*/
13597 /* genpic16Code - generate code for pic16 based controllers */
13598 /*-----------------------------------------------------------------*/
13600 * At this point, ralloc.c has gone through the iCode and attempted
13601 * to optimize in a way suitable for a PIC. Now we've got to generate
13602 * PIC instructions that correspond to the iCode.
13604 * Once the instructions are generated, we'll pass through both the
13605 * peep hole optimizer and the pCode optimizer.
13606 *-----------------------------------------------------------------*/
13608 void genpic16Code (iCode *lic)
13613 lineHead = lineCurr = NULL;
13615 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13616 pic16_addpBlock(pb);
13619 /* if debug information required */
13620 if (options.debug && currFunc) {
13622 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13627 for (ic = lic ; ic ; ic = ic->next ) {
13629 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13630 if ( cln != ic->lineno ) {
13631 if ( options.debug ) {
13632 debugFile->writeCLine (ic);
13635 if(!options.noCcodeInAsm) {
13636 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13637 printCLine(ic->filename, ic->lineno)));
13643 if(options.iCodeInAsm) {
13646 /* insert here code to print iCode as comment */
13647 iLine = printILine(ic);
13648 pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13652 /* if the result is marked as
13653 * spilt and rematerializable or code for
13654 * this has already been generated then
13656 if (resultRemat(ic) || ic->generated )
13659 /* depending on the operation */
13678 /* IPOP happens only when trying to restore a
13679 * spilt live range, if there is an ifx statement
13680 * following this pop then the if statement might
13681 * be using some of the registers being popped which
13682 * would destroy the contents of the register so
13683 * we need to check for this condition and handle it */
13685 && ic->next->op == IFX
13686 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13687 genIfx (ic->next,ic);
13705 genEndFunction (ic);
13721 pic16_genPlus (ic) ;
13725 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13726 pic16_genMinus (ic);
13742 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13746 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13752 /* note these two are xlated by algebraic equivalence
13753 * during parsing SDCC.y */
13754 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13755 "got '>=' or '<=' shouldn't have come here");
13759 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13771 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13775 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13779 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13803 genRightShift (ic);
13806 case GET_VALUE_AT_ADDRESS:
13811 if (POINTER_SET(ic))
13838 addSet(&_G.sendSet,ic);
13841 case DUMMY_READ_VOLATILE:
13851 /* now we are ready to call the
13852 peep hole optimizer */
13853 if (!options.nopeep)
13854 peepHole (&lineHead);
13856 /* now do the actual printing */
13857 printLine (lineHead, codeOutBuf);
13860 DFPRINTF((stderr,"printing pBlock\n\n"));
13861 pic16_printpBlock(stdout,pb);